Delay the v-alert display after an item is added to the array basket using setTimeout

here is my custom rightTableMenu template

<template>
  <div>
    <h1 align="center">{{ title }}</h1>
    <v-alert type="info" icon="mdi-emoticon-sad" v-if="basketStatus">
      Empty Basket, please add some to basket
    </v-alert>
    <div v-if="changeAlertStatus()">
      <v-alert
        type="success"
        icon="mdi-emoticon-happy"
        :value="alert"
        transition="fade-transition"
      >
        thank you
      </v-alert>
      <v-simple-table>
        <template v-slot:default>
          <thead>
            <tr>
              <th class="text-left">Quantity</th>
              <th class="text-left">Name</th>
              <th class="text-left">Price</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="item in basket" :key="item.name">
              <td>
                <v-icon @click="increaseQuantity(item)">add_box</v-icon>
                <span>{{ item.quantity }}</span>
                <v-icon @click="decreaseQuantity(item)"
                  >indeterminate_check_box
                </v-icon>
              </td>
              <td>{{ item.name }}</td>
              <td>{{ (item.price * item.quantity).toFixed(2) }}</td>
            </tr>
          </tbody>
        </template>
      </v-simple-table>
      <v-divider color="black"></v-divider>
      <v-row id="basket_checkout" style="margin: 0">
        <v-col>
          <p>Subtotal:</p>
          <p>Delivery:</p>
          <p>Total amount:</p>
        </v-col>
        <v-col class="text-right">
          <p>${{ subTotalResult }}</p>
          <p>$10</p>
          <p class="font-weight-bold">${{ totalPriceResult }}</p>
        </v-col>
      </v-row>
      <v-row>
        <v-spacer></v-spacer>
        <v-btn depressed class="orange" v-on:click="submitOrder">
          <v-icon>shopping_basket</v-icon>
        </v-btn>
      </v-row>
    </div>
  </div>
</template>

there are two alerts in this template. One shows up when the basket array is empty, determined by the following method:

basketStatus() {
  return this.$store.getters.basket.length === 0;
},

This method is a computed property and is part of the data section below:

data() {
    return {
      title: "Current Basket",
      alert: false,
    };
  },

For the second alert, I want it to be visible for a few seconds before disappearing. Here's what I've implemented so far:

async changeAlertStatus() {
      if (this.$store.getters.basket.length !== 0) {
        this.alert = true;
        try {
          const response = await setTimeout(() => {
            this.alert = false;
          }, 100);
          console.log("this is the resonse " + response);
        } catch (err) {
          console.log("fetch failed", err);
        }
      } else {
        this.alert = false;
      }
    },

This method handles the timing for showing and hiding the alert. However, there seems to be an issue with integrating this function into the div without using the v-if directive. The async changeAlertStatus also appears to get stuck in an infinite loop based on the console logs, and the alert does not disappear as intended.

Any insights or suggestions on how to address these issues would be greatly appreciated!

If more information is required, feel free to ask.

Thank you!

Also, here's the code snippet for my leftTableMenu:

<template>
  <div>
    <div v-if="showError['situation']">
    <!-- 
basically, when you close the alert, the value of the alert goes to false
so you need to turn it to true when there is an error  :value="showError.situation" -->
      <app-alert :text="showError.message"  :value.sync="showError.situation"></app-alert>
    </div>
    <h1 align="center">{{ title }}</h1>
    <v-simple-table od="menu-table">
      <template v-slot:default>
        <thead>
          <tr>
            <th class="text-left">Name</th>
            <th class="text-left">Price</th>
            <th class="text-left">Add</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="item in menuItems" :key="item.name">
            <td>
              <span id="id_name">{{ item.name }}</span>
              <br />
              <span id="menu_item_description">{{ item.description }}</span>
            </td>
            <td>{{ item.price }}</td>
            <td>
              <v-btn text v-on:click="addToBasket(item)">
                <v-icon color="orange">1add_shopping_cart</v-icon>
                <span></span>
              </v-btn>
            </td>
          </tr>
        </tbody>
      </template>
    </v-simple-table>
  </div>
</template>
<script>
export default {
  name: 'LeftTableMenu',
  data() {
    return {
      title: "Menu Items", 
    };
  },
  methods: {
    addToBasket(item) {
      this.$store.dispatch("addToBasket", item);
    },
  },
  computed: {
    showError() {
      return this.$store.getters.showError;
    },
    menuItems() {
      return this.$store.getters.menuItems;
    },
  },
};

Answer №1

One way to track changes in your computed property is by adding a watcher.

With this approach, you can respond to any change by updating the data accordingly, such as displaying a "Success" alert briefly before hiding it again after a set time interval.

To provide more clarity, I have updated some parameter names in the example below:

I've renamed the computed property to emptyBasket

computed: {
  emptyBasket() {
    return this.$store.getters.basket.length === 0;
  }
},

In addition, I have added a new property called showSuccessAlert to the data object

data() {
  return {
    showSuccessAlert: false
  };
},

Here's a watcher that keeps track of changes in the emptyBasket property and updates the showSuccessAlert accordingly:

watch: {
  emptyBasket: {
    immediate: true,
    handler(newVal, oldVal) {
      this.showSuccessAlert = !newVal;
      setTimeout(() => {
        this.showSuccessAlert = oldVal;
      }, 5000);
    }
  }
}

The watcher will be triggered immediately (although it might not be necessary), with newVal and oldVal representing the new and old values of emptyBasket. When newVal is false, it indicates that the basket is not empty, leading to the update of showSuccessAlert = !newVal

If you'd like to see the code in action, I have created a simple sandbox using your provided code.

You can view it here:

https://codesandbox.io/s/smoosh-cherry-ngpqu?file=/src/App.vue

Answer №2

It is advisable to keep an eye on the backStatus and then proceed with your alert tasks

watch: {
    // This function will be triggered whenever there are changes in the question
    backStatus: function (newVal, oldVal) {
        this.alert = newVal;
        const response = setTimeout(() => {
            this.alert = oldVal;
        }, 100); 
        // Swap the values if necessary
    }
}

You may also need to use immediate, depending on how you want to display things.

https://v2.vuejs.org/v2/guide/computed.html#Watchers

Answer №3

Instead of invoking changeAlertStatus within the v-if directive, would it be possible to directly bind it to the this.alert property? This way, when the Add to Cart button is clicked, its function can simply set this.alert to true, triggering the display of alerts. Right after setting this.alert to true, you can set a setTimeout function to switch it back to false.

For example: (Please bear with the abstract nature of this example, as it seems like there might be some missing code related to the add to cart button in the original post)

<template>
  <div id="app">
    <div class="alerts" v-if="alert">
      <div>Thank you</div>
    </div>
    <button @click="handleAddToCart">
      Add to cart
    </button>
  </div>
</template>

<script>
module.exports = {
  el: "#app",
  data: {
    alert: false,
    basketStatus: false
  },
  methods: {
    handleAddToCart() {
      this.alert = true;
      setTimeout(() => {
        this.alert = false;
      }, 3000);
    }
  }
};
</script>

Answer №4

To implement a timeout for alerts, you can utilize watch as suggested by others:

<template>
  <div class="w-full">

    <div class="w-full" v-for="item in cart" :key="item.id">
      <p>{{item.name}}</p>
    </div>

    <div class="w-full p-2 bg-yellow" v-if="alert">
      <p>Your cart is empty</p>
    </div>
  </div>
</template>

<script>
import axios from 'axios'
export default {
  name: 'CartList',
  data() {
    return {
      cart: [],
      alert: true
    }
  },
  watch: {
    cart(val) {
      if(!val.length) {
        this.alert = true
      } else {
        setTimeout(() => {
         this.alert = false
        }, 2000)
      }

    }
  },
  mounted() {
    this.getCart()
  },
  methods: {
    getCart() {
      axios('/cart/get').then((response) => {
        this.cart = response.data.cart
      })
    }
  }
}
</script>

To add a timeout to your request function directly, you can modify it like so:

getCart() {
  axios('/cart/get')
  .then((response) {
    if(response.data.cart.length) {
      setTimeout( () => { 
        this.alert = false
      }, 2000)
    }
  })
}

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

Error: The Tabs component is expecting a different `value`. The Tab with the current `value` ("0") is not present in the document structure

I am encountering an issue while using MUI tabs. The error message I receive is as follows: MUI: The value assigned to the Tabs component is not valid. The Tab with this value ("0") does not exist in the document layout. Please ensure that the tab item is ...

What could be the reason for webpack not making jQuery available as a global variable?

For my current project, I am utilizing several npm modules by integrating them using yarn and webpack. These essential modules include jquery, bootstrap3, moment, jquery-tablesort, jquery-ujs, bootstrap-select, and livestamp. Some of these plugins require ...

Error encountered on NodeJS server

Today marks my third day of delving into the world of Angular. I've come across a section that covers making ajax calls, but I've hit a roadblock where a tutorial instructed me to run server.js. I have successfully installed both nodejs and expre ...

What is the correct way to update an array of objects using setState in React?

I am facing an issue where I have an array of objects that generates Close buttons based on the number of items in it. When I click a Close button, my expectation is that the array should be updated (removed) and the corresponding button element should dis ...

Step by step guide on integrating ReactJS into your current node.js backend application

I am currently working on a basic node.js API Setup: | project-name | public | index.html | ... some static js/css | app.js | package.json app.js var express = require('express'), bodyParser = require('body-parser'), ...

Using the val() function on a select element can occasionally result in a null value

Having an issue with my select. For some reason, when I use $(".test").val(), it sporadically returns null. Can't seem to figure out what's causing this inconsistency. console.log($('.test').val()); <script src="https://ajax.googl ...

What steps can be taken to encourage a client to download a file from a webpage that is password-protected?

I've encountered a challenge with my FTP server, as it is password protected and I want users to be able to download from it via a button on my website without revealing the password. Currently, I am using puppeteer to bypass the authentication proces ...

My Vue frontend project is encountering an error during compilation that states "this relative module module was not found."

I have created a vue frontend to interact with my spring backend, which is working well. However, when I compile the frontend, it compiles to 98% and shows an error message: ERROR Failed to compile with 1 error 11:24:51 The relative module was not foun ...

Newbie mishap: Utilizing an array retrieved from a function in javascript/jquery

After submitting the form, I call a function called getPosts and pass a variable str through it. My aim is to retrieve the data returned from the function. // Triggered upon form submission $('form#getSome').submit(function(){ var str = $("f ...

Ways to position cursor at the end in the Froala Editor

My current dilemma involves the need to position the focus/cursor at the end of text that is loaded within the Froala editor. I attempted to accomplish this using the focus event of Froala (events.focus), but unfortunately, it did not yield the desired out ...

Using async/await in React to retrieve data after a form submission

I am currently facing an issue with displaying data fetched from an API on the screen. My goal is to retrieve data when a user types something in a form and clicks the submit button. The error message I am encountering is: TypeError: Cannot read propert ...

Using jQuery to assign a specific value to all select boxes

I am facing a challenge where I need to change the values of all select boxes on my page to a specific number. Here is the HTML structure: <select> <option value="-1" <option value="55">ENABLE</option> <option value= ...

JavaScript array reformatting executed

I have an array object structured like this. [ {student_code: "BBB-002-XRqt", questions: "Length (in inches)", answer: "8953746", time: "00:00:08:15"}, {student_code: "CCC-003-TYr9", questions: "He ...

Submitting forms that contain files using jQuery and AJAX

Despite searching through numerous questions on this topic, I have yet to find a solution to my specific issue. My objective is to successfully submit an entire form, potentially containing files as well. The code I currently have is not working: $(target ...

Navigating through object arrays using a loop

I have multiple arrays within an object that I would like to iterate through using numeric values. This is necessary in order to assign them to different slots in an accordion loop. The JSON file containing the data looks similar to this (Pokemon used as a ...

What is the formula to determine if x is greater than y and also less than z?

I need help determining if a number falls within the range of greater than 0 but less than 8 using JavaScript. Can anyone assist me with this? Here is my attempt at it: if (score > 0 && score < 8) { alert(score); } ...

Tips for implementing <select> with vee-validate?

I am struggling to integrate my form with vee-validate. According to the documentation, it recommends using <Field />, but I am having difficulty implementing it in a Select form. How can I accomplish this? Thank you. <Form @submit="submit&q ...

Direct your attention to alternative data sources following the selection of an item in the typeahead search feature

Having some trouble with angular-ui bootstrap: I am using 2 input elements: <input type="text" ng-model="selected" uib-typeahead="state for state in states | filter:$viewValue | limitTo:8" typeahead-on-select="focusSuccessive($item, $model, $label, $ev ...

Building a Wordpress website with AJAX functionality using only raw Javascript and no reliance on Jquery

So, I have a custom script named related-posts.php, and I want to insert it into posts only when the user scrolls. In addition, I have an enqueued script file in WordPress that loads in the footer, where I have written AJAX code like this: var xmlhttp = ...

Mixing up letters using a shuffle function

Seeking assistance as a newcomer here. I have a shuffle function triggered by pressing the reset button with class="reset" on the img tag. How can I make it load shuffled from the start? So that when loading this page, the letters do not appear in alphabet ...