Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue.js undefined error on object value when loaded and rendered

OK. I'm not a total newbie and do have some Vue xp but this is bugging me. What really obvious thing am I missing.

I have an object loaded via an ajax call inside a mounted method:

job: {
  "title": "value",  
  "location": {
    "name":"HONG KONG"
  }
}

When I call {{ job.title }} all good. When I call {{ job.location.name }} I have an undefined error but the value renders. When I call {{ job.location }} I get the json object so it is defined.

Aaargh! I'm sure it's really simple but can't possibly see why this isn't as straight forward as it should be.

// Additional

This is my entire Vue class

    const router = new VueRouter({
        mode: 'history',
        routes: []
    });
    const app = new Vue( {
      router,
      el: '#app',
      data: {
        job: {}
      },
      mounted: function () {
        var vm = this
        jQuery.ajax({
            url: 'https://xxx' + this.jobId,
            method: 'GET',
            success: function (data) {
                vm.job = data;
            },
            error: function (error) {
                console.log(error);
            }
        });
      },
      computed: {
        jobId: function() {
            return this.$route.query.gh_jid
        }
      }
    })
like image 288
Dr.ifle Avatar asked Oct 16 '18 08:10

Dr.ifle


2 Answers

When your component renders it tries to get value from job.location.name but location is undefined before ajax request is completed. So I guess error is kind of Cannot read property 'name' of undefined.

To fix this you can define computed property locationName and return, for example, empty string when there is no loaded job object yet:

computed:{
//...
    locationName() {
       return this.job.location ? this.job.location.name : '';
    }
}

Or you can define computed for location and return empty object if there is no location, or you can just add empty location object to your initial data(if you are sure that your API response always has location) like job: { location: {}} all ways will fix your issue.

Also there is a way to fix it with v-if directive in your template:

<div v-if="job.location">
   {{ job.location.name }}
   <!-- other location related stuff -->
</div>
like image 116
Max Sinev Avatar answered Oct 20 '22 13:10

Max Sinev


An ES6 solution for you:

computed: {
  getJobName(){
    return this.job?.location.name
  }
}

Optional Chaining

like image 24
Riza Khan Avatar answered Oct 12 '22 11:10

Riza Khan