简体   繁体   中英

Vue.js : How to use id to select an item in another array

I got 2 array, one for states and another one for countries. I want to display the country name of the state. So, I'm using Laravel 5.7 for the backend and I get data using this for the countries Country::get(); and Vue.js recieve the array like this:

countries:Array(4)
    0:created_at:(...)
        deleted_at:(...)
        id:(...)
        name:(...)
        shortName:(...)
        updated_at:(...)
    1:{…}
    2:{…}
    3:{…}

I do the same for the state as the country. State::get(); and vue recieve this:

states:Array(1)
    0:country_id:(...)
        created_at:(...)
        deleted_at:(...)
        id:(...)
        name:(...)
        shortName:(...)
        updated_at:(...)

When I display the data into the table using v-for:

<tbody>
    <tr v-for="state in data.states">
        <td>{{SOMTHING TO DISPLAY COUNTRY NAME}}</td>
        <td>{{state.name}}</td>
        <td></td>
    </tr>
</tbody>

At the first cell, I tried to do {{data.countries[state.country_id]['name']}} but it failed. Instead it display another country in the array where the key correspond to the country_id I gave.

I know that I can solve my problem by doing this State::with('country')->get(); and then into my vue component doing this state.country.name , but since I already send every country, I'm looking for another way to perform it.

Any idea?

You want to JOIN your country data to your state data using state.country_id mapped to country.id .

Map your countries by ID

const cmap = {} // in your vue.data
countries.forEach(it=>cmap[it.id] = it)

Or use reduce

const cmap = countries.reduce((acc,cur)=>{acc[cur.id]=cur; return acc},{})

Put the map in a computed property so it is calculated one time on demand.

countryMap(){
    return this.countries.reduce((acc,cur)=>{acc[cur.id]=cur; return acc},{})
}

Create a lookup method

getCountryName(state){
    return this.countryMap[state.country_id].name
}

Use it in a template like this

<div>{{getCountryName(state)}}</div>

You don't need a lookup method, but if you are using Vue, it makes sense to break things up. this.countryMap[state.country_id].name is a bit messy in a template.

Since I'm using map with many object, I just changed my code in a way that I don't need to repeat myself everytime.

Since now, the code is a method instead of a computed property.

dataMap: function($model) {
    return this.data[$model].reduce((acc,cur)=>{acc[cur.id]=cur; return acc},{});
},

I use it this way into the component:

{{dataMap('countries')[dealer.country_id].name}}

And my data look like this:

export default {
    data() {
        return {
            data: {
                countries:{...},
                states:{...},
                cities:{...},
                groups:{...},
                dealers:{...},
                users:{...},
            },
        }
    },

So that way I can use the dataMap method for anything found into data array without having to recode a new map computed property. I just have to do this:

{{dataMap('users')[something.user_id].field}}
{{dataMap('groups')[something.group_id].field}}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM