AstroAlpine.js

Using Astro Props with an Alpine.js Component

The other day I was working on a quote creator for the agency I work at, using Astro. I opted to use Alpine.js for the reactivity. Naturally, after a while I needed to split the code into components. Alpine.js doesn’t have a build step, so there’s no single file components.

Astro, however, does have components. They ultimately render to static HTML but they accept props. Here’s an example:

<div class="add-deliverable">
	<AddDeliverableButton title="Design Mockup" hours="4" cat="Design" />
	<AddDeliverableButton title="Amendments" hours="1" cat="Design" />
</div>

The information being passed to the component needs to become available to Alpine.js, so how do we do that? First, let’s take a look at how the component is defined:

---
import Button from '@components/Button.astro';
 
interface Props {
    name: string;
    time: number;
    cat?: string;
}
 
const { name, time, cat = 'Build' } = Astro.props;
---
<Button
    type="button"
    size="sm"
    @click={
        `addItem({
            id: generateItemId(),
            cat: '${cat}',
            name: '${name}',
            time: ${time}
        })`
    }
>
    ...
</Button>

The important bit here is line 16:

@click={
    `addItem({
        id: generateItemId(),
        cat: '${cat}',
        name: '${name}',
        time: ${time}
    })`
}

Notice the braces instead of "", this tells Astro to run some Javascript during the build step. With that, we can use Javascript template literals to build the string of Javascript for Alpine (little bit of Javascript inception going on here).

The code above, once rendered looks like this:

<button type="button" @click="addItem({ id: generateItemId(), cat: 'Design', name: 'Amendments', time: 1 })"></button>

And that’s that, I hope you find this useful :)