Displaying data (an array of objects) using Alpine JS in a table


This is from a perspective for those who haven't yet dived into JavaScript using frameworks / libraries like React, Angular and Vue and template engines. All three are good in their own ways - except that when using it for a single page or 3 page site, it'll consume 100+ MB in development mode and each time you need to deploy, you need to build - even after making a single character change after which the build or dist folder then needs to be re-uploaded in it's entirety to the server.
(Bootstrap 5.0.1 is used for styling - no JavaScript utilities included.)
Let's say we want to display name and description in a table and dynamically add (name, description) pairs to the table using a form.
- Load AlpineJS :
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine.min.js" defer></script>
- Load some initial dummy content for the table :
let content = [
{ name: 'Test 1', description: 'Test Description 1' },
{ name: 'Test 2', description: 'Test Description 2' },
{ name: 'Test 3', description: 'Test Description 3' },
{ name: 'Test 4', description: 'Test Description 4' },
{ name: 'Test 5', description: 'Test Description 5' },
];
- Create the form without the
<form>tag:
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input type="text" id="name" name="name" class="form-control" minlength="1" placeholder="Name" />
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<input type="text" id="description" name="description" class="form-control" minlength="1" placeholder="Description" />
</div>
<div class="mb-3">
<button type="submit" x-on:click="pushData(data);" class="btn btn-primary">Add</button>
</div>
We're not really posting the form's content to the server - hence no <form> tag.
- In order to loop over the data (contents of the object) and display as a table we need to make use of Alpine's
<template>tag in conjunction with thex-forattribute.
<template x-for="(d, i) in data">
...
...
...
</template>
i is the index while d is the single object of data : data[i].
- We need a key for uniqueness of a row. Hence
:key="Date.now() + Math.floor(Math.random() * 1000000)"
We can access the data's single item as d.name or data[i].name
Now, we'll use display: table, display: table-row and display: table-cell to display the form data as a table. The reason why I am not using a <table> itself is because using DIVs is easier.
<template x-for="(d, i) in data" :key="Date.now() + Math.floor(Math.random() * 1000000)">
<div style="display: table-row">
<div style="display: table-cell" x-text="i + 1"></div>
<div style="display: table-cell" x-text="d.name"></div>
<div style="display: table-cell" x-text="data[i].description"></div>
</div>
</template>
x-on:click="pushData(data);"is used to call a function when the click event it triggered.Because we need to bind the data to the template, we set the data in a container div :
<div x-data="{ data: content }">
Full Code :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Div Form</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x" crossorigin="anonymous" />
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine.min.js" defer></script>
<script>
let content = [
{ name: 'Test 1', description: 'Test Description 1' },
{ name: 'Test 2', description: 'Test Description 2' },
{ name: 'Test 3', description: 'Test Description 3' },
{ name: 'Test 4', description: 'Test Description 4' },
{ name: 'Test 5', description: 'Test Description 5' },
];
document.addEventListener("DOMContentLoaded", () =>
{
});
function pushData(data)
{
data.push({
name: document.getElementById('name').value,
description: document.getElementById('description').value
});
}
</script>
</head>
<body>
<div class="container mt-5">
<div x-data="{ data: content }">
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input type="text" id="name" name="name" class="form-control" minlength="1" placeholder="Name" />
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<input type="text" id="description" name="description" class="form-control" minlength="1" placeholder="Description" />
</div>
<div class="mb-3">
<button type="submit" x-on:click="pushData(data);" class="btn btn-primary">Add</button>
</div>
<hr/>
<div class="table" style="display: table">
<template x-for="(d, i) in data" :key="Date.now() + Math.floor(Math.random() * 1000000)">
<div style="display: table-row">
<div style="display: table-cell" x-text="i + 1"></div>
<div style="display: table-cell" x-text="d.name"></div>
<div style="display: table-cell" x-text="data[i].description"></div>
</div>
</template>
</div>
</div>
</div>
</body>
</html>
https://anjanesh.s3.amazonaws.com/div-form.html
#alpine - Alpine Day is coming on June 10th : https://alpineday.com
About the author
- I am a web developer from Navi Mumbai. Mainly dealt with LAMP stack, now into Django and getting into Laravel and Cloud. Founder of nerul.in and gaali.in
Comments
Join the discussionNo comments yet. Be the first to comment.





