[TwigComponents] [Question] Render component using dynamically passed name
Hi,
I'm trying to render a Twig component using a dynamically passed name. Is there a way to achieve this in Twig? Here is an example of what I'm attempting to do:
{% set my_string = 'Modal' %}
{% component (my_string) with {type: 'success'} %}
{% block content %}{{ ...content }}{% endblock %}
{% endcomponent %}
I want to be able to dynamically set the component name using the my_string variable. Any guidance or suggestions on how to accomplish this would be greatly appreciated!
Thank you!
Do you have an error or something when executing this? You can also do this:
{% set my_string = 'Modal' %}
{{ component(my_string, {
type: 'success',
content: ...content
})
but here you need to have your content in a props.
@WebMamba is right, the only way to call component dynamically is with the component function.
Currently there is no possibility to embed content into components with dynamic name.
Maybe we could take inspiration from this: https://laravel.com/docs/11.x/blade#dynamic-components
You can call dynamic component already. It's embedding a component that does not work
Sorry! ☺️
Inspired by what @seb-jean said, we could perhaps create a dynamic-component component like for icons and then use it with HTML Syntax.
Without content:
{% set component_name = 'Modal' %}
<twig:ux:dynamic-component component="{{ component_name }}" />
With content:
{% set component_name = 'Modal' %}
<twig:ux:dynamic-component component="{{ component_name }}">
{{ block(outerBlocks.content) }}
</twig:ux:dynamic-component>
So the content can be passed with dynamic component names.
This is not the real problem, for now the component tag does not allow dynamic bloc names.
The HTML syntax is only sugar on top of it
Thank you for this issue. There has not been a lot of activity here for a while. Has this been resolved?
Friendly reminder that this issue exists. If I don't hear anything I'll close this.
Good timing, @Valmonzo recently asked me about dynamic component name, and I suggested the following syntaxes:
{{ component(componentName) }}
{% component (componentName) %}
<twig:component :is="componentName"/> {# like Vue.js #}
WDYT?
{{ component(componentName) }}
{% component (componentName) %}
Both exist currently, at least the first, right ?
<twig:component :is="componentName"/>
This is something one can do locally in one line with an anonymous template. But not something -- personal opinion here -- should be promoted nor offered by the component.
If you can call many components like this, they are probably nothing more than a "include".
Until now, the idea has always been to offer features for component, not to offer a full alternative syntax to Twig. This could be done. And i see many reasons someone would like this. But I do not think TwigComponent are the place to do this.
As a new syntax could only be done "fully" by template, and would require not a PreLexer, but a custom Lexer. Again, doable. Even in a new UX package if someone wanted to code it.
I may be wrong here, or blind to some needs I don't see. So just in case I say it now explicitely: i have no definitive opinion here, and I can entirely change my mind... Also, my voice has only the limited weight it deserves. ;)
I do not think {% component (componentName) %} exists, at least I don't find any implementation in ComponentTokenParser::componentName nor in tests.
If we make this doable, end-users could create a Twig template like this:
{% props is %}
{% component (is) with attributes %} (or with {...attributes} ..?)
{% block content %}{% endblock %}
{% endcomponent %}
But what about other Twig blocks?
IMO, I would like to see:
- implement dynamic component usage with
{% component (componentName) %} - implement
<twig:component is="...">, an internal component, that will simply map to{% component (is) with {...attributes} %}
WDYT?
First I'd really like to understand the need.. as I have really no example coming to mind (not saying they do not exist!) where this would be anything but an include.
I mean i saw how one could code this anonymous, but i have not yet understood what is the final goal.. how would this be used in a template?
Secondly, you're absolutely right.
{% set foo = 'AlertBar' %}
{{ component(foo, {message: 'Message here'}) }}
This exist, the other one does not indeed.
I know remember I made it once --locally-- to try, but stopped there. Because it brings so many other problems, due to blocks, parent templates, etc.
So this could be done very quickly to be honest
<twig:component :is="componentName"/>
This probably will never be doable
<twig:component :is ...>
</twig:component>