#Using variable from frontmatter in `<script>`
1 messages · Page 1 of 1 (latest)
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:
-
thisin the event handler: In your<script>,thisinside the arrow function does not refer to the DOM element. Arrow functions do not have their ownthisbinding; they inherit it from the parent scope, which is not what you want here. Instead, you should access the dataset from the element directly. -
Passing complex data via data attributes: The
data-versionsattribute 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., withJSON.stringify) and then parse it in your script.
Here's how you can fix your code:
- Serialize the
versionsarray into a JSON string for thedata-versionsattribute. - Parse the data attribute in your script.
- Access the data attribute from the element, not via
thisin 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:
----------------------