[LiveComponent] Clarify re-rendering and DOM for nested Live Components #3243
Replies: 2 comments
-
|
Can you precise what you mean by
I rather precise this... it replaces the previous one, even when ID is not the same, right ?
Well.. it is a good one. Here you want to refresh even when it's already the same id, but you have no concurrency problem, but an invalidation problem. So instead of random i suppose you could derive from timestamp to grant freshness, no? id="{{ my_item_id }}-{{ ''|date('U') }}"
Data skip morph is on a different topic: it basically says "we don't want to compare / update this element and its children element per element, attribute per attribute, simply pass me the whole new HTML and we'll replace the current one". |
Beta Was this translation helpful? Give feedback.
-
|
But i'm having some doubt in the same time... why would you use a LiveComponent for the whole list ? You have other LiveProps on the ProductList I suppose ? |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I believe that, for the benefit of the entire community using Symfony UX Live Components, it is necessary to clarify how the re-rendering and DOM reconciliation system works in order to handle a very common use case, which I can summarize as follows:
Is there anyone who could clarify, once and for all, and perhaps include in the documentation, the best logic for this scenario? It would definitely be a great improvement in terms of DX, since people end up spending hours trying to understand these concepts without knowing the internal workings of Live Components, DOM morphing, and reconciliation.
Conceptual code:
In the Twig template, we specify what should happen when the button for a specific product is clicked:
{% for product in this.products %} <button {{ live_action("setCurrentForEditing", { product: product.id }) }}> Edit Product </button> {% endfor %}Now comes the “difficult” part: the form must be rendered every time this button is clicked.
✅ At the moment, the most reliable way I have found to achieve this (although I don’t think it’s the correct approach) is to use a random id in order to force the
ProductEditFormcomponent to be re-rendered each time:{% if currentProductForEditing is not null %} <twig:ProductEditForm id="edit-form-{{ random() }}" :initialFormData="currentProductForEditing" /> {% endif %}With this approach, the data always appears to be “fresh”, and the form does not retain any previous temporary (unsaved) values.
What happens if we use
id="edit-form-{{ random() }}? ❌{% if current is not null %} <twig:ProductEditForm :initialFormData="current" /> {% endif %}The form is retaining “old” values. For example, if I set a product title and then click on another product in the list, the form keeps the previous title instead of resetting.
What happens if we use
data-skip-morph? ❌It doesn’t work correctly: click on product A, the form appears; click on product B, the form disappears; click again, the form appears… and so on.
Beta Was this translation helpful? Give feedback.
All reactions