Skip to content

Commit 1af3b23

Browse files
authored
feat(view): add :isset attribte (#1675)
1 parent c760b2d commit 1af3b23

File tree

6 files changed

+72
-5
lines changed

6 files changed

+72
-5
lines changed

docs/1-essentials/02-views.md

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ Apart from HTMLs boolean attributes, the same syntax can be used with any expres
177177

178178
### Control flow directives
179179

180-
#### `:if`, `:elseif` and `:else`
180+
#### `:if`, `:elseif`, and `:else`
181181

182182
The `:if` directive can conditionally render the element it is attached to, depending on the result of its expression. Similarly, the `:elseif` and `:else` directives can be used on direct siblings for additional control.
183183

@@ -186,6 +186,21 @@ The `:if` directive can conditionally render the element it is attached to, depe
186186
<span :else>Import {{ $this->pendingUploads->count() }} file(s)</span>
187187
```
188188

189+
#### `:isset`
190+
191+
The `:isset` directive can be used to conditionally render the element it is attached to, depending on the existence of a variable.
192+
193+
```html
194+
<h1 :isset="$title">{{ $title }}</h1>
195+
```
196+
197+
Since `:isset` is a shorthand for `:if="isset()"`, it can be combined with `:elseif` and `:else`:
198+
199+
```html
200+
<h1 :isset="$title">{{ $title }}</h1>
201+
<h1 :else>Title</h1>
202+
```
203+
189204
#### `:foreach` and `:{:hl-keyword:forelse:}`
190205

191206
The `:foreach` directive may be used to render the associated element multiple times based on the result of its expression. Combined with `:{:hl-keyword:forelse:}`, an empty state can be displayed when the data is empty.
@@ -230,7 +245,7 @@ To create a view component, create a `.view.php` file that starts with `x-`. The
230245
```html app/x-base.view.php
231246
<html lang="en">
232247
<head>
233-
<title :if="$title">{{ $title }} — AirAcme</title>
248+
<title :if="$title ?? null">{{ $title }} — AirAcme</title>
234249
<title :else>AirAcme</title>
235250
</head>
236251
<body>
@@ -265,7 +280,7 @@ Attributes and [expression attributes](#expression-attributes) may be passed int
265280

266281
```html x-base.view.php
267282
// ...
268-
<title :if="$title">{{ $title }}</title>
283+
<title :if="$title ?? null">{{ $title }}</title>
269284
```
270285

271286
Note that the casing of attributes will affect the associated variable name:

docs/4-internals/03-view-spec.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Some frontend frameworks also provide a `{html}:{:hl-property:attribute:}` synta
2727

2828
### Control structures
2929

30-
Control structures like conditionals and loops are modelled with expression attributes. These control structure attributes are available: `{html}:{:hl-property:if:}`, `{html}:{:hl-property:elseif:}`, `{html}:{:hl-property:else:}`, `{html}:{:hl-property:foreach:}`, `{html}:{:hl-property:forelse:}`. Code within these control structures is compiled to valid PHP expressions.
30+
Control structures like conditionals and loops are modelled with expression attributes. These control structure attributes are available: `{html}:{:hl-property:if:}`, `{html}:{:hl-property:elseif:}`, `{html}:{:hl-property:else:}`, {:hl-property:isset:}`, `{html}:{:hl-property:foreach:}`, `{html}:{:hl-property:forelse:}`. Code within these control structures is compiled to valid PHP expressions.
3131

3232
The following conditional:
3333

packages/view/src/Attributes/AttributeFactory.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public function make(string $attributeName): Attribute
1212
{
1313
return match (true) {
1414
$attributeName === ':if' => new IfAttribute(),
15+
$attributeName === ':isset' => new IssetAttribute(),
1516
$attributeName === ':elseif' => new ElseIfAttribute(),
1617
$attributeName === ':else' => new ElseAttribute(),
1718
$attributeName === ':foreach' => new ForeachAttribute(),
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\View\Attributes;
6+
7+
use Tempest\View\Attribute;
8+
use Tempest\View\Element;
9+
use Tempest\View\Elements\PhpIfElement;
10+
11+
final readonly class IssetAttribute implements Attribute
12+
{
13+
public function apply(Element $element): Element
14+
{
15+
return new PhpIfElement($element);
16+
}
17+
}

packages/view/src/Elements/PhpIfElement.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,16 @@ public function setElse(Element $element): self
4646

4747
public function compile(): string
4848
{
49+
if ($condition = $this->wrappingElement->consumeAttribute(':isset')) {
50+
$condition = sprintf('isset(%s)', $condition);
51+
} else {
52+
$condition = $this->wrappingElement->consumeAttribute(':if');
53+
}
54+
4955
$compiled = sprintf(
5056
'<?php if(%s): ?>
5157
%s',
52-
$this->wrappingElement->consumeAttribute(':if'),
58+
$condition,
5359
$this->wrappingElement->compile(),
5460
);
5561

tests/Integration/View/TempestViewRendererTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,34 @@ public function test_if_attribute(): void
7878
);
7979
}
8080

81+
public function test_isset_attribute(): void
82+
{
83+
$this->assertSame(
84+
'',
85+
$this->render(view('<div :isset="$foo">Hello</div>')),
86+
);
87+
88+
$this->assertSame(
89+
'<div>else</div>',
90+
$this->render(view('<div :isset="$foo">Hello</div><div :else>else</div>')),
91+
);
92+
93+
$this->assertSame(
94+
'<div>elseif</div>',
95+
$this->render(view('<div :isset="$foo">Hello</div><div :elseif="true">elseif</div><div :else>else</div>')),
96+
);
97+
98+
$this->assertSame(
99+
'<div>else</div>',
100+
$this->render(view('<div :isset="$foo">Hello</div><div :elseif="false">elseif</div><div :else>else</div>')),
101+
);
102+
103+
$this->assertSame(
104+
'<div>Hello</div>',
105+
$this->render(view('<div :isset="$foo">Hello</div>', foo: true)),
106+
);
107+
}
108+
81109
public function test_if_with_other_expression_attributes(): void
82110
{
83111
$html = $this->render('<div :if="$this->show" :data="$data">Hello</div>', show: true, data: 'test');

0 commit comments

Comments
 (0)