Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue equivalent of setTimeout?

I'm making a shopping cart system with Laravel and Vue. When I add an item to the basket, I display a confirmation message by toggling a Vue variable being watched by a v-if:

<div class="alert alert-success" v-if="basketAddSuccess" transition="expand">Added to the basket</div>

And the JS:

addToBasket: function(){
                item = this.product;
                this.$http.post('/api/buy/addToBasket', item);
                this.basketAddSuccess = true;
            }

(And yes, I will be adding this in a then-catch shortly).

This works fine and the message appears. However, I'd like the message to disappear again after a certain time, say a few seconds. How can I do this with Vue? I've tried setTimeOut but Vue doesn't seem to like it, saying it's undefined.

EDIT: I was misspelling setTimeout like an idiot. However, it still doesn't work:

My function is now:

addToBasket: function(){
                item = this.photo;
                this.$http.post('/api/buy/addToBasket', item);
                this.basketAddSuccess = true;
                setTimeout(function(){
                    this.basketAddSuccess = false;
                }, 2000);
            }
like image 411
flurpleplurple Avatar asked Jul 15 '16 14:07

flurpleplurple


People also ask

What can I use instead of setTimeout?

The setInterval method has the same syntax as setTimeout : let timerId = setInterval(func|code, [delay], [arg1], [arg2], ...) All arguments have the same meaning. But unlike setTimeout it runs the function not only once, but regularly after the given interval of time.

What is difference between setInterval and setTimeout?

setTimeout(expression, timeout); runs the code/function once after the timeout. setInterval(expression, timeout); runs the code/function repeatedly, with the length of the timeout between each repeat.

How do I clear set timeout?

To cancel a setTimeout() method from running, you need to use the clearTimeout() method, passing the ID value returned when you call the setTimeout() method.

What is VUE use?

Vue. js is a progressive framework for JavaScript used to build web interfaces and one-page applications. Not just for web interfaces, Vue. js is also used both for desktop and mobile app development with Electron framework.


4 Answers

Arrow Function

The best and simplest way to solve this problem is by using an arrow function () => {}:

    addToBasket() {
        var item = this.photo;
        this.$http.post('/api/buy/addToBasket', item);
        this.basketAddSuccess = true;
        // now 'this' is referencing the Vue object and not the 'setTimeout' scope
        setTimeout(() => this.basketAddSuccess = false, 2000);
    }

This works because the this of arrow functions is bound to the this of its enclosing scope- in Vue, that's the parent/ enclosing component. Inside a traditional function called by setTimeout, however, this refers to the window object (which is why you ran into errors when you tried to access this.basketAddSuccess in that context).

Argument Passing

Another way of doing this would be passing this as an arg to your function through setTimeout's prototype using its setTimeout(callback, delay, arg1, arg2, ...) form:

    addToBasket() {
        item = this.photo;
        this.$http.post('/api/buy/addToBasket', item);
        this.basketAddSuccess = true;
        //Add scope argument to func, pass this after delay in setTimeout
        setTimeout(function(scope) {
             scope.basketAddSuccess = false;
        }, 2000, this);
    }

(It's worth noting that the arg passing syntax is incompatible with IE 9 and below, however.)

Local Variable

Another possible, but less eloquent and less encouraged, way is to bind this to a var outside of setTimeout:

    addToBasket() {
        item = this.photo;
        this.$http.post('/api/buy/addToBasket', item);
        this.basketAddSuccess = true;
        //Declare self, which is accessible inside setTimeout func
        var self = this;
        setTimeout(function() {
             self.basketAddSuccess = false;
        }, 2000);
    }

Using an arrow function would eliminate the need for this extra variable entirely however, and really should be used unless something else is preventing its use.

like image 109
g.annunziata Avatar answered Oct 22 '22 07:10

g.annunziata


after encountering the same issue, I ended up on this thread. For future generation's sake: The current up-most voted answer, attempts to bind "this" to a variable in order to avoid changing the context when invoking the function which is defined in the setTimeout.

An alternate and more recommended approach(using Vue.JS 2.2 & ES6) is to use an arrow function in order to bind the context to the parent (Basically "addToBasket"'s "this" and the "setTimeout"'s "this" would still refer to the same object):

addToBasket: function(){
        item = this.photo;
        this.$http.post('/api/buy/addToBasket', item);
        this.basketAddSuccess = true;
        setTimeout(() => {
            this.basketAddSuccess = false;
        }, 2000);
    }
like image 20
Samuel Bergström Avatar answered Oct 22 '22 07:10

Samuel Bergström


Add bind(this) to your setTimeout callback function

setTimeout(function () {
    this.basketAddSuccess = false
}.bind(this), 2000)
like image 31
Kevin Muchwat Avatar answered Oct 22 '22 08:10

Kevin Muchwat


ES6 can bind 'this'

setTimeout(() => {

 },5000);

like image 19
陈奕璇 Avatar answered Oct 22 '22 08:10

陈奕璇