Dmitry Bubnenkov
Dmitry Bubnenkov

Reputation: 9869

Can't change button text inside setTimeout function

I have got follow Vue-js App:

<html>
    <head>
    <script src="https://cdn.jsdelivr.net/vue/1.0.26/vue.min.js"></script>
        <style>
            .mydiv
            {
                border: 1px black dashed;
                font-size: 2em;
            }
        </style>

    <script>
    var App = null; // it's global because function behind will overwrite it's with Vue App instance
    window.onload = function() 
    {
        new Vue(
        {
              el: '#app',
              data: 
              {
                btntext: "OK"
              },
              methods:
              {
                change: function()
                {
                    this.btntext = "cancel";
                    setTimeout(function() {console.log("test"); this.btntext = "text changed";},1000);
                }
              }

        })  
    }
    </script>
    </head>

    <body>
        <div id="app">
            <div class="mydiv">
                <button v-on:click="change">{{btntext}}</button>
            </div>
        </div>
    </body>
</html>

After running I am getting "test" on console, but button do not change it's text to text changed. Why?

Upvotes: 0

Views: 2022

Answers (2)

Fabien
Fabien

Reputation: 549

The function given to setTimeout does not have the same "this" as your Vue. You could use the bind function:

new Vue({
	el: '#app',
	data: {
		btntext: "OK"
	},
	methods: {
		change: function () {
			this.btntext = "cancel";
			setTimeout(function () {
				console.log("test");
				this.btntext = "text changed";
			}.bind(this), 1000);
		}
	}
})  
.mydiv{
  border: 1px black dashed;
  font-size: 2em;
}
<script src="https://cdn.jsdelivr.net/vue/1.0.26/vue.min.js"></script>
<div id="app">
  <div class="mydiv">
    <button v-on:click="change">{{btntext}}</button>
  </div>
</div>

Upvotes: 1

Marko Gresak
Marko Gresak

Reputation: 8217

You have to understand the context of this keyword. When in setTimeout callback function, this refers to different object that this before it. To solve this issue, you should solve reference to this before the callback or if you're going to use ES2015, you can change function () {...} with arrow function () => {...}, which will automatically save reference to outer this and use it instead of actual this inside the function. But if you're going to use that, make sure it's supported across all your target browsers, or alternatively use a compiler to ES5, most popular of which is Babel.

Upvotes: 1

Related Questions