DEV Community

Cover image for State & DOM Manipulation with AlpineJS
Semir Teskeredzic
Semir Teskeredzic

Posted on

State & DOM Manipulation with AlpineJS

In my previous post I introduced this great lightweight JavaScript framework - AlpineJS. You can read about it here. In this post I will go through some of the concepts that AlpineJS uses for state management and DOM manipulation.

State

You can say that the State is the magic ingredient and I will agree with you, but essentially State is a data object that enables us to do many things on the frontend side. Alpine lets you provide data within specific HTML element(s) or make it accessible from anywhere on your page. Let's start with the local one.

x-data

This attribute is simple and straightforward, you declare it inside the HTML element and the entire block has the access to it. In the example below h1 and p will have no problem accessing toggle value and additionally if they depend on it, they will react automatically.

<div x-data="{ toggle: true }">
...
  <h1></h1>
  <p></p>
...
</div>
Enter fullscreen mode Exit fullscreen mode

You can also nest data and access parent data from the child. Let's see that in the example

<div x-data="{ toggle: false }">
  <div x-data="{ title: 'I am the title' }">
    <h1 x-text="title"></h1>
    <p x-show="toggle">Paragraph</p>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Data can also be used within the same element, you can also pass only the x-data directive without expression if you need to.

<button x-data="{ label: 'Buy Now' }" x-text="label"></button>
<button x-data @click="alert('Button is clicked')">Alert</button>
Enter fullscreen mode Exit fullscreen mode

Alpine.store(...)

When you need your data to be available to every component on the page, you can use Alpine.store that stands for global store on the page level. You are registering it with Alpine.store(...) and referencing it with the $store() method. First we will register the store:

Alpine.store('tabs', {
  current: 'overview',
  items: ['overview','description','specification'],
})
Enter fullscreen mode Exit fullscreen mode

We can now access it or modify it anywhere on the page

<div x-data>
  <template x-for="tab in $store.tabs.items">
    ...
  </template>
</div>

<div x-data>
  <button @click="$store.tabs.current = 'overview'">Overview</button>
  <button @click="$store.tabs.current = 'description'">Description</button>
  <button @click="$store.tabs.current = 'spoecification'">Specification</button>
</div>
Enter fullscreen mode Exit fullscreen mode

DOM Manipulation

Alpine makes DOM manipulation available through the use of various directives. We will go through some of the most common ones here.

Text content

We can use directive x-text to essentially control the text content of the element:

<div x-data="{ paragraph: 'This is the paragraph' }">
  <p x-text="paragraph"></p>
</div>
Enter fullscreen mode Exit fullscreen mode

With this directive you can use any JavaScript expression and it will evaluate as the content of the element.

<div x-data="{a: 1, b: 4}">
  <p x-text="b > a"></p>
</div>
Enter fullscreen mode Exit fullscreen mode

This will output true

Toggling elements

You will require this directive when you create modals, dropdowns and similar content that has 'on-off' logic. We can use x-show and x-if here to toggle elements on the page. Behind the scenes Alpine is adding display: none to the element it needs to hide

<div x-data="{ toggle: false }">
    <button @click="toggle = ! toggle">Show More</button>
    <div x-show="toggle">
        My Content...
    </div>
</div>
Enter fullscreen mode Exit fullscreen mode

We can use x-if to achieve the same goal

<div x-data="{ toggle: false }">
    <button @click="toggle = ! toggle">Show More</button>
    <template x-if="toggle">
      <div>
        My Content...
      </div>
    </template>
</div>
Enter fullscreen mode Exit fullscreen mode

Binding attributes

We can add HTML attributes to elements using x-bind directive

<button
    x-data="{ green: false }"
    x-bind:class="green ? 'bg-green' : ''"
    @click="green = !green"
>
    Toggle Green
</button>
Enter fullscreen mode Exit fullscreen mode

You can use syntax without x-bind only on class bindings like so:

<div x-data="{ open: true }">
  <p :class="{ 'hidden': !open }">...</p>
</div>
Enter fullscreen mode Exit fullscreen mode

Here we will have hidden class added to the p element whenever open is false.

Looping elements

We've seen x-for earlier when we iterated through tabs in Alpine.store(...) example. As you've seen there, x-for allows us to iterate through our data. Note that it has to be applied within <template> tag though.

<div x-data="{ seasons: ['spring', 'summer', 'autumn', 'winter'] }">
    <template x-for="season in seasons">
        <div x-text="season"></div>
    </template>
</div>
Enter fullscreen mode Exit fullscreen mode

Inner HTML

You can also control HTML content with the x-html directive like so:

<div x-data="{ title: '<h1>I am the Title</h1>' }">
    <div x-html="title"></div>
</div>
Enter fullscreen mode Exit fullscreen mode

Hope some of the examples will help you in your work, hobbies, and projects. Thank you for reading and stay safe.

Discussion (0)