Skip to content

Commit 6c7dfae

Browse files
authored
feat(view): access view component attributes (#1008)
1 parent a5fd85c commit 6c7dfae

File tree

5 files changed

+57
-13
lines changed

5 files changed

+57
-13
lines changed

src/Tempest/Support/tests/JavaScript/PackageManagerTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public function test_can_detect_package_manager(string $fixture, ?PackageManager
2727
actual: PackageManager::detect(cwd: __DIR__ . "/Fixtures/{$fixture}"),
2828
);
2929
}
30+
3031
#[TestWith(['bun-lock', 'bun dev'])]
3132
#[TestWith(['bun-lockb', 'bun dev'])]
3233
#[TestWith(['npm', 'npm run dev'])]

src/Tempest/View/src/Attributes/DataAttribute.php

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,9 @@ public function apply(Element $element): Element
2323
{
2424
$value = str($element->getAttribute($this->name));
2525

26-
// Render {{ and {!! tags
27-
if ($value->startsWith(['{{', '{!!']) && $value->endsWith(['}}', '!!}'])) {
28-
$value = new TextElement($value->toString())->compile();
29-
$element->setAttribute($this->name, $value);
30-
}
26+
$value = new TextElement($value->toString())->compile();
27+
28+
$element->setAttribute($this->name, $value);
3129

3230
// Data attributes should only be parsed for view components
3331
if ($element->unwrap(ViewComponentElement::class) === null) {

src/Tempest/View/src/Elements/ViewComponentElement.php

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,18 @@ final class ViewComponentElement implements Element
1717
{
1818
use IsElement;
1919

20+
private array $dataAttributes = [];
21+
2022
public function __construct(
2123
private readonly Environment $environment,
2224
private readonly TempestViewCompiler $compiler,
2325
private readonly ViewComponent $viewComponent,
2426
array $attributes,
2527
) {
2628
$this->attributes = $attributes;
29+
$this->dataAttributes = arr($attributes)
30+
->filter(fn ($value, $key) => ! str_starts_with($key, ':'))
31+
->toArray();
2732
}
2833

2934
public function getViewComponent(): ViewComponent
@@ -84,16 +89,25 @@ public function compile(): string
8489
->toArray();
8590

8691
$compiled = str($this->viewComponent->compile($this))
87-
// Add dynamic slots to the current scope
8892
->prepend(
93+
// Add attributes to the current scope
94+
'<?php $_previousAttributes = $attributes ?? null; ?>',
95+
sprintf('<?php $attributes = \Tempest\Support\arr(%s); ?>', var_export($this->dataAttributes, true)), // @mago-expect best-practices/no-debug-symbols Set the new value of $attributes for this view component
96+
97+
// Add dynamic slots to the current scope
8998
'<?php $_previousSlots = $slots ?? null; ?>', // Store previous slots in temporary variable to keep scope
90-
sprintf('<?php $slots = %s; ?>', var_export($slots, true)), // @mago-expect best-practices/no-debug-symbols Set the new value of $slots for this view component
99+
sprintf('<?php $slots = \Tempest\Support\arr(%s); ?>', var_export($slots, true)), // @mago-expect best-practices/no-debug-symbols Set the new value of $slots for this view component
91100
)
92-
// Cleanup slots after the view component and restore slots from previous scope
93101
->append(
94-
'<?php unset($slots); ?>', // Unset current $slots
95-
'<?php $slots = $_previousSlots ?? null; ?>', // Restore previous $slots
96-
'<?php unset($_previousSlots); ?>', // Cleanup temporary $_previousSlots
102+
// Restore previous slots
103+
'<?php unset($slots); ?>',
104+
'<?php $slots = $_previousSlots ?? null; ?>',
105+
'<?php unset($_previousSlots); ?>',
106+
107+
// Restore previous attributes
108+
'<?php unset($attributes); ?>',
109+
'<?php $attributes = $_previousAttributes ?? null; ?>',
110+
'<?php unset($_previousAttributes); ?>',
97111
)
98112
// Compile slots
99113
->replaceRegex(

tests/Integration/View/TempestViewRendererDataPassingTest.php

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ public function test_boolean_attributes(): void
264264

265265
$this->assertSame(
266266
'<textarea autofocus></textarea>',
267-
$this->render('<textarea autofocus></textarea>')
267+
$this->render('<textarea autofocus></textarea>'),
268268
);
269269
}
270270

@@ -290,4 +290,21 @@ public function test_expression_attribute_in_raw_element(): void
290290
$html,
291291
);
292292
}
293+
294+
public function test_echo_in_attributes(): void
295+
{
296+
$this->assertSame(
297+
'<div class="hi hi hi"></div>',
298+
$this->render(<<<HTML
299+
<div class="hi {{ 'hi' }} hi">
300+
HTML),
301+
);
302+
303+
$this->assertSame(
304+
'<div class="hi hi hi"></div>',
305+
$this->render(<<<HTML
306+
<div class="hi {!! 'hi' !!} hi">
307+
HTML),
308+
);
309+
}
293310
}

tests/Integration/View/ViewComponentTest.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,6 @@ public function test_custom_components_in_head(): void
547547
HTML, $html);
548548
}
549549

550-
551550
public function test_head_injection(): void
552551
{
553552
$this->registerViewComponent('x-custom-link', <<<'HTML'
@@ -574,4 +573,19 @@ public function test_head_injection(): void
574573
</body></html>
575574
HTML, $html);
576575
}
576+
577+
public function test_attributes_variable_in_view_component(): void
578+
{
579+
$this->registerViewComponent('x-test', <<<'HTML'
580+
<div class="foo {{ $attributes['class'] }}" style="font-weight: bold; {{ $attributes['style'] }}"></div>
581+
HTML);
582+
583+
$html = $this->render(<<<'HTML'
584+
<x-test class="baz" style="text-decoration: underline;"></x-test>
585+
HTML);
586+
587+
$this->assertStringEqualsStringIgnoringLineEndings(<<<'HTML'
588+
<div class="foo baz" style="font-weight: bold; text-decoration: underline;"></div>
589+
HTML, $html);
590+
}
577591
}

0 commit comments

Comments
 (0)