Nate Beers
Nate Beers

Reputation: 1425

Vue.js 2 Cannot change value of data property inside method

I am trying to update taxParentId with the new id that i retrieve with my API call inside the getTaxParentId function, but I cannot get it to change. I can console.log the value fine inside the method, but it won't update it. It seems to be an issue of scope, but i have set $this = this to take care of this, however, it is not working.

the getPostType method works fine and properly updates the data value.

var newVue = new Vue({
  el: '#app',
  data() {
    return{
      posts: [],
      taxonomy: '',
      postType: '',
      taxParentSlug: '',
      taxParentId: 0
    }
  },
  created (){
    let $this = this;
    this.getPostType(location.href);
    this.getTaxParent(location.href)
    this.getTaxParentId();
    this.getPosts();

  },
  methods: {
    getPostType: function(currentURL){
        if (currentURL.includes('residential')) {
            this.postType = 'residential';
        }else if(currentURL.includes('commercial')){
            this.postType = 'commercial';
        }else if (currentURL.includes('auto')) {
            this.postType = 'auto';
        }
    },
    getTaxParent: function(currentURL){
        if (currentURL.includes('solar')) {
            this.taxParentSlug = 'solar';
        }else if(currentURL.includes('decorative')){
            this.taxParentSlug = 'decorative';
        }else if (currentURL.includes('safety-security')) {
            this.taxParentSlug = 'safety-security';
        }
    },
    getTaxParentId: function(){
        let $this = this;

        axios
          .get(apiRoot + $this.postType + '-categories')
          .then(function (response) {
            response.data.forEach(function(item){
                if (item.slug == $this.taxParentSlug) {
                    $this.taxParentId = item.id;
                }
            });
          }
        )
    },
    getPosts: function(){
        let $this = this;

        console.log(apiRoot + $this.postType + '-categories?parent=' + $this.taxParentId)
        axios

          .get(apiRoot + $this.postType + '-categories?parent=' + $this.taxParentId)
          .then(function (response) {
            $this.posts = response.data;
            console.log($this.posts)
          }
        )
    },
  },

});

Upvotes: 0

Views: 2189

Answers (2)

Nathan Bland
Nathan Bland

Reputation: 245

Since you are already using promises, you should be able to build a promise chain to solve your async issue.

Take your current function: ```javascript getTaxParentId: function(){ let $this = this;

    axios
      .get(apiRoot + $this.postType + '-categories')
      .then(function (response) {
        response.data.forEach(function(item){
            if (item.slug == $this.taxParentSlug) {
                $this.taxParentId = item.id;
            }
        });
      }
    )
},

and make it return a value, even if it is just the response ```javascript getTaxParentId: function(){ let $this = this;

    axios
      .get(apiRoot + $this.postType + '-categories')
      .then(function (response) {
        response.data.forEach(function(item){
            if (item.slug == $this.taxParentSlug) {
                $this.taxParentId = item.id;
            }
        });
        return response
      }
    )
},

Then in your created() function, you can chain the call..

created (){
    let $this = this;
    this.getPostType(location.href);
    this.getTaxParent(location.href)
    this.getTaxParentId()
     .then(function (response) {
        this.getPosts();
    })
  },

This should force this.getPosts() to wait for getTaxParentId to be complete.

Upvotes: 0

Steven Spungin
Steven Spungin

Reputation: 29179

Because of the async, add watchers to your data, and log there.

watch:{
    posts(value){console.log(value))},
    taxParentId(value){console.log(value))}
}

Ideally you would get a promise from each call, and then wait for them all. If one call is dependent on another, you need to put the second call in a then() block, or even better, await it (async/await)

Using this, all you need to do is return the promise, and it will be synchronized.

  async created (){
    let $this = this;
    await this.getPostType(location.href);
    await this.getTaxParent(location.href)
    await this.getTaxParentId();
    await this.getPosts();
  },

So much cleaner then chaining then blocks. You can wrap the entire block in a SINGLE catch, and trap all exceptions AND all rejections. Of course, if the calls are not dependent, you may want to call them in parallel and not await.

Upvotes: 1

Related Questions