Alpine.js: Defining data

We’ve seen how to define data using x-data:

<div x-data="{ showThis: false }">
  <p x-show="showThis">Show this</p>
</div>

The string passed to x-data contains a JavaScript object, and we can add more variables into it:

<div x-data="{ showThis: false, name: '' }">
  <p x-show="showThis">Show this</p>
</div>

But it’s kind of difficult to write JavaScript in this way, especially because it’s not syntax highlighted and being inside a string it’s easy to do errors and the editor cannot detect them for us.

You can do this instead:

Alpine.data('mydata', () => ({
  showThis: false,
  name: ''
}))

and then you associate mydata to an HTML tag:

<div x-data="mydata">
  
</div>

and in its children (and on the element itself, if you need) you have access to the variables defined in mydata:

<div x-data="mydata">
  <p x-show="showThis">Show this</p>
</div>

This is very useful if you need to add methods that you can call when an event occurs, or when you have more complex data processing.

Simple example, I have a shopping cart and in addition to the data, I have some utility functions to format this data nicely in my UI:

Alpine.data('shop', () => ({
  showCartOverlay: false,
  cart: JSON.parse(localStorage.getItem('cart')) || [],
  subtotal: 0,
  subtotalFormatted() {
    return this.formatAsPrice(this.subtotal)
  },
  formatAsPrice(price) {
    return Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(price)
  },
  recalculateSubtotal() {
    this.subtotal = 0
    this.cart.map((item) => (this.subtotal = (parseInt(this.subtotal * 100) + parseInt(item.price * 100)) / 100))
  }
})

.. you got the idea.

Now I can use functions like this:

<div x-data="shop">
  ...
  <p class='ml-4' x-text='formatAsPrice(item.price)'></p>
</div>

It’s much cleaner than adding all those functions inside x-data.

Lessons in this unit:

0: Introduction
1: Installing Alpine
2: The basics of Alpine
3: Events
4: ▶︎ Defining data
5: Looping
6: Binding user input to variables
7: Watching variables change
8: Stores