Skip to content

[TwigComponent] Add a way to add stimulus twig helper functions to twig components #2825

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
FlorianBoe opened this issue Jun 6, 2025 · 3 comments

Comments

@FlorianBoe
Copy link

I am currently working on a project in which StimulusJs and Twig components are being used together. I just looked in the documentation, it seems to me that there is no way to add a Stimulus controller using the Stimulus Twig helpers.

<twig:Button
  variant="danger"
  {{ stimulus_action('controller', 'action') }}
>
  Delete
</twig:Button>

It is not possible to add a controller or action like this because only attributes are allowed, which results in an error.

Expected attribute name when parsing the "<twig:Button" syntax.

I could pass the controller or action to the component via a prop, but this would make the components much more complex. Ultimately, we used the stimulus data attributes as a fallback. This means we lose all the benefits of the stimulus twig helper functions.

<twig:Button
  variant="danger"
  data-action="controller#action"
>
  Delete
</twig:Button>

Is there a better way to add these stimulus twig helper functions, or what would be required to allow them?

@norkunas
Copy link
Contributor

norkunas commented Jun 6, 2025

If stimulus_action would return array, then you could use spread syntax.
But the second solution is shorter, so I don't see any benefits

@FlorianBoe
Copy link
Author

If you look at the StimulusBundle documentation, you will see examples that make it clearer why using the helpers would be more compact.

Like:

<twig:Button {{ stimulus_action('hello-controller', 'method', 'click', { 'count': 3 }) }}>Hello</twig:Button>

Would render:

<twig:Button
  data-action="click->hello-controller#method"
  data-hello-controller-count-param="3"
>
  Hello
</twig:Button>

In addition, it seems to me that conditional attributes and for loops are not possible. The following example also does not work:

<twig:Button
    {{ not action.disabled ? 'href=' ~ action.url ~ ' data-turbo-frame=_top' }}
    {% for attr_name, attr_value in action.attr %}{{ attr_name }}="{{ attr_value }}"{% endfor %}
  >
    {{ action.label }
</twig:Button>

@smnandre
Copy link
Member

smnandre commented Jun 7, 2025

<twig:Button
    {{ not action.disabled ? 'href=' ~ action.url ~ ' data-turbo-frame=_top' }}

This is not possible, and will not for some time. In short, the TwigComponent HTML syntax is syntaxic.. sugar.

A template containing

<twig:Foo bar="foobar" />

is in fact transliterated into

{{ component('Foo', {bar: "foobar"}) }}

There is no way to use for nor it is to pass attrbute strings here, as Twig prevent it.

On a broader angle, as Twig component allow props: they need keys to accept values.


But, you absolutely can do this:

{% set attributes = action.attr %}        {# not using immediately because i have a doubt for parenthesis and dot notation here #}

<twig:Button  {{ ...attributes }} />

As long attributes is a map of things indexed by string keys.. this should work for you.

:)

In short: you have to deal with "conditions" outside the component call, but that can be done quite easily :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants