symfony / ux

Symfony UX initiative: a JavaScript ecosystem for Symfony
https://ux.symfony.com/
MIT License
824 stars 298 forks source link

[TwigComponent] Nested Twig components #1630

Open dev-waltr opened 6 months ago

dev-waltr commented 6 months ago

Hi,

is there a plan to implement something like the datatable component in JSF/PrimeFaces or at least to process nested twig-components e.g.:

<p:dataTable var="product" value="#{dtSortView.products1}" allowUnsorting="true" sortMode="single">
    <p:column sortBy="#{product.code}" headerText="Code">
        <h:outputText value="#{product.code}"/>
    </p:column>
    <p:column sortBy="#{product.name}" headerText="Name" sortOrder="asc">
        <h:outputText value="#{product.name}"/>
    </p:column>
    <p:column sortBy="#{product.category}" headerText="Category">
        <h:outputText value="#{product.category}"/>
    </p:column>
    <p:column sortBy="#{product.quantity}" headerText="Quantity">
        <h:outputText value="#{product.quantity}"/>
    </p:column>
</p:dataTable>

In this case it's needed to access the p:column component in p:dataTable component. It could also help in developing form-component and form-field-components.

Thank you!

WebMamba commented 6 months ago

Hey @dev-waltr sorry I don't understand the question, we can already have nested components, see here:

<twig:Alert color="red" size="lg">
    <twig:Icon name="warning"/>
    <div>My content</div>
</twig:Alert>

For the datatable some POC has already been made but nothing concrete for now

moke13-dev commented 6 months ago

Hi @WebMamba,

I think the problem or the question is ultimately aimed at accessing the properties of the child components in a parent component.

If you have a DataTable component and a column component, to be able to render the header, sortability, filter, etc. in the template of the DataTable component, you would have to be able to access the data/configuration of the individual Column components.

In addition, you would then foreach the collection or the iterable in the template of the DataTable component and only then render the Column components accordingly.

The alternative approaches that I have found here for realizing something like this, are all aimed at a DataTableBuilder, similar to the FormBuilder, however, the variant of @dev-waltr or Primefaces/JSF would have the huge advantage that individualized rendering of each column would be very easy, e.g. if you want to use an icon instead of the text or any if-conditions, html wrappers, fancy html-markump etc., you would not have to do this in the PHP code of the builder. You can simply do this in the Twig template, as e.g.

<twig:dataTableColumn :sortable="true" title="Title">
    {% if value == false %}
        <span class="icon-1"><svg ...></span>
    {% else %}
        <span class="icon-2"><svg ...></span>
    {% endif %}
<twig:dataTableColumn>

If anyone has an idea or solution for this, I would also be very interested.

WebMamba commented 6 months ago

Ok, thank you @moke13-dev for the clarification. But I think we don't want to do that. One of the main rules when dealing with components is data should only go one way: parent -> child but never the other way. If you want your parent component to be aware of the from your child, you should move your data to your parent component. See the doc from React about this subject: https://legacy.reactjs.org/docs/composition-vs-inheritance.html

norkunas commented 6 months ago

React at least has contexts, so you can use parent data in child component and vice versa

smnandre commented 6 months ago

https://symfony.com/bundles/ux-twig-component/current/index.html#context-variables-inside-of-blocks

ALL variables from the upper component (e.g. SuccessAlert) are available inside the content of the lower component (e.g. Alert). However, because variables are merged, any variables with the same name are overridden by the lower component (e.g. Alert). That's why this refers to the embedded, or "current" component Alert.

You can keep referring to components higher up as well. Just add another outerScope. Remember though that the outerScope reference only starts once you're INSIDE the (embedded) component.

And the entire section: https://symfony.com/bundles/ux-twig-component/current/index.html#inheritance-forwarding-outer-blocks

carsonbot commented 1 week ago

Thank you for this issue. There has not been a lot of activity here for a while. Has this been resolved?