mat.hudak
mat.hudak

Reputation: 3163

Vue - error in render when trying to display data from nested object

I'm dealing with a strange problem in Vue. I'm trying to display a list of employees in the table. Employees are provided by a REST service and response looks exactly like this (shown below is one item from the paginatedList):

{
  "id": 10a,
  "code": 0000,
  "firstName": "John",
  "lastName": "Doe",
  "level": "WORKER",
  "specialization": {
    "id": 20,
    "name": "Default",
    "taem": {
      "id": 2,
      "name": "Builders",
      "system": false,
      "teamLead": null,
      "specializationDtos": null,
      "categoryDtos": null
    }
  },
  "team": {
    "id": 2,
    "name": "Builders",
    "system": false,
    "teamLead": null,
    "specializationDtos": null,
    "categoryDtos": null
  },
  "coachDto": null,
  "roles": [
    "DL"
  ]
}

In Vue, I'm using Vuex actions to preprocess raw data and return paginated list of employees. Then I'm trying to print it in the table using v-for like this:

<tr v-for="item in paginatedList" :key="item.id"
  v-on:click="selectRow(item)"
  v-bind:class="{selectedRow: selectedItem === item}"
>
  <td>{{item.id}}</td>
  <td>{{item.name}}</td>
  <td>{{item.team.name}}</td>
</tr>

And this is where it fails (kind of). Even though the table is displayed with no employee missing the team name, I'm getting warning from Vue:

[Vue warn]: Error in render: "TypeError: Cannot read property 'name' of undefined"

After clicking on the line of code, which causes the warning, it points to the place where I'm trying to render {{item.team.name}}

My first thought was that the employee with missing team was simply not displayed. In order to check it I came up with following workaround:

<td>{{getTeamName(item.team)}}</td>

And the method:

getTeamName(team) {
  return (team ? team.name : 'FAILED');
}

Warning/error disappears but there is no employee with FAILED team. What exactly is the problem with this? Is it possible to display properties of nested object like that or should I avoid it?

Upvotes: 1

Views: 2261

Answers (2)

Natalie
Natalie

Reputation: 11

It looks as though you have mis-spelled team in your object:

 "taem": {
      "id": 2,
      "name": "Builders",
      "system": false,
      "teamLead": null,
      "specializationDtos": null,
      "categoryDtos": null
    }

which I guess is why it can't render name of undefined.

Upvotes: 0

webnoob
webnoob

Reputation: 15934

This can happen when the object your iterating doesn't yet have the data you're expecting but by the time you come to debug it, it does. I find this most often when using data which you're getting from a promise. With that in mind, just add a check to make sure that your data has loaded properly, in your case, this should suffice:

<tr v-for="item in paginatedList" :key="item.id"
  v-on:click="selectRow(item)"
  v-bind:class="{selectedRow: selectedItem === item}"
>
  <div v-if="item.team">
    <td>{{item.id}}</td>
    <td>{{item.name}}</td>
    <td>{{item.team.name}}</td>
  </div>
</tr>

I generally have a dataLoaded prop on my component which is initialised as false but set to true once I've finished messing with my data to avoid issues like this. I'd then check v-if="dataLoaded" around my whole component.

Upvotes: 4

Related Questions