diff --git a/packages/view/src/Components/x-component.view.php b/packages/view/src/Components/x-component.view.php index c35181f9d..fdd0cf954 100644 --- a/packages/view/src/Components/x-component.view.php +++ b/packages/view/src/Components/x-component.view.php @@ -10,9 +10,20 @@ use function Tempest\Container\get; use function Tempest\View\view; -$attributeString = $attributes - ->map(fn (string $value, string $key) => "{$key}=\"{$value}\"") - ->implode(' '); +$htmlAttributes = []; +$dataVariables = []; + +foreach ($attributes as $key => $value) { + if (is_object($value) || is_array($value)) { + $dataVariables[$key] = $value; + } elseif ($value === true) { + $htmlAttributes[] = $key; + } elseif ($value !== false && $value !== null) { + $htmlAttributes[] = "{$key}=\"{$value}\""; + } +} + +$attributeString = implode(' ', $htmlAttributes); $content = $slots[Slot::DEFAULT]->content ?? ''; @@ -24,6 +35,7 @@ $data = $scopedVariables ?? $_data ?? []; $data = is_array($data) ? $data : []; +$data = array_merge($data, $dataVariables); $html = get(TempestViewRenderer::class)->render(view($template, ...$data)); ?> diff --git a/tests/Integration/View/ViewComponentTest.php b/tests/Integration/View/ViewComponentTest.php index e39194e2c..ca32b886b 100644 --- a/tests/Integration/View/ViewComponentTest.php +++ b/tests/Integration/View/ViewComponentTest.php @@ -870,6 +870,43 @@ public function test_dynamic_view_component_with_variable_attribute(): void $this->assertSame('
test
', $html); } + public function test_dynamic_view_component_with_object_attribute_forwarded_as_data(): void + { + $this->view->registerViewComponent('x-field', ''); + + $field = new class { + public string $label = 'Email'; + }; + + $html = $this->view->render(<<<'HTML' + + HTML, field: $field); + + $this->assertSame('', $html); + } + + public function test_dynamic_view_component_with_boolean_true_renders_bare_attribute(): void + { + $this->view->registerViewComponent('x-test', '{{ isset($disabled) ? "yes" : "no" }}'); + + $html = $this->view->render(<<<'HTML' + + HTML); + + $this->assertSame('yes', $html); + } + + public function test_dynamic_view_component_with_boolean_false_omits_attribute(): void + { + $this->view->registerViewComponent('x-test', '{{ isset($disabled) ? "yes" : "no" }}'); + + $html = $this->view->render(<<<'HTML' + + HTML); + + $this->assertSame('no', $html); + } + public function test_dynamic_view_component_with_slot(): void { $this->view->registerViewComponent('x-test', '
');