#Integration intercept link clicks/page transitions

20 messages · Page 1 of 1 (latest)

frank panther
#

In my integration, I would like to execute arbitrary code when the user moves to another page of the site. How would I accomplish this?

mortal latchBOT
#

Hi @frank panther. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

Astro provides a way to execute code when a user navigates to another page through its View Transitions API. You can listen to the astro:page-load event which fires at the end of page navigation, after the new page is visible to the user and blocking styles and scripts are loaded. This event is fired both on initial page navigation for a pre-rendered page and on any subsequent navigation, either forwards or backwards.

Here is an example of how you can use this event to run code on every page navigation:

<script>
  document.addEventListener('astro:page-load', () => {
    // This runs on first page load and after every navigation.
    setupStuff(); // e.g. add event listeners
  });
</script>

This script listens for the astro:page-load event and runs a function setupStuff() on every page load. You can replace setupStuff() with any function you want to execute when a user navigates to a new page.

For more information, you can refer to the Astro documentation on View Transitions (https://docs.astro.build/en/guides/view-transitions/#astropage-load) and Astro API Reference (https://docs.astro.build/en/reference/api-reference/#astropage-load-event).

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@frank panther kapa.ai is still learning and improving, please let us know how it did by reacting below

frank panther
#

@mortal latch To be clear, I am not using View Transitions.

mortal latchBOT
#

Let me check the knowledge base for you. One moment! :books:

#

If you're not using Astro's View Transitions, you can still intercept link clicks and execute arbitrary code using standard JavaScript event listeners. You can add an event listener to the click event on all links (<a> tags) and run your code within that event listener.

Here's a basic example:

document.querySelectorAll('a').forEach(link => {
  link.addEventListener('click', (event) => {
    event.preventDefault(); // prevent the default link click action
    // Your code here...
    window.location.href = event.target.href; // navigate to the link after your code has executed
  });
});

This code will intercept all link clicks, prevent the default navigation action, allow you to execute your code, and then navigate to the clicked link.

Please note that this is a basic example and might need to be adjusted based on your specific needs. For example, if links are dynamically added to your page, you might need to use event delegation or periodically add the event listener to new links.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@frank panther kapa.ai is still learning and improving, please let us know how it did by reacting below

frank panther
#

@mortal latch Would using middleware also be a potential solution?

mortal latchBOT
#

Let me check the knowledge base for you. One moment! :books:

#

Yes, using Astro's middleware could be a potential solution to intercept requests and responses, and inject behaviors dynamically every time a page or endpoint is about to be rendered. Middleware allows you to set and share request-specific information across endpoints and pages by mutating a locals object that is available in all Astro components and API endpoints.

Here's an example of how you can use middleware to modify the HTML of your page:

export const onRequest = async (context, next) => {
    const response = await next();
    const html = await response.text();
    const redactedHtml = html.replaceAll("PRIVATE INFO", "REDACTED");

    return new Response(redactedHtml, {
        status: 200,
        headers: response.headers
    });
};

In this example, the middleware replaces all instances of "PRIVATE INFO" with "REDACTED" in the HTML of the page before it is rendered.

However, please note that middleware in Astro is run at build time for all prerendered pages, but occurs when the route is requested for pages rendered on demand. So, if you need to execute arbitrary code on the client-side when the user moves to another page of the site, using JavaScript event listeners as described in the previous response might be more suitable.

For more information, you can refer to the Astro documentation on Middleware (https://docs.astro.build/en/guides/middleware/).

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@frank panther kapa.ai is still learning and improving, please let us know how it did by reacting below

frank panther
#

@mortal latch Can you import a virtual:xxx package within a <script> tag? If not, what would be the most elegant way to make constants defined in the virtual available for the script?

mortal latchBOT
#

Let me check the knowledge base for you. One moment! :books:

#

Astro does not currently support importing virtual:xxx packages directly within a <script> tag. However, you can pass variables from your component's frontmatter into the client <script> or <style> tags using the define:vars directive. This allows you to make constants defined in the frontmatter available for the script.

Here's an example:

---
const message = "Astro is awesome!";
---
<script define:vars={{ message }}>
  alert(message);
</script>

In this example, the message constant is defined in the frontmatter and then passed into the <script> tag using the define:vars directive. The script then alerts the message.

Please note that using define:vars on a <script> tag implies the is:inline directive, which means your scripts won’t be bundled and will be inlined directly into the HTML. This is because when Astro bundles a script, it includes and runs the script once even if you include the component containing the script multiple times on one page. define:vars requires a script to rerun with each set of values, so Astro creates an inline script instead.

For more information, you can refer to the Astro documentation on the define:vars directive (https://docs.astro.build/en/reference/directives-reference/#definevars).

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@frank panther kapa.ai is still learning and improving, please let us know how it did by reacting below

frank panther
#

@mortal latch What would be a canonical way for this <script> tag to be loaded in for every page? How would I do this in an integration?

mortal latchBOT
#

Let me check the knowledge base for you. One moment! :books:

#

In an Astro integration, you can use the astro:config:setup hook to inject a script onto every page. This hook provides an injectScript option which is a callback function to inject a string of JavaScript content onto every page.

Here's an example of how you can use this hook to inject a script:

injectScript('page-ssr', 'import "global-styles.css";');

In this example, the injectScript function is called with two arguments: the stage at which the script should be inserted (page-ssr), and the content of the script (import "global-styles.css";).

The stage argument denotes how the script should be inserted. Some stages allow inserting scripts without modification, while others allow optimization during Vite’s bundling step. Here are the possible values for the stage argument:

  • "head-inline": Injected into a script tag in the <head> of every page. Not optimized or resolved by Vite.
  • "before-hydration": Imported client-side, before the hydration script runs. Optimized and resolved by Vite.
  • "page": Similar to head-inline, except that the injected snippet is handled by Vite and bundled with any other <script> tags defined inside of Astro components on the page. The script will be loaded with a <script type="module"> in the final page output, optimized and resolved by Vite.
  • "page-ssr": Imported as a separate module in the frontmatter of every Astro page component. Because this stage imports your script, the Astro global is not available and your script will only be run once when the import is first evaluated.