From 21dae515b3340a7d43d785040d4e106d3a012efd Mon Sep 17 00:00:00 2001 From: Kevin Bond Date: Wed, 21 Feb 2024 21:12:35 -0500 Subject: [PATCH] [Twig] `ComponentAttributes::append()/prepend()` --- src/TwigComponent/CHANGELOG.md | 5 +++ src/TwigComponent/doc/index.rst | 19 +++++++---- src/TwigComponent/src/ComponentAttributes.php | 14 ++++++-- .../components/RenderAttributes.html.twig | 11 +++--- .../Integration/ComponentExtensionTest.php | 34 ++++++++++++------- .../tests/Unit/ComponentAttributesTest.php | 23 +++++++------ 6 files changed, 70 insertions(+), 36 deletions(-) diff --git a/src/TwigComponent/CHANGELOG.md b/src/TwigComponent/CHANGELOG.md index f3cc736248..76fdcda6f9 100644 --- a/src/TwigComponent/CHANGELOG.md +++ b/src/TwigComponent/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGELOG +## 2.16.0 + +- Add default value to `ComponentAttributes::render()` #1531 +- Add `ComponentAttributes::append()/prepend()` #1531 + ## 2.15.0 - Add the ability to render specific attributes from the `attributes` variable #1442 diff --git a/src/TwigComponent/doc/index.rst b/src/TwigComponent/doc/index.rst index 72e93491ac..6fde2f2a3d 100644 --- a/src/TwigComponent/doc/index.rst +++ b/src/TwigComponent/doc/index.rst @@ -952,14 +952,21 @@ Render The ability to *render* attributes was added in TwigComponents 2.15. +.. versionadded:: 2.16 + + The ability to *render* attributes with a default, *prepend*, and *append* were + added in TwigComponents 2.16. + You can take full control over the attributes that are rendered by using the -``render()`` method. +``render()``, ``prepend()``, and ``append()`` methods. .. code-block:: html+twig {# templates/components/MyComponent.html.twig #}
My Component! @@ -969,15 +976,15 @@ You can take full control over the attributes that are rendered by using the {{ component('MyComponent', { style: 'color:red;' }) }} {# renders as: #} -
+
My Component!
.. caution:: - There are a few important things to know about using ``render()``: + There are a few important things to know about using ``render()``/``prepend()``/``append()``: - 1. You need to be sure to call your ``render()`` methods before calling ``{{ attributes }}`` or some + 1. You need to be sure to call these methods before calling ``{{ attributes }}`` or some attributes could be rendered twice. For instance: .. code-block:: html+twig @@ -998,7 +1005,7 @@ You can take full control over the attributes that are rendered by using the My Component!
- 2. If you add an attribute without calling ``render()``, it will be rendered twice. For instance: + 2. If you add an attribute without calling these methods, it will be rendered twice. For instance: .. code-block:: html+twig diff --git a/src/TwigComponent/src/ComponentAttributes.php b/src/TwigComponent/src/ComponentAttributes.php index 8b7d10a060..f3144505d2 100644 --- a/src/TwigComponent/src/ComponentAttributes.php +++ b/src/TwigComponent/src/ComponentAttributes.php @@ -65,10 +65,10 @@ public function __clone(): void $this->rendered = []; } - public function render(string $attribute): ?string + public function render(string $attribute, ?string $default = null): ?string { if (null === $value = $this->attributes[$attribute] ?? null) { - return null; + return $default; } if (!\is_string($value)) { @@ -80,6 +80,16 @@ public function render(string $attribute): ?string return $value; } + public function prepend(string $attribute, string $value, string $separator = ' '): string + { + return trim(sprintf('%s%s%s', $value, $separator, $this->render($attribute))); + } + + public function append(string $attribute, string $value, string $separator = ' '): string + { + return trim(sprintf('%s%s%s', $this->render($attribute), $separator, $value)); + } + /** * @return array */ diff --git a/src/TwigComponent/tests/Fixtures/templates/components/RenderAttributes.html.twig b/src/TwigComponent/tests/Fixtures/templates/components/RenderAttributes.html.twig index 59f132689c..a77b7f5d42 100644 --- a/src/TwigComponent/tests/Fixtures/templates/components/RenderAttributes.html.twig +++ b/src/TwigComponent/tests/Fixtures/templates/components/RenderAttributes.html.twig @@ -1,7 +1,10 @@
diff --git a/src/TwigComponent/tests/Integration/ComponentExtensionTest.php b/src/TwigComponent/tests/Integration/ComponentExtensionTest.php index ff891610c5..4eb772f91b 100644 --- a/src/TwigComponent/tests/Integration/ComponentExtensionTest.php +++ b/src/TwigComponent/tests/Integration/ComponentExtensionTest.php @@ -14,7 +14,6 @@ use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Symfony\UX\TwigComponent\Tests\Fixtures\User; use Twig\Environment; -use Twig\Error\RuntimeError; /** * @author Kevin Bond @@ -228,10 +227,13 @@ public static function renderingAttributesManuallyProvider(): iterable ['class' => 'block'], << HTML, @@ -240,17 +242,23 @@ class="block" yield [ [ 'class' => 'block', - 'foo' => 'value', - 'bar' => 'value', - 'baz' => 'value', - 'qux' => 'value', + 'attr1' => 'value1', + 'attr2' => 'value2', + 'attr3' => 'value3', + 'attr4' => 'value4', + 'attr5' => 'value5', + 'attr6' => 'value6', + 'attr7' => 'value7', ], << HTML, diff --git a/src/TwigComponent/tests/Unit/ComponentAttributesTest.php b/src/TwigComponent/tests/Unit/ComponentAttributesTest.php index 7cad387a28..e1cf676b0a 100644 --- a/src/TwigComponent/tests/Unit/ComponentAttributesTest.php +++ b/src/TwigComponent/tests/Unit/ComponentAttributesTest.php @@ -200,20 +200,21 @@ public function testIsTraversableAndCountable(): void $this->assertCount(1, $attributes); } - public function testRenderSingleAttribute(): void + public function testRenderAttributes(): void { - $attributes = new ComponentAttributes(['attr1' => 'value1', 'attr2' => 'value2']); - - $this->assertSame('value1', $attributes->render('attr1')); - $this->assertNull($attributes->render('attr3')); - } - - public function testRenderingSingleAttributeExcludesFromString(): void - { - $attributes = new ComponentAttributes(['attr1' => 'value1', 'attr2' => 'value2']); + $attributes = new ComponentAttributes([ + 'attr1' => 'value1', + 'attr2' => 'value2', + 'attr3' => 'value3', + 'attr4' => 'value4', + ]); $this->assertSame('value1', $attributes->render('attr1')); - $this->assertSame(' attr2="value2"', (string) $attributes); + $this->assertSame('default value2', $attributes->prepend('attr2', 'default')); + $this->assertSame('value3 default', $attributes->append('attr3', 'default')); + $this->assertNull($attributes->render('attr5')); + $this->assertSame('default', $attributes->render('attr5', 'default')); + $this->assertSame(' attr4="value4"', (string) $attributes); } public function testCannotRenderNonStringAttribute(): void