Binding reactively to array length
Clonkex opened this issue · comments
Say I have this:
const selectedProductIds = reactive([]);
return html`
<div>
<span>Selected products: ${() => selectedProductIds.length}/${productCount}</span>
</div>
...
<input type="checkbox" ${selectedProductIds.includes(productData.internalId) ? 'checked' : ''} @input="${e => {
if (e.target.checked) {
if (!selectedProductIds.includes(productData.internalId)) {
selectedProductIds.push(productData.internalId);
}
} else {
if (selectedProductIds.includes(productData.internalId)) {
selectedProductIds.splice(selectedProductIds.indexOf(productData.internalId), 1);
}
}
selectedProductIds.length = selectedProductIds.length + 1; // <----- how can I not have to do this?
selectedProductIds.length = selectedProductIds.length - 1;
}}"/>
How can I avoid having to do the jankiness of those last two lines? If I only push to the array or splice from it, the reactive length binding doesn't update.
I think the issue here is that you’re reactive data is the array itself instead of a property of the array. Consider your "reactive" more like a store, you want to set data on properties of your reactive rather then itself. So:
const store = reactive({ selectedProductIds: [] });
// ...
html`<span>Selected products: ${() => store.selectedProductIds.length}/${productCount}</span>`
These changes propagated throughout the code should get you sorted.
Ah I nearly just tried that, but I figured arrays are objects and I'm not assigning the array at any point so it should be fine.
Wrapping it in another object does indeed fix the issue, thanks!