Description: The x-model directive in AlpineJS provides a powerful and convenient way to create a seamless, reactive, two-way synchronization between form input elements and your component's data properties. This means that when the user changes the value of an input, the corresponding data property in your Alpine component updates automatically. Conversely, if the data property changes programmatically, the input element's value will also reflect that change.
x-model is the star of the show here. It's an Alpine directive you add directly to form elements.
Binds the value of a text input (<input type="text">, <input type="password">, <textarea>, etc.) to a data property. The property will typically hold a string.
<input type="text" x-model="message">
For a single checkbox, x-model binds its checked state (true/false) to a boolean property.
<input type="checkbox" x-model="agreedToTerms">
If multiple checkboxes share the same x-model binding to an array property, Alpine will populate the array with the value attributes of the checked checkboxes.
<input type="checkbox" value="red" x-model="selectedColors"> Red
<input type="checkbox" value="blue" x-model="selectedColors"> Blue
<!-- selectedColors will be an array, e.g., ['red'] or ['red', 'blue'] -->
All radio buttons in a group should share the same x-model property. The value attribute of the *selected* radio button will be assigned to this property.
<input type="radio" value="optionA" x-model="chosenOption"> Option A
<input type="radio" value="optionB" x-model="chosenOption"> Option B
<!-- chosenOption will be 'optionA' or 'optionB' -->
Binds the value of the selected <option> to a data property. If the <select> element has the multiple attribute, x-model will bind to an array of selected option values.
<select x-model="selectedCountry">
<option value="US">United States</option>
<option value="CA">Canada</option>
</select>
x-model:
Modifiers can alter how x-model behaves:
.lazy: By default, x-model updates the data property on every input event. With .lazy, it only updates on the change event (e.g., when the input field loses focus).
<input type="text" x-model.lazy="username">
.number: Automatically casts the input's value (which is always a string from the DOM) to a JavaScript Number type. This is crucial for inputs like <input type="number"> if you need the bound property to be a numeric type.
<input type="number" x-model.number="quantity">
.debounce: Adds a debounce to the data update. This means Alpine will wait for a specified period of inactivity after the user stops typing before updating the data property.
<!-- Default debounce of 250ms -->
<input type="text" x-model.debounce="searchTerm">
<!-- Debounce of 500ms -->
<input type="text" x-model.debounce.500ms="searchTerm">
.trim: Automatically trims whitespace from the input value before updating the data property.
<input type="text" x-model.trim="comment">
x-model data:
If an input element has an HTML value attribute (e.g., <input type="text" value="Initial HTML Value" x-model="message">) and x-model is also set, x-model will generally take precedence for setting the initial state of the Alpine data property. However, the recommended practice is to define the initial state of your data properties directly within your x-data object. This ensures clarity and a single source of truth for your component's initial state. Relying on HTML value attributes for initial Alpine state can lead to confusion.
Correct approach:
// In your Alpine component's data
{
message: 'Initial value from x-data'
}
<input type="text" x-model="message">
x-model on non-form elements:
x-model is specifically designed for form elements like <input>, <select>, and <textarea>. Attempting to use x-model on elements like <div> or <p> will not work for two-way binding as these elements don't have an intrinsic "value" that can be user-modified in the same way form inputs do. For displaying data in such elements (one-way binding), use directives like x-text or x-bind.
.number for numerical inputs:
Values retrieved from HTML input elements are always strings, even from <input type="number">. If you bind x-model to such an input and expect the corresponding data property to be a JavaScript Number, you might encounter issues if you perform arithmetic operations directly. Always use the .number modifier (e.g., x-model.number="age") to ensure the value is automatically cast to a number. Without it, '2' + '2' would result in '22' (string concatenation) instead of 4 (addition).
Current message:
Agreed:
Choose your plan (x-model="chosenPlan"):
Chosen Plan:
Selected Color:
Lazy Text Value:
Quantity Value: (Type: )
Debounced Text Value: