Skip to content

Commit 35f85e9

Browse files
authored
feat(view): improve boolean attributes (#1111)
1 parent 0b824b6 commit 35f85e9

File tree

6 files changed

+62
-81
lines changed

6 files changed

+62
-81
lines changed

src/Tempest/View/src/Attributes/AttributeFactory.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,17 @@
55
namespace Tempest\View\Attributes;
66

77
use Tempest\View\Attribute;
8-
use Tempest\View\Element;
98

109
final readonly class AttributeFactory
1110
{
12-
public function make(Element $element, string $attributeName): Attribute
11+
public function make(string $attributeName): Attribute
1312
{
1413
return match (true) {
1514
$attributeName === ':if' => new IfAttribute(),
1615
$attributeName === ':elseif' => new ElseIfAttribute(),
1716
$attributeName === ':else' => new ElseAttribute(),
1817
$attributeName === ':foreach' => new ForeachAttribute(),
1918
$attributeName === ':forelse' => new ForelseAttribute(),
20-
BooleanAttribute::matches($element, $attributeName) => new BooleanAttribute($attributeName),
2119
str_starts_with($attributeName, ':') => new ExpressionAttribute($attributeName),
2220
default => new DataAttribute($attributeName),
2321
};

src/Tempest/View/src/Attributes/BooleanAttribute.php

Lines changed: 0 additions & 75 deletions
This file was deleted.

src/Tempest/View/src/Elements/GenericElement.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public function compile(): string
6666

6767
if ($attributes !== '') {
6868
$attributes = ' ' . $attributes;
69+
$attributes = str_replace('?> <?php', '?><?php', $attributes);
6970
}
7071

7172
// Void elements

src/Tempest/View/src/Elements/PhpDataElement.php

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44

55
namespace Tempest\View\Elements;
66

7-
use Stringable;
87
use Tempest\View\Element;
9-
use Tempest\View\Renderers\TempestViewCompiler;
108
use Tempest\View\WrapsElement;
119

1210
use function Tempest\Support\str;
@@ -49,6 +47,25 @@ public function compile(): string
4947
$name,
5048
);
5149

50+
// Support for boolean attributes. When an expression attribute has a falsy value, it won't be rendered at all.
51+
// When it's "true", it will only render the attribute name and not the "true" value
52+
$coreElement = $this->unwrap(GenericElement::class);
53+
54+
if ($isExpression && $coreElement instanceof GenericElement) {
55+
$coreElement
56+
->addRawAttribute(
57+
sprintf(
58+
'<?php if($%s === true) {?>%s<?php } elseif($%s) { ?>%s="%s"<?php } ?>',
59+
$name,
60+
str($name)->kebab(),
61+
$name,
62+
str($name)->kebab(),
63+
$coreElement->getAttribute($name),
64+
),
65+
)
66+
->unsetAttribute($name);
67+
}
68+
5269
return sprintf(
5370
'<?php %s ?>
5471
%s

src/Tempest/View/src/Renderers/TempestViewCompiler.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ private function applyAttributes(array $elements): array
195195
->setChildren($children);
196196

197197
foreach ($element->getAttributes() as $name => $value) {
198-
$attribute = $this->attributeFactory->make($element, $name);
198+
$attribute = $this->attributeFactory->make($name);
199199

200200
$element = $attribute->apply($element);
201201

tests/Integration/View/TempestViewRendererDataPassingTest.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Tests\Tempest\Integration\View;
66

7+
use PHPUnit\Framework\Attributes\TestWith;
78
use Tempest\View\Exceptions\InvalidExpressionAttribute;
89
use Tempest\View\ViewCache;
910
use Tests\Tempest\Integration\FrameworkIntegrationTestCase;
@@ -267,6 +268,45 @@ public function test_boolean_attributes(): void
267268
);
268269
}
269270

271+
#[TestWith(['false'])]
272+
#[TestWith(['null'])]
273+
#[TestWith(['0'])]
274+
#[TestWith(['$show'])]
275+
public function test_falsy_bool_attribute(mixed $value): void
276+
{
277+
$html = $this->render(<<<HTML
278+
<div :data-active="{$value}"></div>
279+
HTML, show: false);
280+
281+
$this->assertStringEqualsStringIgnoringLineEndings(<<<'HTML'
282+
<div ></div>
283+
HTML, $html);
284+
}
285+
286+
#[TestWith(['true'])]
287+
#[TestWith(['$show'])]
288+
public function test_truthy_bool_attribute(mixed $value): void
289+
{
290+
$html = $this->render(<<<HTML
291+
<div :data-active="{$value}"></div>
292+
HTML, show: true);
293+
294+
$this->assertStringEqualsStringIgnoringLineEndings(<<<'HTML'
295+
<div data-active></div>
296+
HTML, $html);
297+
}
298+
299+
public function test_multiple_boolean_attribute(): void
300+
{
301+
$html = $this->render(<<<HTML
302+
<div :data-a="false" :data-b="false" :data-c="true"></div>
303+
HTML);
304+
305+
$this->assertStringEqualsStringIgnoringLineEndings(<<<'HTML'
306+
<div data-c></div>
307+
HTML, $html);
308+
}
309+
270310
public function test_expression_attribute_in_raw_element(): void
271311
{
272312
$this->registerViewComponent(

0 commit comments

Comments
 (0)