DEV Community

Tyler Smith
Tyler Smith

Posted on • Updated on

 

Binding an Alpine.js element to the turbolinks:load event

If you use Alpine.js and Turbolinks together, there may be times where you want an Alpine-powered element to do something when the Turbolinks turbolinks:load event fires. Unfortunately, the following code doesn't work:

<div
  x-data="{}"
  x-on:turbolinks:load="console.log('Turbolinks load event should fire')"
></div>
Enter fullscreen mode Exit fullscreen mode

The x-on shorthand syntax (@) doesn't work either:

<div
  x-data="{}"
  @turbolinks:load="console.log('Turbolinks load event should fire')"
></div>
Enter fullscreen mode Exit fullscreen mode

What's going on here? Well, according to Alpine's docs for the x-on directive:

x-on can only listen for events with lower case names, as HTML attributes are case-insensitive. Writing x-on:CLICK will listen for an event named click.

Alternatively, you can use x-bind to attach an x-on directive to an element in javascript code (where case will be preserved).

It seems that Alpine's x-on directive and @ shorthand don't work with anything except lowercase characters. The colon in turbolinks:load seems to be the cause of our problem. We can use Alpine's x-bind directive to work around this, which preserves both the case and characters of the bound attributes:

<div
  x-data="{}"
  x-bind:x-on:turbolinks:load="console.log('Turbolinks load event fired')"
></div>
Enter fullscreen mode Exit fullscreen mode

Using x-bind with the x-on shorthand also works:

<div
  x-data="{}"
  x-bind:@turbolinks:load="console.log('Turbolinks load event fired')"
></div>
Enter fullscreen mode Exit fullscreen mode

You can now execute code when Turbolinks completes a page transition.

An alternative solution

Conversely, it might be better to use x-init with Alpine's $nextTick() magic function, which will execute only after the page has finished loading. If you're familiar with React.js, this is similar to useEffect(..., []).

<div
  x-data="{}"
  x-init="$nextTick(() => console.log('The new page has loaded')"
></div>
Enter fullscreen mode Exit fullscreen mode

This solution is nice because it isn't tightly-coupled to Turbolinks. If you removed Turbolinks from your site, the x-init code would continue to fire when a new page is loaded.

Top comments (0)

Who's your favorite PM?

We're Hiring for one!

We're looking for someone who can develop, maintain, and implement our product roadmap and strategy as a Senior Product Manager.

Head here to learn more about who we're looking for.