juneum
Developer Notes

Using Alpine 3 with Phoenix LiveView

February 16, 2022
trisager

Phoenix LiveView mostly eliminates the need to write JavaScript in the front end, but there are still some parts of the user interface that are best handled with JS, e.g. showing and hiding a drop-down menu. A convenient way to do this is by using the Alpine.js package that lets you put the behavior you want directly into the markup, instead of having to write callback functions in plain JavaScript.

Because Alpine and LiveView both manipulate the DOM, you cannot simply add Alpine to a page using a <script> tag and expect it to work. And unfortunately many of the tutorials and code snippets out there won't work with recent versions of Alpine and LiveView. So this is a quick overview of how to get Alpine v3.9.0 to work with LiveView v0.17.7 (the most recent versions at the time of writing).

Begin by installing Alpine:

$ cd assets
$ npm install alpinejs

Import it at the top of app.js:

import Alpine from "alpinejs";
window.Alpine = Alpine;
Alpine.start();

Finally, add a dom key to the object that is used to initialize the LiveView socket:

let liveSocket = new LiveSocket("/live", Socket, {
  params: { _csrf_token: csrfToken },
  dom: {
    onBeforeElUpdated(from, to) {
      if (from._x_dataStack) {
        window.Alpine.clone(from, to);
      }
    },
  },
});

The onBeforeElUpdated callback lets us hook into the step where LiveView updates a DOM element, before the update is completed. At this point, from holds the current version of the DOM element and to is what the element will become after the DOM update is complete.

If the DOM element that is being updated by LiveView is also tracked by Alpine, it will have a _x_dataStack property. If that is the case, we call Alpine.clone to make sure that this property is copied to the new element.

This is enough to let you use Alpine with LiveView to manipulate DOM elements. But note that LiveView has code that you can hook into if you want to pass events from Alpine to LiveView, e.g. if you use Alpine to animate a toggle but also want to notify LiveView of the toggle event. We'll look into how you can do that in a future article.

← Back to articles