Adding new LiveView component ignores AlpineJS directives

Hello! I am having a weird issue when adding new LiveView components to the page. AlpineJS directives for component are totally ignored for the new component. Anyone else stumbled on this before?

AlpineJS works as expected. I followed the guides from the forum to upgrade it from v2 to v3. My app has a form that allows user to add some data and that data added to the list on the page in the form of a new component. However, when the new component is added and rendered on the page its Alpine directives are totally ignored. It’s just a simple menu that is broken and I could probably get away with pure hooks, but the menu has some CSS transitions and Alpine make working with transitions really easy.

Any help would be greatly appreciated! Thanks!

Did you add the appropriate config for Alpine directives to work on LiveView’s? Something like:

// in app.js
let liveSocket = new LiveSocket("/live", Socket, {
  params: { _csrf_token: csrfToken },
  hooks: hooks,
  dom: { // This is the important bit!
    onBeforeElUpdated(from, to) {
      if (from._x_dataStack) {
        window.Alpine.clone(from, to);
      }
    },
  },
});

Yes. This is the strange thing. Everything works on the initial page load. The components are the same, it’s a list, except for when adding new ones to the list (via a form), their directives x-data and x-init are ignored by Alpine. I am not sure where the trouble lies.

For the record: I am using phx-update="prepend" on the list with temporary assigns and every component in that list is stateful.

I have this code in my app.js copied from a post on this forum and Alpine works as expected on the page in general.

import Alpine from 'alpinejs';
window.Alpine = Alpine;
// ...
const liveSocket = new LiveSocket('/live', Socket, {
  params: {
    _csrf_token: csrfToken
  },
  hooks: Hooks,
  dom: {
    onBeforeElUpdated(from, to) {
      if (from._x_dataStack) {
        window.Alpine.clone(from, to)
        window.Alpine.initTree(to)
      }
    },
  },
});
// ...
Alpine.start();

I saw that livesocket also has a onNodeAdded(el) callback, but not sure if I should touch it as I haven’t found any documentation on it.

1 Like

So I figured where the problem is how to solve it. When a new element (component) is added to the page the onBeforeElUpdated is not called and therefore all Alpine directives are not initialized.

To properly wire up Alpine for newly added DOM components make sure to add this callback to your socket config.

  dom: {
    // add this callback
    onNodeAdded(node) {
      if (node._x_dataStack) {
        window.Alpine.initTree(node);
      }
    },
    onBeforeElUpdated(from, to) {
      if (from._x_dataStack) {
        window.Alpine.clone(from, to);
        window.Alpine.initTree(to);
      }
    },
  }

Hope this helps someone in the same situation :slightly_smiling_face:

9 Likes