HTMX, perform something on page load
By Flavio Copes
Learn how to run code on page load with htmx using the htmx.onLoad() function, for example to automatically trigger a click on a button when the page loads.
Use htmx.onLoad().
It runs a function every time htmx processes new content. That includes the first page load, and it also runs again for any HTML that htmx swaps into the page later. A plain DOMContentLoaded listener only fires once, so it would miss content that arrives after a swap. That’s the reason htmx gives you its own hook.
First, load htmx:
<script src='https://unpkg.com/htmx.org@1.9.6'></script>
Simple example. Say you have a button that fetches the “last updated” time, and you want that fetch to happen automatically when the page opens, without the user clicking anything:
<p class='mt-5 mb-0' id='last-updated'>Last updated ...</p>
<button
id='fetch-last-updated'
hx-post='/partials/last-updated/'
hx-trigger='click'
hx-target='#last-updated'
hx-swap='innerHTML'>
</button>
<script>
htmx.onLoad(function (el) {
const contentElement = document.getElementById('fetch-last-updated')
htmx.trigger(contentElement, 'click', {})
})
</script>
The button already knows what to do: on click, it posts to /partials/last-updated/ and swaps the response into the #last-updated paragraph. We don’t want to duplicate that logic. We just want to fire it on load.
That’s what htmx.trigger() does. It dispatches an event on an element, exactly as if a real user had triggered it. Here we send a click, so the button runs its normal request and the paragraph fills in on its own.
Why the el argument
The function you pass to onLoad() receives el, the element that was just loaded or swapped in. On the first load that’s the whole document. After a swap it’s only the new fragment.
Use it to scope your work to the fresh content. If you search the whole document every time, you might grab elements that were already initialized, and you’d run your setup twice. A safer version looks inside el:
<script>
htmx.onLoad(function (el) {
const button = el.querySelector('#fetch-last-updated')
if (button) htmx.trigger(button, 'click', {})
})
</script>
The if check matters. A swap can bring in content that doesn’t contain your button at all, and querySelector would return null. Guarding against that keeps onLoad() from throwing on unrelated swaps.
If you need help writing the hx-* attributes on that button, my free htmx attribute builder generates them for you.