Sync Alpine.js x-data to localStorage/sessionStorage
Alpine.js is great for writing widgets. localStorage
/sessionStorage
are Web APIs that enable JavaScript application to store data beyond the life of the current JavaScript process.
This is useful for example if we wanted to persist our todos when the user closes the tab and comes back to it later.
If you want to skip to the examples, they’re in this CodePen collection or at the following:
Table of Contents
Sync a single string field to localStorage with Alpine.js x-init
and $watch
In the following example, we initialise the message
field to the msg
localStorage property using localStorage.getItem('msg')
.
To sync state from Alpine.js to localStorage, we can use $watch('message', (val) => localStorage.setItem('msg', val))
in x-init
. This will run the callback on every message
change and therefore update the msg
value in localStorage.
<div
x-data="{ message: localStorage.getItem('msg') }"
x-init="$watch('message', (val) => localStorage.setItem('msg', val))"
>
<div><code>localStorage.getItem('msg')</code>: "<span x-text="localStorage.getItem('msg')"></span>"</div>
<input x-model="message" />
<div>Output: <span x-text="message"></span></div>
</div>
You can see the example working in the following CodePen:
See the Pen Alpine.js sync to localStorage - simple example by Hugo (@hugodf) on CodePen.
We’ve now seen how to sync a simple string between Alpine.js state and localStorage using x-init
, $watch
, localStorage.getItem
and localStorage.setItem
.
Next we’ll see how to sync an Array/Object between localStorage and Alpine.js using x-init
, $watch
, localStorage.removeItem
and JSON.stringify
/JSON.parse
.
Sync an Array/Object to localStorage with Alpine.js x-init
and $watch
The following is a full “todo” app with new todo and remove functionality.
Don’t use this in production, the way I’m generating id’s isn’t great 😂.
The interesting bits are as follows.
- In
x-data
, we doJSON.parse(localStorage.getItem('todos') || '[]')
, that means that we try to parse what’s in localStorage under the'todos'
key, if it’s empty, parse'[]'
(which parses to[]
, ie. an empty array). - In
x-init
, we$watch
the'todos'
Alpine.js data property. When the value updates, we run(val) => localStorage.setItem('todos', JSON.stringify(val))
. We takes the fulltodos
value andJSON.stringify
it into localStorage. - There’s a “new todo” form that can be submitted, and which would update the
todos
list. - We loop through the “todos” using
x-for
, for each todo, we have a remove button which resets todos to all the current ones except the one for which we clicked the “remove” button.
<script>
function badId() {
return (Math.random() * 100).toFixed(0);
}
</script>
<div
x-data="{
newTodo: '',
todos: JSON.parse(localStorage.getItem('todos') || '[]')
}"
x-init="$watch('todos', (val) => localStorage.setItem('todos', JSON.stringify(val)))"
>
<div>
<code>localStorage.getItem('todos')</code>:
<code x-text="localStorage.getItem('todos')"></code></div>
<div>
<button @click="todos = []; localStorage.removeItem('todos');">
Clear
</button>
</div>
<form
@submit.stop.prevent="
todos = [].concat({ id: badId(), text: newTodo }, todos);
newTodo = '';
"
>
<input x-model="newTodo" />
<button>Add</button>
</form>
<ul>Todos:
<template x-for="todo in todos" :key="todo.id">
<li>
<span x-text="todo.text"></span>
<button @click="todos = todos.filter(t => t.id !== todo.id)">x</button>
</li>
</template>
</ul>
</div>
You can see it in action at the following CodePen:
See the Pen Alpine.js sync to localStorage - persistent todo app by Hugo (@hugodf) on CodePen.
We’ve now seen how to sync more complex data structures between Alpine.js and localStorage.
Since sessionStorage has the same API, you can achieve something similar using that instead of localStorage.
That’s it for this post, you can check out the Alpine.js tag on Code with Hugo for more in-depth Alpine.js guides.
If you’re interested in Alpine.js, Subscribe to Alpine.js Weekly. A free, once–weekly email roundup of Alpine.js news and articles.
Photo by Steve Johnson on Unsplash
Interested in Alpine.js?
Subscribe to Alpine.js Weekly. A free, once–weekly email roundup of Alpine.js news and articles