#Using variable from frontmatter in `<script>`

1 messages · Page 1 of 1 (latest)

hexed thunderBOT
#

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

#

You're on the right track by following the recommended approach of passing frontmatter variables to the client via data attributes. However, there are a couple of issues in your code:

  1. this in the event handler: In your <script>, this inside the arrow function does not refer to the DOM element. Arrow functions do not have their own this binding; they inherit it from the parent scope, which is not what you want here. Instead, you should access the dataset from the element directly.

  2. Passing complex data via data attributes: The data-versions attribute is being set to an array of objects, but HTML data attributes can only store strings. If you want to pass complex data, you need to serialize it (e.g., with JSON.stringify) and then parse it in your script.

Here's how you can fix your code:

  • Serialize the versions array into a JSON string for the data-versions attribute.
  • Parse the data attribute in your script.
  • Access the data attribute from the element, not via this in the event handler.

Example:

---
// ...your frontmatter code...
const versionsJson = JSON.stringify(versions);
---
<div id="diagram-container" data-versions={versionsJson}>
  <span class="font-semibold">Diagram version:</span>
  <select id="diagram-dropdown" class="bg-color">
    {
      versions.map((version, index) => (
        <option value={index} selected={index === 0}>
          {version.version}
        </option>
      ))
    }
  </select>

  <Image
    id="diagram-image"
    class="size-fit"
    src={versions[0].diagram}
    alt="homelab-diagram"
    width={1920}
    height={2600}
  />
</div>

<script>
  const container = document.getElementById("diagram-container");
  const dropdown = document.getElementById("diagram-dropdown");
  const image = document.getElementById("diagram-image");
#

// Parse the versions data from the data attribute
const versions = JSON.parse(container.dataset.versions);

dropdown.addEventListener("change", (event) => {
const target = event.target;
const index = parseInt(target.value);
image.src = versions[index].diagram.src; // .src because Astro's Image component uses an object
});
</script>


**Key points:**
- Use `JSON.stringify` in the frontmatter to serialize your data.
- Use `JSON.parse` in your script to retrieve the data.
- Access the data attribute from the container element, not via `this` in the event handler.

This approach is directly recommended in the Astro documentation for passing frontmatter variables to scripts using `data-*` attributes ([see the official guide](<https://docs.astro.build/en/guides/client-side-scripts/#pass-frontmatter-variables-to-scripts>)).

Let me know if you need further clarification!
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------