x-data Directive
The starting point of every Alpine component. Define reactive state here.
What is x-data?
x-data declares a new Alpine component scope. It expects a JavaScript object (or a function returning an object) that will become reactive. All Alpine directives inside this element can access its properties. Every interactive component must have an x-data attribute at its root.
💡 Tip
Think of x-data as the data() function in Vue – it holds your component’s state.
When to Use
Use x-data on any element that needs interactive state. A dropdown, modal, counter, or tab component must have x-data at its root. You can have multiple independent x-data components on the same page – they won't interfere with each other.
Basic Usage
<div x-data="{ open: false }">
<button @click="open = !open">Toggle</button>
<div x-show="open">This content toggles!</div>
</div>When open changes, x-show updates automatically because Alpine's reactivity system tracks the dependency.
Using Functions and init()
For more complex logic, you can define x-data as a function. The function runs once when the component initialises, and you can include an init() method that is called automatically.
<div x-data="{
init() {
this.count = 0;
console.log('Component ready');
},
count: 0
}">
<button @click="count++">Increment</button>
<span x-text="count"></span>
</div>Reusable Data with Alpine.data()
For components used multiple times, register a global data factory using Alpine.data(). This keeps your code DRY and allows parameters.
<div x-data="dropdown">
<button @click="toggle">Open</button>
<div x-show="open">...</div>
</div>
<script>
document.addEventListener('alpine:init', () => {
Alpine.data('dropdown', (initial = false) => ({
open: initial,
toggle() { this.open = !this.open }
}))
})
</script>Best Practices
- Keep the data object small – extract large logic into
Alpine.data(). - Use
init()for setup (like fetching data). - One
x-dataper component. Nesting is allowed but keep it understandable. - Always use
x-dataas the root attribute; don’t put it on a<template>tag unless wrapping withx-if.
Can I have multiple x‑data components on the same page?
Yes! Each one creates its own independent reactive scope. They do not share state unless you use $store.
What’s the difference between inline object and Alpine.data()?
Inline is fine for one‑off components. Alpine.data() is reusable, testable, and can accept parameters. It also separates your logic from the markup.
Can I use this inside x-data to reference the current element?
You don't need this if you use the object syntax; the properties are accessed directly. Inside Alpine.data(), this works as expected referring to the data proxy.
Live Counter Example
⚠️ Warning
Don’t use x-data on a <template> tag unless it’s wrapped with x-if correctly – the template tag is not rendered, so the data scope won't be attached.