Reputation: 6739
this is my 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>
as you see there are two alerts one is showing when there is not item inside the array basket by checking the following
basketStatus() {
return this.$store.getters.basket.length === 0;
},
which is computed property my data property section is
data() {
return {
title: "Current Basket",
alert: false,
};
},
but for the second v-alert, I wanna to have the alert to be shown and disappear after few sec and so far I have done the following for it
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;
}
},
which is a method I am confused how to interject the function inside the div part without using v-if directive and my async changeAlertStatus gets in the infinite loop when I check it inside the console and the v-alert does not get disappear
any thoughts on that?
if there is more info needed , please let me know
thank you
just in case my leftTableMenu
is follows
<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;
},
},
};
Upvotes: 1
Views: 631
Reputation: 12669
Should probably be watching backStatus
and then do your alert stuff
watch: {
// whenever question changes, this function will run
backStatus: function (newVal, oldVal) {
this.alert = newVal;
const response = setTimeout(() => {
this.alert = oldVal;
}, 100);
// swap the vals around if needed
}
}
maybe you might need immediate too, but that's up to how your want to display things.
https://v2.vuejs.org/v2/guide/computed.html#Watchers
Upvotes: 1
Reputation: 111
You can achieve this timeout on alert using watch like the others guys said:
<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>
But you can add some extra code to your request function and add the timeout there too:
getCart() {
axios('/cart/get')
.then((response) {
if(response.data.cart.length) {
setTimeout( () => {
this.alert = false
}, 2000)
}
})
}
Upvotes: 0
Reputation: 1281
You can add a watcher on your computed property to see if it's changed.
When it changes you can update your data to show or the "Success" alert and then set a timeout to hide it back again after some time.
Here is an updated example with some changed param names for clarity.
I changed the computed name to be emptyBasket
computed: {
emptyBasket() {
return this.$store.getters.basket.length === 0;
}
},
I added showSuccessAlert to data
data() {
return {
showSuccessAlert: false
};
},
And here it the watcher that updates the showSuccessAlert
watch: {
emptyBasket: {
immediate: true,
handler(newVal, oldVal) {
this.showSuccessAlert = !newVal;
setTimeout(() => {
this.showSuccessAlert = oldVal;
}, 5000);
}
}
}
The watcher will be triggered immediately (not sure you need it),
newVal
and oldVal
are representing the new and old state of emptyBasket
.
So when newVal
is false
it means that the basket is not empty, hence the update of showSuccessAlert = !newVal
I created a simple working sandbox with your code.
Here is the link:
https://codesandbox.io/s/smoosh-cherry-ngpqu?file=/src/App.vue
Upvotes: 1
Reputation: 2178
Rather than calling changeAlertStatus
in the v-if
directive, can that just be bound to the this.alert
property? Then, when the Add to Cart button is clicked, its callback can set this.alert
to true, causing the alerts to display. Just after setting this.alert
to true, register the setTimeout to revert it back to false
Example: (Please excuse the abstract-ness of it, I feel like this is some missing code from the original post, specifically the add to cart button)
<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>
Upvotes: 0