Reputation: 227
I have an array of objects (users) gotten by an api request. Its structure is something like this:
api response: (5) [{…}, {…}, {…}, {…}, {…}]
Inside this array, the objects are like this:
0: {
user_address_string: ('Street 1')
id: (3)
avatar: (img')
...
user: {
id: 1
first_name: 'Lucas'
last_name: 'Smith'
}
},
1: {...},
2: {...},
....
]
It is just a sample just to show you the structure. As you can see, among its properties there's another object named user{}. I need to display only the properties contained in this object. I would like to keep the structure of the table I was using before I got this new api (which didn't have objects as properties).
<b-table
responsive
v-if="users && users.length > 0"
:fields="fields"
:items="users"
>
The template should be something like this:
<template slot-scope="data">
{{ data.item.user }}
</template>
data.item
should be the single user in the users array of objects, and with .user
I should be able to access the properties of its object property user. (Going further data.item.user.first_name
, etc, to access the single properties in it). What am I missing?
Nothing is rendered on the screen.
No errors in the console though.
In the script I have:
users: [],
fields: [
{ key: 'id', label: 'ID'},
{ key: 'name', label: 'Name' }
]
So, how should I write the template for displaying the nested object’s properties?
Also, the directive v-if="users && users.length > 0"
in the b-table should still work, right? It is still an array, but of objects this time. Please correct me if I am wrong.
Thank you
Upvotes: 3
Views: 6068
Reputation: 590
An easy way to do it is by using a formatter in fields definition:
data() {
return {
fields: [
{
key: "avg_score",
label: this.$t("avgScore"),
sortable: true,
sortByFormatted: true,
formatter: (value, key, item) => item.stats.avg_score?.text
},
],
items: [...your item list]
}
}
And in the template:
<b-table :items="items" :fields="fields"></b-table>
The formatter will print the specified key or value automatically.
Upvotes: 0
Reputation: 227
As @Troy Morehouse suggested, I just needed to redefine the fields definition as
{ key: 'user.first_name', label: 'First name' }
**UPDATE after @artworkjpm comment: The HTML code should be something like this:
<b-table
v-if="users && users.length > 0 && !isLoading"
id="table-transition-userList"
:key="users.id"
responsive
:tbody-tr-class="userStatus"
:tbody-transition-props="transProps"
:fields="fields"
:items="users"
>
<template
v-slot:cell(fullName)="data"
>
{{ data.item.user.first_name }} {{ data.item.user.last_name }}
</template>
<template
v-slot:cell(buttons)="data"
>
<b-button
v-b-tooltip.hover
title="See plan"
class="btn-plan p2"
variant="primary"
:disabled="!data.item.user.is_active"
@click.prevent="seePlan(data.item), selectUser(data.item)"
>
<span class="svg-container">
<svg-icon icon-class="route" />
</span>
</b-button>
</template>
</b-table>
**Minor change in fields, but the concept is the same:
fields: [
{ key: 'fullName', label: 'User' },
{ key: 'buttons', label: 'Operations' }
],
Hope it helps. xx
Upvotes: 1
Reputation: 5435
You can specify nested field keys in dotted notation:
export default {
data() {
return {
users: [],
fields: [
{ key: 'id', label: 'ID'},
{ key: 'user.first_name', label: 'First Name' },
{ key: 'user.last_name', label: 'Last Name' }
]
}
}
Upvotes: 4
Reputation: 5048
Whereever you get your data, you can extract the property you want and save locally in this case it would look something like this:
data()
return {
users: []
}
methods: {
async getUsersFromApi(){
const { data: {users }} = await axios.get(...)
users.map(user => {
this.users.push(user.user)
}
Upvotes: 0