简体   繁体   中英

Vue.Js how to get value of prop attribute with id

I've been stuck on this for a while now and i'm not sure what to Google to find a solution and through the vuejs docs but can't find anything usefull.

Basicly I have a app with a few props. One of them is 'soundpacks'. This prop is setup this way in my app.js:

soundpacks: [
    { 
        title: 'Techno soundpack',
        tempo: 130,
        genre_id: 1,
        teacher_id: 1
    },
    { 
        title: 'Deep House soundpack',
        tempo: 123,
        genre_id: 2,
        teacher_id: 2
    }
]

As you can see I have declared a genre_id in here. I have another prop declared like this:

genres: [
    {
        id: 1,
        label: 'Techno'
    }, 
    {
        id: 2,
        label: 'Deep House'
    }
]

My problem is as follows. On my front-page I want to display all the soundpacks in a div which I do with a v-for. This is working but in this div I want to display the name of the genre that is linked to the soundpack through the genre_id. I have no clue on how to get this label value to display in this v-for and i'm hoping anybody can give me a push in the good direction. I'm new to Vue.Js thats why I'm asking what looks to be a very simple problem.

Any help is appreciated.

Thank you!

I just wrote a computed property that you can add to your component. Will compute a new list that you can directly use to display in your app.

computed: {
    computeListData(){
        let newList = []
        this.soundpacks.forEach((item) => {
            let data = this.genres.filter((genre) => {
                return (genre.id === item.genre_id)
            })
            let listData = item
            listData.label = data[0].label
            newList.push(listData)
        })
        return newList
    }
}

Here's a gist link that you can refer to: https://gist.github.com/ayushgupta11/7eeb1a4fdfeadab1a94a1e592ecd53dd

Please tell if this worked for you.

<li v-for="soundpack in soundpacks" :key="soundpack.teacher_id">
   {{genres[soundpack.genre_id - 1].label}} 
</li>

Note that the -1 is because you started your indexing at 1 while the index of an array starts at 0, also note that my code only works if you continue a constant numbering of your genres.

Lots of options here.

Just using a template you can achieve this using nested loops:

<div v-for="pack in soundpacks">
    {{ pack.title }} -
    <template v-for="genre in genres">
        <template v-if="genre.id === pack.genre_id">
            {{ genre.label }}
        </template>
    </template>
</div>

Alternatively, you can use a computed property to add the genre label to your soundpack data:

computed: {
    extendedSoundpacks () {
        return this.soundpacks.map(pack => {
            const genre = this.genres.find(genre => genre.id === pack.genre_id)

            return {
                // Copy the original object to avoid mutating it.
                // Alternatively you could just nest the object by
                // removing the three dots, though this would be at
                // the expense of a more complicated template.
                ...pack,
                label: genre.label
            }
        })
    }
}

While this is slightly better than the loop in the template it still uses nested looping. Better would be to prepare a map to do a quick lookup of the label from the id:

computed: {
    genreMap () {
        const genreMap = {}

        this.genres.forEach(genre => {
            // If genres have more than just a label you could store
            // the whole object instead of just the label
            genreMap[genre.id] = genre.label
        })

        return genreMap
    }
}

Now we've got genreMap , the find in my earlier extendedSoundpacks example becomes just:

const genre = this.genreMap[pack.genre_id]

Whilst the code isn't much shorter it does avoid the nested looping, which would be much faster if the arrays are large enough.

However, once you have genreMap it becomes pretty trivial to do this in the template without creating a new array of soundpacks:

{{ genreMap[pack.genre_id] }}

In this case that would be sufficient but if the logic were more complicated than a simple id/label lookup you could use a method...

{{ getGenreLabel(pack.genre_id) }}

... or a filter:

{{ pack.genre_id | genreLabel }}

These would need to be defined as functions in the methods or filters sections of your component respectively. If you needed to use this logic across multiple components you might consider registering the filter globally.

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