How to turn my client-side DOM manipulations into DOM-patch aware manipulations?

I was also wondering how LiveView JS commands could achieve “DOM-patch aware” DOM manipulations, so I just tried to read the source code of liveview js lib a few days ago. And here is my understanding:

When LiveView executes a JS command on the client-side, for example, a JS.set_attribute operation, it not only sets the attribute of that specific element, but also puts some private information into the element properties. It is shown in the code snippet below in the DOM.putSticky function:

And you can also inspect these private properties in Chrome DevTools.

All these executed JS commands will be stored in this phxPrivate.sticky property, so that when DOM-patching happens, these DOM changes made by JS commands will remain intact.

So if you want to achieve something similar to JS commands, here is a kind of tricky approach: just executing LiveView JS commands from JavaScript. Here’s how you can do it:

In your heex template, store JS commands in a data attribute:

<div id="my-element" data-js={JS.set_attribute({"aria-expanded", "true"})}>
</div>

And on the JavaScript side:

let liveSocket = new LiveSocket()

const el = document.getElementById("my-element")
liveSocket.execJS(el, el.dataset.js)

I think this approach is also used in GitHub - fly-apps/live_beats

1 Like