0

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.

1 Answer 1

2

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>

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.