javascriptdomevent-handlingdom-eventsastrojs

Attaching click event handlers in Astro pages


In the component template section of an Astro page, I am adding the following script:

// src/pages/foo.astro
<script>
document.addEventListener('DOMContentLoaded', function() {
    const myElement = document.getElementById('myId');
    
    if (myElement) {
        myElement.addEventListener('click', function() {
            console.log('Clicked on element with ID "myId"');
            // Add your desired functionality here
        });
    } else {
        console.warn('Element with ID "myId" not found');
    }
});
</script>

It's a generic script attaching a click event handler to myId element if found. Note that the event is attached when the DOM content is loaded, via the DOMContentLoaded listener, to be sure that myId is created when due.

If I navigate directly to the page, I can read the messages sent by console.log(), depending on the presence of myId. However, linking to foo.astro from another page:

// src/pages/bar.astro
...
<a href="/foo.astro">Go to foo</a>

then, when I click on the link to foo, the DOMContentLoaded event is not fired and I see no console messages.

This happens also when I look for elements with different functions, such asdocument.querySelectorAll().

So, what is the correct way to add event handlers in Astro?
Should I avoid waiting for DOM loading and expect that Astro will inject my page scripts when it's the right time? And how is this decided by Astro?


Solution

  • Are you using Astro ViewTransitions? If so, that would explain the difference in behaviour. And you should listen to the astro:page-load event.

    btw. <script> tags in Astro without any attributes are converted to <script type="module"> and thus you don't need any DOMContentLoaded listener (see Astro docs). JS Modules are only executed once the DOM is loaded.