Description: The x-init directive allows you to execute JavaScript expressions or call component methods when an Alpine component is first initialized and added to the DOM. This is conceptually similar to a constructor in object-oriented programming (like Python's __init__ method) or lifecycle hooks like mounted in other JavaScript frameworks.
x-init="expressionOrMethodCall()": This is the core directive. It accepts any valid JavaScript expression or a call to a method defined within the component's x-data.
Examples:
<!-- Execute a simple JavaScript expression -->
<div x-data x-init="console.log('Component initialized!')"></div>
<!-- Call a component method -->
<div x-data="{ setup() { console.log('Setup method called.') } }" x-init="setup()"></div>
<!-- Multiple expressions can be chained with semicolons -->
<div x-data="{ count: 0, message: '' }" x-init="count = 5; message = 'Initialized'; console.log('Done init')"></div>
Can access component data: x-init="myProperty = 'initial value'"
x-init executes within the scope of the component, meaning it has direct access to all data properties and methods defined in the corresponding x-data object. You can read from and write to these properties.
<div x-data="{ user: { name: 'Guest', loggedIn: false } }"
x-init="user.name = 'Alice'; user.loggedIn = true; console.log('User set:', user)">
Welcome, <span x-text="user.name"></span>!
</div>
Runs after initial data is set up from x-data.
Alpine.js first processes the x-data directive to establish the component's reactive state. Only after this initial data object is created and its properties are set up does Alpine execute any x-init directives on that element or its children (from outermost to innermost). This ensures that when your x-init code runs, the component's data context is fully available.
Placing x-init on an element outside an x-data scope:
x-init needs the context of an Alpine component, which is defined by x-data. If you put x-init on an element that isn't inside an x-data scope (or isn't an x-data element itself), it won't have access to component data or methods. It might run in the global scope or not run as intended. Think of it like trying to use self in Python outside of a class method – it doesn't make sense.
<!-- Incorrect: x-init has no component context here -->
<div x-init="someVariable = 'value'">This might not work as expected or error.</div>
<!-- Correct: x-init is within an x-data scope -->
<div x-data="{ someVariable: '' }" x-init="someVariable = 'value'">
Value: <span x-text="someVariable"></span>
</div>
Trying to access DOM elements that are conditionally rendered by x-if (or x-show that's initially false) from within x-init before they exist:
x-init runs when its own element is initialized. If this x-init tries to immediately access a child DOM element that is wrapped in an <template x-if="false">, that child element won't be in the DOM yet. To safely interact with such elements, use Alpine's $nextTick magic property. $nextTick schedules your callback to run after Alpine has finished its current DOM update cycle.
<div x-data="{ showInput: false, inputValue: '' }"
x-init="showInput = true; $nextTick(() => { if ($refs.myInput) $refs.myInput.focus(); })">
<template x-if="showInput">
<input type="text" x-ref="myInput" x-model="inputValue">
</template>
</div>
In the example above, focusing $refs.myInput is deferred until $nextTick, ensuring the input element actually exists in the DOM after showInput becomes true.
Overusing x-init for things that could be simple x-data initial values:
If you're just setting a static initial value for a data property, it's often cleaner and more declarative to do it directly in x-data.
Less Ideal:
<div x-data="{ message: '' }" x-init="message = 'Hello, Alpine!'"></div>
Preferred for static initial values:
<div x-data="{ message: 'Hello, Alpine!' }"></div>
Reserve x-init for actions that truly need to *run code* upon initialization, such as:
Initial Value from x-data:
Value Set via x-init Expression:
No items were loaded. Check console for details.