91

I have the following code:

{
  data: function ()  {
    return {
      questions: [],
      sendButtonDisable: false,
    }
  },

  methods: { 
    postQuestionsContent: function () {
      var that = this;
      that.sendButtonDisable = true;
    },
  },
},

I need to change sendButtonDisable to true when postQuestionsContent() is called. I found only one way to do this; with var that = this;.

Is there a better solution?

Gonçalo Peres
  • 11,752
  • 3
  • 54
  • 83
Dmitry Bubnenkov
  • 9,415
  • 19
  • 85
  • 145
  • This should work without `var this = that` (in fact, the way you show it in your example is meaingless, you could leave it out). functions in the `methods:` object will be bound to the current instance. I assume you have left something out in your example - are you doing any AJAX calls and try to change the value inside a callback or something? – Linus Borg Mar 23 '16 at 17:33
  • In my case I have my method attached to an event listener on a button. I do not understand vuejs do any more. – The Oracle Jan 02 '18 at 18:27

4 Answers4

90

Inside methods if you don't have another scope defined inside, you can access your data like that:

this.sendButtonDisable = true; 

but if you have a scope inside the function then in vue is a common usage of a variable called vm (stands for view model) at the beginning of the function, and then just use it everywhere like:

vm.sendButtonDisable = false;

An example of vm can be seen in the Vue official documentation as well.

complete example:

data: function ()  {
  return {
     questions: [],
     sendButtonDisable : false
  }
},

methods: { 
  postQuestionsContent : function() {
    // This works here.
    this.sendButtonDisable = true;

    // The view model.
    var vm = this;

    setTimeout(function() {
      // This does not work, you need the outside context view model.
      //this.sendButtonDisable = true;
      
      // This works, since wm refers to your view model.
      vm.sendButtonDisable = true;
    }, 1000); 
  }
}
tony19
  • 125,647
  • 18
  • 229
  • 307
V. Sambor
  • 12,361
  • 6
  • 46
  • 65
  • 12
    THIS answer is so useful for vue noobs (voobs?). The Vue 2 documentation even makes use of **vm = this** on the following page: https://vuejs.org/v2/guide/computed.html#Watchers But it would be easy to oversee this reading through the documentation. – A2D Mar 29 '19 at 09:33
  • 3
    up for "voobs"! – victorf Jan 23 '20 at 10:18
  • 2
    also note it will NOT work if we use Arrow function instead of Normal function in `methods` – Matianda Aug 09 '21 at 15:19
  • 2
    Note for people finding this: If you are using lambda notation `this` will not work, so instead use `function(){}` – Jesper Hustad Aug 11 '21 at 20:05
34

It depends on how you call your postQuestionsContent method (if you call it asynchronously, you might need to bind the this context).

In most cases, you should be able to access it using this.$data.YOURPROPNAME, in your case this.$data.sendButtonDisable:

data: function ()  {
  return {
     questions: [],
     sendButtonDisable : false
  }

  },

  methods: 
  { 
     postQuestionsContent : function()
     {
        this.$data.sendButtonDisable = true;
     }
  }
nils
  • 25,734
  • 5
  • 70
  • 79
  • 2
    Some some reason this does not work. I think the community should review this issue. – The Oracle Jan 02 '18 at 18:23
  • 5
    Hi @TheOracle the question and aswer was valid in the realm of vue 0.x versions. 2.x should work normally without `$data`. – nils Jan 04 '18 at 12:51
  • 2
    I'm getting this issue using 2.5.17. Might have to report it as a bug, but `$data` works. – Blieque Oct 16 '18 at 16:02
  • 1
    this.$data.something is undefined. Better to use this.something – grant zukowski Nov 20 '18 at 22:33
  • 1
    Using `Vue-cli 3.x` I can NOT access properties inside `data ()` from e.g. `methods` or `computed` with `this.property` or with `this.$data.property`. Is there another way? – sunwarr10r Feb 19 '19 at 20:40
  • It is not an issue at all. The correct way of accessing `sendButtonDisable` using `this.$data` is like this: `this.$data[sendButtonDisable]`, because `this.$data`'s array nature. Cheers. – andcl Jun 28 '19 at 18:03
18

Try this instead

...
methods: 
{ 
   postQuestionsContent ()
   {
      this.sendButtonDisable = true;
   }
}

Registering your methods in the above manner should resolve the issue.

The Oracle
  • 2,373
  • 3
  • 26
  • 44
  • 3
    Can you explain what's going on here? Why does this work? – Umair A. Nov 16 '19 at 06:29
  • Are you using Nuxtjs? @UmairA. – The Oracle May 22 '20 at 12:02
  • 2
    @UmairA. From the Vue documentation: `Note that you should not use an arrow function to define a method (e.g. plus: () => this.a++). The reason is arrow functions bind the parent context, so this will not be the Vue instance as you expect and this.a will be undefined.` Here: https://vuejs.org/v2/api/#methods – Connor May 30 '20 at 17:52
0

I tried both this.$data.sendButtonDisable and vm.sendButtonDisable and did not work for me.

But I got it working with outer_this = this, something like:

methods: {
    sendForm(){
        var outer_this;
        
        outer_this = this;
        
        $.ajax({
                url: "email.php",
                type: "POST",
                dataType: "text",
                data: {
                    abc: "..."
                },
                success: function(res){
                    if(res){
                        //...
                        
                        outer_this.sendButtonDisable = false;
                    }else{
                        //...
                    }
                }
        });
    }
},
ajax333221
  • 11,436
  • 16
  • 61
  • 95