Vue.js tutorial: Disabling button dynamically based on empty data array

My project involves creating a shopping cart application using 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, ',');
        }
    }
});

This is how I have structured the HTML:

<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 am facing an issue with disabling the "Confirm Button" when the items array is empty. Despite binding the disabled attribute to the button, it does not work as expected. How can I properly disable the button? Any assistance would be greatly appreciated. Thank you.

Answer №1

Your button logic seems fine, but I think your isEmpty() method could be improved by changing its name to isNotEmpty, as currently it is a bit confusing.

It would be more efficient to use the same computed property for both calculations rather than using a method in a v-if.

computed: {
  isEmpty: ({ items }) => items.length === 0
}

As an example (along with some other enhancements)

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(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>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Django: Troubleshooting a 403 CSRF Error when making a post request with Vue.js and axios - "CSRF token missing or incorrect"

As a newbie in web development, I've run into a problem that I can't seem to solve easily. Currently, I'm utilizing Django 3.2.6, django restframework (DRF) 3.14, Vue 3.0, and axios for making API calls. I've created an APIView to lock ...

What steps can I take to streamline this code and enhance its elegance in writing?

Working on some practice problems involving higher-order functions, I managed to solve this particular problem. However, the code I used feels somewhat messy and not as elegant as it could be. Is there a better way to combine map and reduce for a cleaner s ...

Analyzing a tweet containing unique characters

I am currently working on extracting links from tweets, particularly hashtags and mentions. However, I have encountered an issue when the tweets contain special characters like " ...

In search of a way to implement a conditional class binding within the current project

I am working on enhancing a child component within an existing Vue project. My goal is to allow users to add custom classes to the child component. I typically use :class="customClasses" in the dom-element for this purpose. However, there is alre ...

The text becomes distorted and unreadable after the function is applied. It is impossible to decipher the message

There is a function called getResourceText(''), which takes a key as an argument. This function provides a translation of the requested text when it is called. setFilterName = (isFilterChanged, buttonId, filterName) => { switch (filterName ...

Tips for capturing everything in NextJs with getStaticPaths

My current challenge involves utilizing getStaticProps and getStaticPaths to dynamically generate pages at build time. This is my first experience working with CatchAll routes, so I embarked on a search for solutions. Unfortunately, none of the results al ...

What is the reason behind the necessity of adding an extra slash when reloading the page and controller in AngularJS by using $location.path()?

In AngularJS, when you use $location.path() and pass the same URL as the current one, it does not reload the page and controller. However, if you add an extra slash at the end of the URL like this: $location.path('/currentURL/'); it forces a re ...

How can components be utilized with v-edit-dialog?

Hey there, I've been exploring the v-edit-dialog component offered by Vuetify and had a query about its implementation. Currently, I'm structuring my v-data-table in a way where I'm importing a component with props into a template slot. The ...

Using JavaScript to make an AJAX request when a dropdown menu from

Looking to update a graph created with Google Chart API using a drop-down menu. Currently facing a few issues. The dropdown is sending a request to the wrong URL. Instead of /graph/, it's sending data to the current page, which is /services/. This ...

Executing Javascript dynamically in VueJS: Learn how to run code from a string efficiently

Currently, I am developing a website with VueJS that enables selected users to upload scripts for automatic execution upon page load. For instance, here is an example of the type of script a user may input: <script src="https://cdnjs.cloudflare.com/aja ...

Exploring React: Opening a new page without rendering the SideBar component

I currently have an application with a sidebar that navigates to three different pages, all of which include a navigation bar and the sidebar. However, for the next page I want to exclude the sidebar but still include the navigation bar. How can I configur ...

Exploring the proper method for closing connections in Node JS and the pg module

I'm experiencing frustration with the node pg module as I keep encountering a 'too many clients already' error. For instance, in my app.js file, I handle various routes where I query data from postgres. Here's a snippet of how app.js i ...

The Mystery of Socket.io Random Disconnects (version 1.0.6)

Currently, I am utilizing the most recent version of socket.io (1.0.6) to develop an online multiplayer game using Phaser and Node. One issue that has arisen is that after the clients connect, they will sporadically disconnect without any specific pattern. ...

Tips for generating JavaScript within list elements using a PHP script

My PHP script is designed to fetch data from a database and display it as list items within a jQuery Dialog. The process involves creating an array in the PHP while loop that handles the query results, with each list item containing data, an HTML button, a ...

Tips for modifying animations based on screen width thresholds

Currently, I've implemented the data-aos attribute to add a "fade-up-right" animation to an element on my website, as shown below: <div className="des__Container" data-aos="fade-up-right"> However, I now want to modify this ...

I'm curious, does a specific event get triggered when an item is added to a UL element?

Is there an event that gets triggered when a new item is added to a UL list? I am on the lookout for something like this. Thank you! ...

When attempting to run the npm install mathjs command, an error is displayed

Trying to install mathjs using npm but encountering an error: npm install mathjs The error message received is as follows: npm WARN tar TAR_ENTRY_ERROR UNKNOWN: unknown error, write npm WARN tar TAR_ENTRY_ERROR UNKNOWN: unknown error, write npm WARN tar T ...

How can we trigger a function once the API requests within a for loop have completed?

Within this for loop, a maximum of 'time' iterations are specified. With each iteration, a GET call is made to retrieve data that must be added to the obj object. I am seeking a method to determine when all 3 GETS have been completed along with ...

Using TypeScript to filter and compare two arrays based on a specific condition

Can someone help me with filtering certain attributes using another array? If a condition is met, I would like to return other attributes. Here's an example: Array1 = [{offenceCode: 'JLN14', offenceDesc:'Speeding'}] Array2 = [{id ...

Validation of PO Box Addresses Using Regular Expressions

I'm having trouble getting the alert to work with my code. $(document).ready( function (){ $("[id*='txtAddress1S']").blur(function() { var pattern = new RegExp('\b[P|p]*(OST|ost)*\.*\s*[O|o|0]*(ffice|FFICE)*& ...