Feature: Arbitrary element replacement

Desired behavior:

The ability to define a segregated container with, say, phx-update=“cross-replace” containing the elements which LiveView then uses to replace elements with the corresponding ids in their respective appended/prepended containers within the same template.
The “cross-replace” container is discarded once the operation is finished.
This is virtually the same feature that LiveView already does when replacing elements in an appended/prepended container, the only difference here being the support for cross-container replacement.

Purpose:

Use cases dealing with more than a single dimension of elements (e.g. a table/grid) typically require a more detailed element replacement then just having their top-dimension entries (e.g. rows) appended and then sorted in the JS code. With the majority of changes occurring at the level of a single element, it is suboptimal to have LiveView transfer the entire rows.

The reason why this feature cannot be done safely at an application level is hooks - the elements getting replaced require their hook related listeners removed by LV.

@josevalim Please share your thoughts on the matter even if you choose not to consider this enhancement request.

UPDATE: Another option is for client code to alter individual attributes of an element instead of having it replaced with the suggested feature, but the limitations here are substantial.

From your description, it feels like you should make each table row a live component. In this scenario, you can change each row, piece by piece, or even transfer it altogether. How is your proposal different from using components as above?

Unfortunately, I find components too heavy for the use with table/grid rows because of their helper index structure included along with any change.
With hundreds of rows, the helper structure becomes quite burdensome.

In addition to this, since the row component itself is made up of a list of cells, somehow it always sends the entire row (all cells) even if just a couple of characters have changed in a single cell. When binary comparing the HTML output it is identical but for the couple of bytes, yet the JS object in the debugging mode gets to contain the entire row and the accompanying structure. It could be me, but I did absolutely everything to follow the rules and yet somehow that diffing within a component does not work properly (still using v0.14.7 though).

UPDATE: Please note that the only option that I haven’t tried so far is the row components in appended container. However, if the behavior is as provided in the documentation, a component will get replaced as a whole, right/wrong?

Just to let you know it’s that last option that actually works as desired.
To sum it up, the table/grid optimal solution:

  • rows: no components, just appended container + JS removal of the marked for deletion and positioning of inserts on updated
  • cells: components

Thanks,
Damir