With Vuejs, how to use a modal component inside a v-for loop the right way
These two links helped me figure this out:
#In your Parent Component You don't have to create a modal for each item within the v-for loop, simply include the modal-component at the beginning of your parent and then work with v-if="..." and props.
<template>
<div>
<modal v-if="modalVisible" @close="modalVisible = false" :data="modalData"/>
<div v-for="item in items">
<button type="button" @click="openModal(item)">Open Modal</button>
</div>
</div>
</template>
and then in your script:
import modal from './Modal'
export default {
components: {
modal
},
data() {
return {
modalVisible: false,
modalData: null
}
},
methods: {
openModal(data) {
this.modalData = data
this.modalVisible = true
},
}
#In your child (modal) component In your modal you can now do the following:
Template:
<template>
{{ data.foo }}
<button @click="$emit('close')">Cancel</button>
</template>
Script
<script>
export default {
props: ['user']
};
</script>
Hope that helps :-)
Tiago
Updated on July 06, 2022Comments
-
Tiago almost 2 years
In my vue.js app, I need to display a list of items which the user can click.
When clicked, each of these items should then fire a modal, containing additional information about the item that the user just clicked.
What I have so far in my
Items.vue
component is:<template> <div id="content"> <li v-for="item in items" class="list-item pa2 ba"> <div class="f5 pt2 pb2"> <span>{{item.name}}</span> </div> </li> </div> </template> <script> import Items from '@/api/items'; export default { name: 'items', asyncComputed: { items: { async get() { const items = await Items.getAll(); return items.data; }, default: [] } }, components: {} } </script>
Now, I could simply add a modal component to the
v-for
loop, thus creating one modal for each item, but this does not seem ideal if, for example, I have a list of thousands of items.This led me to believe that the modal should probably be placed at the root of the app (in my case
App.vue
), like this:<template> <div id="app"> <modal></modal> <router-view></router-view> </div> </template> <script> export default { name: 'app' } </script>
and then somehow fired with custom data whenever I needed it.
However, I'm not sure how to proceed. How do I fire this modal with custom information from inside the
v-for
loop, which is in a child component relative toApp.vue
? -
Scornwell over 5 yearsThis was fantastic, I was racking my head on this for a few hours. Simply moving it out of the for loop and passing it data solved my issue of having a modal pop-up for every line item regardless of which on was clicked. +1