How to update Alpine.js data from sort handler
There is a sort plugin for Alpine.js. I wanted to use this plugin to let the user sort a list and react to it by changing the Alpine reactive data (x-data).
My first approach has been following code:
<!-- NOT WORKING AS EXPECTED -->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/sort@3.x.x/dist/cdn.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
</head>
<body>
<main>
<div>
<div x-data="sortedData">
<ul x-sort="handleSort">
<li x-sort:item="1">foo</li>
<li x-sort:item="2">bar</li>
<li x-sort:item="3">baz</li>
</ul>
<div x-text="sorted"></div>
</div>
<script>
document.addEventListener('alpine:init', () => {
Alpine.data('sortedData', () => ({
sorted: false,
get getSorted() { return this.sorted },
handleSort(items) { this.sorted = !this.sorted; }
}))
});
</script>
</div>
</body>
</html>
Unfortunately, this does not work as expected. handleSort is called but the context is not the same as the context of Alpine data (this refers to something else).
After trying a lot of different ways making the context of the sort handler, that of Alpine data I found that passing (items) => handleSort(items) to x-sort works as expected:
<!-- WOKRING SOLUTION -->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/sort@3.x.x/dist/cdn.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
</head>
<body>
<main>
<div>
<div x-data="sortedData">
<ul x-sort="(items) => handleSort(items)">
<li x-sort:item="1">foo</li>
<li x-sort:item="2">bar</li>
<li x-sort:item="3">baz</li>
</ul>
<div x-text="sorted"></div>
</div>
<script>
document.addEventListener('alpine:init', () => {
Alpine.data('sortedData', () => ({
sorted: false,
get getSorted() { return this.sorted },
handleSort(items) {this.sorted = !this.sorted;}
}))
});
</script>
</div>
</body>
</html>