diff --git a/README.md b/README.md index 81a5e3e7..e582536f 100644 --- a/README.md +++ b/README.md @@ -204,7 +204,7 @@ class ScriptNonceSubscriber implements EventSubscriberInterface ### stimulus_controller This bundle also ships with a special `stimulus_controller()` Twig function -that can be used to render [Stimulus Controllers & Values](https://stimulus.hotwired.dev/reference/values) +that can be used to render [Stimulus Controllers & Values](https://stimulus.hotwired.dev/reference/values), [Outlets](https://stimulus.hotwired.dev/reference/outlets) and [CSS Classes](https://stimulus.hotwired.dev/reference/css-classes). See [stimulus-bridge](https://github.com/symfony/stimulus-bridge) for more details. @@ -260,6 +260,17 @@ If you have multiple controllers on the same element, you can chain them as ther ``` +If you need to attach an [outlet](https://stimulus.hotwired.dev/reference/outlets) to the controller, you can call the `addOutlet()` method. + +For example: + +```twig +
Hello
+ + +
Hello
+``` + You can also retrieve the generated attributes as an array, which can be helpful e.g. for forms: ```twig diff --git a/src/Dto/StimulusControllersDto.php b/src/Dto/StimulusControllersDto.php index 973aa19a..e55b5c21 100644 --- a/src/Dto/StimulusControllersDto.php +++ b/src/Dto/StimulusControllersDto.php @@ -11,10 +11,13 @@ namespace Symfony\WebpackEncoreBundle\Dto; +use Twig\Markup; + final class StimulusControllersDto extends AbstractStimulusDto { private $controllers = []; private $values = []; + private $outlets = []; private $classes = []; public function addController(string $controllerName, array $controllerValues = [], array $controllerClasses = []): void @@ -36,10 +39,21 @@ public function addController(string $controllerName, array $controllerValues = foreach ($controllerClasses as $key => $class) { $key = $this->escapeAsHtmlAttr($this->normalizeKeyName($key)); - $this->values['data-'.$controllerName.'-'.$key.'-class'] = $class; + $this->classes['data-'.$controllerName.'-'.$key.'-class'] = $class; } } + public function addOutlet(string $outletName, string $selector) + { + if (1 < \count($this->controllers)) { + throw new \LengthException('You cannot call addOutlet() method when passing more than one controller identifier to stimulus_controller() function'); + } + + $this->outlets['data-'.$this->controllers[0].'-'.$outletName.'-outlet'] = $selector; + + return new Markup($this, 'UTF-8'); + } + public function __toString(): string { if (0 === \count($this->controllers)) { @@ -53,7 +67,10 @@ public function __toString(): string }, array_keys($this->values), $this->values)).' '. implode(' ', array_map(function (string $attribute, string $value): string { return $attribute.'="'.$this->escapeAsHtmlAttr($value).'"'; - }, array_keys($this->classes), $this->classes)) + }, array_keys($this->classes), $this->classes)).' '. + implode(' ', array_map(function (string $attribute, string $value): string { + return $attribute.'="'.$this->escapeAsHtmlAttr($value).'"'; + }, array_keys($this->outlets), $this->outlets)) ); } diff --git a/tests/Dto/StimulusControllersDtoTest.php b/tests/Dto/StimulusControllersDtoTest.php index 2ef6fa0d..fa7e1adf 100644 --- a/tests/Dto/StimulusControllersDtoTest.php +++ b/tests/Dto/StimulusControllersDtoTest.php @@ -51,4 +51,20 @@ public function testToArrayNoEscapingAttributeValues(): void $attributesArray ); } + + public function testAddOutlet(): void + { + $this->stimulusControllersDto->addController('foo', ['bar' => '"'], ['baz' => '"']); + $this->stimulusControllersDto->addOutlet('outlet-name', '"'); + $attributesArray = $this->stimulusControllersDto->toArray(); + self::assertSame( + [ + 'data-controller' => 'foo', + 'data-foo-bar-value' => '"', + 'data-foo-baz-class' => '"', + 'data-foo-outlet-name-outlet' => '"', + ], + $attributesArray + ); + } }