tl;dr How to force liveview to
phx-update="ignore" an element and then to
phx-update="replace" its children so as not to reset client state on that one particular element?
I’m working on a project using liveview and Muuri (muuri is a js grid layout library) to create a draggable dashboard of real-time widgets that can be added and removed. The page roughly looks like this:
<div id="grid" phx-hook="Muuri"> <%= for widget <- @widgets do %> <div class="grid-item"> <!-- ... --> <button phx-click="remove" phx-value-widget="<%= widget.id %>">Remove</button> <!-- ... real time data as a component or a view ... --> </div> <% end %> </div> <button phx-click="add-widget">Add widget</button>
The problem I have is that I need liveview to ignore and never patch the elements which are controlled by Muuri, namely
.grid-item. And at the same time I need liveview to be able to modify the contents of
.grid-item freely for the real-time functionality so as not to do it in JS. I also need liveview to be able to prepend to the list of widgets when a new widget is added.
Here’re my attempts at achieving it:
The first thing that I tried was
#grid. Using this directive adding, moving and removing widgets is easy. But any other update/patch (unrelated to grid and widgets) sent to the client resets the attributes on
.grid-itemwhich breaks the grid layout. The workaround is to remove all previous items from the muuri instance and re-add them again. On my laptop this sometimes results in a 50ms blip in the layout, which is not good.
The next thing that I tried was
#grid's parent. In order to be able to use that directive and still show real-time data from inside of the grid, all widgets are turned into liveviews. Moving and removing widgets also works with little modification, but adding new widgets doesn’t seem to be possible since even though the new widget update is sent to the client, it’s never applied to the DOM and never added to the grid. I can probably use
push_eventto get the new widget html and init the liveview manually but I’d rather avoid that.
I wonder how would others approach the problem, and whether anyone thinks that a
phx-update attribute that would offset
ignore one would make sense. For example, with my first approach it would allow me to wrap
stop-ignore blocks and still be able to add, move, and remove widgets without interferring with Muuri.