DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • Exploring Intercooler.js: Simplify AJAX With HTML Attributes
  • React, Angular, and Vue.js: What’s the Technical Difference?
  • Top 10 Games Running on Javascript and HTML5
  • Creating Scrolling Text With HTML, CSS, and JavaScript

Trending

  • Ethical AI in Agile
  • A Deep Dive Into Firmware Over the Air for IoT Devices
  • Performing and Managing Incremental Backups Using pg_basebackup in PostgreSQL 17
  • The Human Side of Logs: What Unstructured Data Is Trying to Tell You
  1. DZone
  2. Coding
  3. Frameworks
  4. Augmenting the Client With Alpine.js

Augmenting the Client With Alpine.js

This post, dedicated to Alpine.js, is part of a series comparing different ways to implement asynchronous requests on the client.

By 
Nicolas Fränkel user avatar
Nicolas Fränkel
DZone Core CORE ·
Oct. 04, 24 · Tutorial
Likes (1)
Comment
Save
Tweet
Share
6.3K Views

Join the DZone community and get the full member experience.

Join For Free

This post is part of a series comparing different ways to implement asynchronous requests on the client, which is colloquially known as AJAX. I dedicated the previous post to Vue.js. I'll dedicate this one to Alpine.js — not to be confused with Alpine Linux.

I'll follow the same structure as previously.

Laying out the Work

Here's the setup, server- and client-side.

Server-Side

Here is how I integrate Thymeleaf and Alpine.js in the POM:

XML
 
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>        <!--1-->
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>  <!--1-->
    </dependency>
    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>webjars-locator</artifactId>                <!--1-->
        <version>0.52</version>
    </dependency>
    <dependency>
        <groupId>org.webjars.npm</groupId>
        <artifactId>alpinejs</artifactId>                       <!--2-->
        <version>3.14.1</version>
    </dependency>
    <dependency>
        <groupId>org.webjars.npm</groupId>
        <artifactId>axios</artifactId>                          <!--1-->
        <version>1.7.3</version>
    </dependency>
</dependencies>


  1. Same as last week with Vue
  2. Alpine instead of Vue

It's similar to Vue's setup.

Client-Side

Here's the code on the HTML side:

HTML
 
<script th:src="@{/webjars/axios/dist/axios.js}" src="https://cdn.jsdelivr.net/npm/axios@1.7/dist/axios.min.js"></script> <!--1-->
<script th:src="@{/webjars/alpinejs/dist/cdn.js}" src="https://cdn.jsdelivr.net/npm/alpinejs@3.14.1/dist/cdn.min.js" defer></script> <!--2-->
<script th:src="@{/alpine.js}" src="../static/alpine.js"></script>  <!--3-->
<script th:inline="javascript">
/*<![CDATA[*/
    window.alpineData = {                                           <!--4-->
        title: /*[[${ title }]]*/ 'A Title',
        todos: /*[[${ todos }]]*/ [{ 'id': 1, 'label': 'Take out the trash', 'completed': false }]
    }
/*]]>*/
</script>


  1. Axios helps make HTTP requests.
  2. Alpine itself
  3. Our client-side code
  4. Set the data

As for the POM, it's the same code for Alpine as for Vue.

The Alpine Code

We want to implement the same features as for Vue.

Our First Steps Into Alpine

The first step is to bootstrap the framework. We already added the link to our custom alpine.js file above.

JavaScript
 
document.addEventListener('alpine:init', () => {                    //1
    Alpine.data('app', () => ({                                     //2
        // The next JavaScript code snippets will be inside the block
    }))
})


  1. Run the block when the alpine:init event is triggered; the triggering event is specific to Alpine.
  2. Bootstrap Alpine and configure it to manage the HTML fragment identified by app. 

We now set the app id on the HTML side.

HTML
 
<div id="app">
</div>


Until now, it's very similar to Vue.js, a straight one-to-one mapping.

Unlike Vue.js, Alpine doesn't seem to have templates. The official UI components are not free. I found an open-source approach, but it's unavailable on WebJars.

Basic Interactions

Let's implement the check of the complete checkbox.

Here's the HTML code:

HTML
 
<input type="checkbox" :checked="todo.completed" @click="check(todo.id)"> <!--1-->
<input type="checkbox" :checked="todo.completed" @click="check" />  <!--2-->


  1. Alpine code
  2. Vue code

The code is very similar, with the difference that Alpine allows passing parameters.

On the JavaScript side, we must define the function, and that's all:

JavaScript
 
Alpine.data('app', () => ({
    check(id) {
        axios.patch(`/api/todo/${id}`, {checked: event.target.checked})
    }
}))


Client-Side Model

You might wonder where the todo above comes from. The answer is: from the local model.

We initialize it in the app or to be more precise, we initialize the list:

JavaScript
 
Alpine.data('app', () => ({
    title: window.alpineData.title,                                 //1
    todos: window.alpineData.todos,                                 //2
}))


  1. Initialize the title even if it's read-only.
  2. Initialize the todos list; at this point, it's read-only but we are going to update it the next section.

Updating the Model

In this section, we will implement adding a new Todo.

Here's the HTML snippet:

HTML
 
<form>
    <div class="form-group row">
        <label for="new-todo-label" class="col-auto col-form-label">New task</label>
        <div class="col-10">
            <input type="text" id="new-todo-label" placeholder="Label" class="form-control" x-model="label" /> <!--1-->
        </div>
        <div class="col-auto">
            <button type="button" class="btn btn-success" @click="create()">Add</button> <!--2-->
        </div>
    </div>
</form>


  1. The x-model defines a model and binds the label property defined in app. 
  2. Define the behavior of the button, as in the previous section.

The related code is the following:

JavaScript
 
Alpine.data('app', () => ({
    label: '',                                                      //1
    create() {
        axios.post('/api/todo', {label: this.label}).then(response => { //2
            this.todos.push(response.data)                          //3
        }).then(() => {
            this.label = ''                                         //4
        })
    }
}))


  1. Define a new label property.
  2. Send a POST request with the label value as the JSON payload.
  3. Get the response payload and add it to the local model of Todo. 
  4. Reset the label value.

Conclusion

Alpine is very similar to Vue, with the notable difference of the lack of templating; components are only available via a price. All other features have an equivalent.

I may need to be corrected because the documentation is less extensive. Also, Vue is much more popular than Alpine.

The complete source code for this post can be found on GitHub.

HTML JavaScript Open source Vue.js AJAX

Published at DZone with permission of Nicolas Fränkel, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Exploring Intercooler.js: Simplify AJAX With HTML Attributes
  • React, Angular, and Vue.js: What’s the Technical Difference?
  • Top 10 Games Running on Javascript and HTML5
  • Creating Scrolling Text With HTML, CSS, and JavaScript

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!