'How can I get the count of Object keys in a Vue template?
I'm trying to count the number of entries in an object and output that to the user. In a method this works fine using Object.keys(this.myObject).length but when outputting that in the template it is always 0.
Example:
<template>
<div>
Selected: {{ selectedCount }}<br> <!-- Always 0 -->
Selected: {{ Object.keys(selected).length }}<br> <!-- Always 0 -->
<div class="referral-redemptions-table">
<b-table
ref="table"
:items="referrals">
<template v-slot:cell(isReferralRedeemed)="data">
<button type="button" class="btn btn-sm btn-primary" @click="markSelected(data.index)" :class="{ 'btn-ghost' : data.item.isSelected }">
{{ data.item.isSelected ? 'Selected' : 'Redeem' }}
</button>
</template>
</b-table>
</div>
</div>
</template>
<script>
export default {
data() {
return {
referrals: [
{
id: 1,
isSelected: false,
name: 'Test',
email: '[email protected]'
},
{
id: 2,
isSelected: false,
name: 'Test',
email: '[email protected]'
},
{
id: 3,
isSelected: false,
name: 'Test',
email: '[email protected]'
},
{
id: 4,
isSelected: false,
name: 'Test',
email: '[email protected]'
},
],
fields: [
{
key: 'name',
label: 'Who',
sortable: true
},
{
key: 'email',
label: 'Email',
sortable: true
},
],
selected: {},
}
},
computed: {
// a computed getter
selectedCount: function () {
return Object.keys(this.selected).length;
}
},
methods: {
// Mark an item as selected
markSelected: function(index) {
// Not selected, add it
if(!this.referrals[index].isSelected) {
this.selected[index] = {
'id' : this.referrals[index].id,
'email' : this.referrals[index].email
};
} else {
delete this.selected[index];
}
console.log(Object.keys(this.selected).length); // Outputs the correct number
this.referrals[index].isSelected = !this.referrals[index].isSelected;
this.$refs.table.refresh();
},
}
}
</script>
Update
To add to the confusion, if I set a data attribute of numSelected: 0 and then set this in the markSelected method using the Object.keys approach then everything works, even Object.keys(selected).length is available in the template, not just the variable I'm setting.
<!-- In template... -->
Selected: {{ numSelected }}<br> <!-- This now shows correctly... -->
Selected: {{ Object.keys(selected).length }} <!-- But so does this. Why would this not work before? -->
markSelected: function(index) {
// [...]
this.numSelected = Object.keys(this.selected).length;
// [...]
},
Solution 1:[1]
I can't find the Vue 3 version of this but I believe you're running into change detection caveats (Vue doesn't know you're adding a new key to the object, so it does not re-render)
See https://v2.vuejs.org/v2/guide/reactivity.html#For-Objects
EDIT Can you clarify if you're on Vue 2 or 3? This answer says this problem shouldn't affect you in Vue 3
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
