Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

x-model and form inputs

The x-model directive binds a form field to a component property in both directions. The user types — the property changes; code changes the property — the field updates. This link is called two-way binding.

A text field

<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
 
<div x-data="{ title: '' }">
  <input x-model="title" placeholder="New task">
  <p>You typed: <span x-text="title"></span></p>
</div>

The text below the field repeats what you type on every key press.

The to-do form

Now the form can be built without $refs. After a task is added, the field is cleared by assigning title = '':

<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
 
<style>
  .done { text-decoration: line-through; }
</style>
 
<div x-data="{
  title: '',
  tasks: [{ id: 1, title: 'Buy milk', done: false }],
  add() {
    if (this.title.trim() === '') return;
    this.tasks.push({ id: Date.now(), title: this.title.trim(), done: false });
    this.title = '';
  }
}">
  <form @submit.prevent="add()">
    <input x-model="title" placeholder="New task">
    <button>Add</button>
  </form>
 
  <ul>
    <template x-for="task in tasks" :key="task.id">
      <li>
        <label>
          <input type="checkbox" x-model="task.done">
          <span :class="{ done: task.done }" x-text="task.title"></span>
        </label>
      </li>
    </template>
  </ul>
</div>

Type a task and press Enter — it appears in the list and the field is cleared. The checkbox is bound to the done property: checking it crosses the task out.

Other fields

FieldWhat goes into the property
<input type="checkbox">true or false
Several checkboxes bound to one arrayAn array of the checked values
<input type="radio">The value of the selected one
<select>The value of the selected option
<textarea>The text

An example with a task filter:

<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
 
<div x-data="{ filter: 'all' }">
  <select x-model="filter">
    <option value="all">All</option>
    <option value="active">Active</option>
    <option value="done">Done</option>
  </select>
  <p x-text="'Filter: ' + filter"></p>
</div>

Pick another option — the line below shows its value.

Modifiers

ModifierWhat it does
x-model.numberTurns the input into a number
x-model.lazyUpdates the property when the field loses focus, not on every key
x-model.debounceWaits for a pause in typing, handy for search

Common mistake

Forgetting .number on a numeric field. The value of an <input type="number"> still arrives as a string, and addition glues strings together:

<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
 
<div x-data="{ hours: 2 }">
  <input type="number" x-model="hours">
  <p x-text="'Total hours: ' + (hours + 1)"></p>
</div>

At first it shows 3, but after typing 5 you get "51". With x-model.number the result is 6.

Thanks for reading!

Donate to the site — we work hard for you.