Alpine.js x-bound: Binding indeterminate property
by rameel
HTML
<div x-data="tableData()">
<table>
<thead>
<tr>
<th class="checkbox-cell">
<input type="checkbox" &indeterminate="isPartialSelected" &checked="isAllSelected" />
</th>
<th></th>
</tr>
</thead>
<tbody>
<template x-for="(item, index) in items" :key="index">
<tr :class="{ 'selected': item.selected }" x-format>
<td class="checkbox-cell">
<input type="checkbox" &checked="item.selected" />
</td>
<td>{{ item.name }}</td>
</tr>
</template>
</tbody>
</table>
</div>
<script src="https://cdn.jsdelivr.net/npm/@ramstack/alpinegear-bound@1/alpinegear-bound.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/@ramstack/alpinegear-format@1/alpinegear-format.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/alpinejs@3/dist/cdn.min.js" defer></script>
CSS
html {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
table {
width: 100%;
border-collapse: collapse;
}
th,
td {
padding: 12px 15px;
text-align: left;
border-bottom: 1px solid #ddd;
}
th {
background-color: #adadad;
color: white;
}
tr:nth-child(even) {
background-color: #f9f9f9;
}
tr:hover {
background-color: #f1f1f1;
}
.checkbox-cell {
width: 40px;
text-align: center;
}
input[type="checkbox"] {
transform: scale(1.25);
cursor: pointer;
}
.selected {
background-color: #f1f1f1 !important;
}
JavaScript
function tableData() {
return {
items: Array.from({ length: 4 }, (_, i) => ({
name: `Element ${i + 1}`,
selected: i % 2 !== 0
})),
get isAllSelected() {
return this.items.length > 0 && this.items.every(item => item.selected);
},
set isAllSelected(value) {
this.items.forEach(item => item.selected = value);
},
get isPartialSelected() {
let selected = this.items.reduce((count, item) => (item.selected ? count + 1 : count), 0);
return selected > 0 && selected < this.items.length
}
}
}