Reputation: 185
I write a simple shopping cart app with Vue.js:
var app = new Vue({
el: "#app",
data: {
items: [
{ id: 1, name: "Item 00", spec: "spec 00", price: 400, quantity: 1, unit: "unit 00" },
{ id: 2, name: "Item 01", spec: "spec 01", price: 416, quantity: 1, unit: "unit 01" },
]
},
methods: {
isEmpty: function () {
return this.items.length > 0;
},
handleReduce: function (index) {
if (this.items[index].quantity === 1) {
return;
}
this.items[index].quantity--;
},
handleAdd: function (index) {
this.items[index].quantity++;
},
handleRemove: function (index) {
this.items.splice(index, 1);
},
isDisabled: function (index) {
return this.items[index].quantity === 1;
}
},
computed: {
total: function () {
var total = 0;
for (var i = 0; i < this.items.length; i++) {
total += this.items[i].quantity * this.items[i].price;
}
return total;
},
disabled: function (value) {
return this.items.length < 1;
}
},
filters: {
numberFormat: function (value) {
return value.toString().replace(/\B(?=(\d{3})+$)/g, ',');
}
}
});
And my HTML is:
<template v-if="isEmpty()">
<tr v-for="(item, index) in items">
<td>{{ index+1 }}.</td>
<td>{{ item.name }}</td>
<td>{{ item.spec }}</td>
<td class="text-right">{{ item.price | numberFormat }}</td>
<td>
<button class="btn btn-sm btn-secondary" @click="handleReduce(index)" :disabled="isDisabled(index)">-</button>
{{ item.quantity }}
<button class="btn btn-sm btn-secondary" @click="handleAdd(index)">+</button>
</td>
<td>{{ item.unit }}</td>
<td class="text-right">{{ (item.quantity * item.price) | numberFormat }}</td>
<td class="text-right"><button class="btn btn-sm btn-danger" @click="handleRemove(index)">Remove</button></td>
</tr>
</template>
<template v-else>ereNo Items h</template>
<h5 class="text-right mt-5">Total:{{ total | numberFormat }}</h5>
<button class="btn btn-primary" :disabled="disabled">Confirm</button>
I want to disable the "Confirm Button" when items array is empty, and I have bind the disabled
attribute on the button. But It does not work when I empty the items array.
How do I correctly disable the button ? Any help is appreciated. Thanks.
Upvotes: 0
Views: 1837
Reputation: 164731
The button logic looks fine to me but your isEmpty()
method logic is back-to-front for its name. It would only make sense if you called it isNotEmpty
.
I would use the same computed property to determine both since using a method in a v-if
is highly inefficient.
computed: {
isEmpty: ({ items }) => items.length === 0
}
For example (and with a few other improvements)
new Vue({
el: "#app",
data: () => ({
items: [{"id":1,"name":"Item 00","spec":"spec 00","price":400,"quantity":1,"unit":"unit 00"},{"id":2,"name":"Item 01","spec":"spec 01","price":416,"quantity":1,"unit":"unit 01"}]
}),
methods: {
handleReduce (item) {
item.quantity = Math.max(1, item.quantity - 1)
},
handleAdd (item) {
item.quantity++;
},
handleRemove (index) {
this.items.splice(index, 1);
}
},
computed: {
total: ({ items }) => items.reduce((total, { quantity, price }) =>
total + quantity * price, 0),
isEmpty: ({ items }) => items.length === 0
},
filters: {
numberFormat: function(value) {
return value.toString().replace(/\B(?=(\d{3})+$)/g, ',');
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<table id="app">
<tbody>
<template v-if="!isEmpty">
<tr v-for="(item, index) in items" :key="item.id">
<td>{{ index+1 }}.</td>
<td>{{ item.name }}</td>
<td>{{ item.spec }}</td>
<td class="text-right">{{ item.price | numberFormat }}</td>
<td>
<button class="btn btn-sm btn-secondary" @click="handleReduce(item)" :disabled="item.quantity === 1">-</button>
{{ item.quantity }}
<button class="btn btn-sm btn-secondary" @click="handleAdd(item)">+</button>
</td>
<td>{{ item.unit }}</td>
<td class="text-right">{{ (item.quantity * item.price) | numberFormat }}</td>
<td class="text-right"><button class="btn btn-sm btn-danger" @click="handleRemove(index)">Remove</button></td>
</tr>
</template>
<template v-else><tr><td>ereNo Items h</td></tr></template>
</tbody>
<tfoot>
<tr><td colspan="8">
<h5 class="text-right mt-5">Total:{{ total | numberFormat }}</h5>
</td></tr>
<tr><td colspan="8">
<button class="btn btn-primary" :disabled="isEmpty">Confirm</button>
</td></tr>
</table>
Upvotes: 2