From 773ead9336672416bd268861b4e2889b82d65cf4 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 10 Feb 2021 15:34:00 -0500 Subject: [PATCH] adding a simpler syntax for single stimulus controller elements --- README.md | 16 +++++++++++-- src/Twig/StimulusTwigExtension.php | 25 +++++++++++++++++--- tests/IntegrationTest.php | 37 ++++++++++++++++++++++-------- 3 files changed, 64 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 60c09e01..71a8d193 100644 --- a/README.md +++ b/README.md @@ -207,7 +207,7 @@ See [stimulus-bridge](https://github.com/symfony/stimulus-bridge) for more detai For example: ```twig -
+
Hello
@@ -223,6 +223,18 @@ For example: Any non-scalar values (like `data: [1, 2, 3, 4]`) are JSON-encoded. And all values are properly escaped (the string `[` is an escaped -`[` character, so the attribute is really `[1,2,3,4]`). +`[` character, so the attribute is really `[1,2,3,4]`). + +If you have multiple controllers on the same element, pass them all as an +associative array in the first argument: + +```twig +
+ Hello +
+``` Ok, have fun! diff --git a/src/Twig/StimulusTwigExtension.php b/src/Twig/StimulusTwigExtension.php index 96adb0e1..76b62ee9 100644 --- a/src/Twig/StimulusTwigExtension.php +++ b/src/Twig/StimulusTwigExtension.php @@ -22,10 +22,29 @@ public function getFunctions() ]; } - public function renderStimulusController(Environment $env, array $data): string + /** + * @param string|array $dataOrControllerName This can either be a map of controller names + * as keys set to their "values". Or this + * can be a string controller name and data + * is passed as the 2nd argument. + * @param array $controllerValues Array of data if a string is passed to the first argument. + * @return string + * @throws \Twig\Error\RuntimeError + */ + public function renderStimulusController(Environment $env, $dataOrControllerName, array $controllerValues = []): string { - if (!$data) { - return ''; + if (is_string($dataOrControllerName)) { + $data = [$dataOrControllerName => $controllerValues]; + } else { + if ($controllerValues) { + throw new \InvalidArgumentException('You cannot pass an array to the first and second argument of stimulus_controller(): check the documentation.'); + } + + $data = $dataOrControllerName; + + if (!$data) { + return ''; + } } $controllers = []; diff --git a/tests/IntegrationTest.php b/tests/IntegrationTest.php index 56340996..fe8a01a3 100644 --- a/tests/IntegrationTest.php +++ b/tests/IntegrationTest.php @@ -182,48 +182,53 @@ public function testAutowireDefaultBuildArgument() public function provideRenderStimulusController() { yield 'empty' => [ - 'data' => [], + 'dataOrControllerName' => [], + 'controllerValues' => [], 'expected' => '', ]; yield 'single-controller-no-data' => [ - 'data' => [ + 'dataOrControllerName' => [ 'my-controller' => [], ], + 'controllerValues' => [], 'expected' => 'data-controller="my-controller"', ]; yield 'single-controller-scalar-data' => [ - 'data' => [ + 'dataOrControllerName' => [ 'my-controller' => [ 'myValue' => 'scalar-value', ], ], + 'controllerValues' => [], 'expected' => 'data-controller="my-controller" data-my-controller-my-value-value="scalar-value"', ]; yield 'single-controller-typed-data' => [ - 'data' => [ + 'dataOrControllerName' => [ 'my-controller' => [ 'boolean' => true, 'number' => 4, 'string' => 'str', ], ], + 'controllerValues' => [], 'expected' => 'data-controller="my-controller" data-my-controller-boolean-value="1" data-my-controller-number-value="4" data-my-controller-string-value="str"', ]; yield 'single-controller-nested-data' => [ - 'data' => [ + 'dataOrControllerName' => [ 'my-controller' => [ 'myValue' => ['nested' => 'array'], ], ], + 'controllerValues' => [], 'expected' => 'data-controller="my-controller" data-my-controller-my-value-value="{"nested":"array"}"', ]; yield 'multiple-controllers-scalar-data' => [ - 'data' => [ + 'dataOrControllerName' => [ 'my-controller' => [ 'myValue' => 'scalar-value', ], @@ -231,30 +236,44 @@ public function provideRenderStimulusController() 'anotherValue' => 'scalar-value 2', ], ], + 'controllerValues' => [], 'expected' => 'data-controller="my-controller another-controller" data-my-controller-my-value-value="scalar-value" data-another-controller-another-value-value="scalar-value 2"', ]; yield 'normalize-names' => [ - 'data' => [ + 'dataOrControllerName' => [ '@symfony/ux-dropzone/dropzone' => [ 'my"Key"' => true, ], ], + 'controllerValues' => [], 'expected' => 'data-controller="symfony--ux-dropzone--dropzone" data-symfony--ux-dropzone--dropzone-my-key-value="1"', ]; + + yield 'short-single-controller-no-data' => [ + 'dataOrControllerName' => 'my-controller', + 'controllerValues' => [], + 'expected' => 'data-controller="my-controller"', + ]; + + yield 'short-single-controller-with-data' => [ + 'dataOrControllerName' => 'my-controller', + 'controllerValues' => ['myValue' => 'scalar-value'], + 'expected' => 'data-controller="my-controller" data-my-controller-my-value-value="scalar-value"', + ]; } /** * @dataProvider provideRenderStimulusController */ - public function testRenderStimulusController(array $data, string $expected) + public function testRenderStimulusController($dataOrControllerName, array $controllerValues, string $expected) { $kernel = new WebpackEncoreIntegrationTestKernel(true); $kernel->boot(); $twig = $this->getTwigEnvironmentFromBootedKernel($kernel); $extension = new StimulusTwigExtension(); - $this->assertSame($expected, $extension->renderStimulusController($twig, $data)); + $this->assertSame($expected, $extension->renderStimulusController($twig, $dataOrControllerName, $controllerValues)); } private function getContainerFromBootedKernel(WebpackEncoreIntegrationTestKernel $kernel)