Reputation: 75
I am currently using Vue.JS in a research project at work.
At the moment I am working primarily on the front-end side of things. I have a table with a few entries, and on click of the row, I want a modal popup window to appear with further details of that row.
I am just trying to get the multiple popups working, and will work on the dynamic content within each one once this is working correctly.
At the moment the top row is working as seen below:
<tr class="activate-popupmodal-tr" @click="showmodal = true">
<td>01/01/2016
<modal :show.sync="showmodal">
<h3 slot="header">
Bug #1 - <span> 04/07/2016 </span>
<img src="files/cross.jpg" @click="showmodal = false" />
</h3>
<div slot="body">
</div>
<div slot="footer">
</div>
</modal>
</tr>
With app.js as:
Vue.component('modal', {
template: '#dashboard-popup-template',
props: {
show: {
type: Boolean,
required: true,
twoWay: true
}
}
})
new Vue({
el: '.activate-popupmodal-tr',
data: {
showmodal: false
}
})
This works, but only on one row. Any idea on how I can get this to work?
Table: https://jsfiddle.net/a6n04o3t/
Upvotes: 3
Views: 8604
Reputation: 20940
Vue is pretty flexible so you can show modals in a number of different ways. Here's one of the ways I use frequently.
A working demo (including some ugly styling) can be found here on webpackbin.
First I start with a parent vue instance that is going to hold my list component, the modal component, and my list of items (really in this case the list of items could be stored in the parent or the list component, but likely you'll want it in the parent):
// in main.js
new Vue({
el: 'body',
components:{
list: List,
modal: Modal
},
data:{
items:[
{name: 'foo'},
{name: 'bar'},
{name: 'baz'}
]
},
events:{
showModal: function(item){
this.$broadcast('showModal', item)
}
}
})
It also holds a bridging event, i.e. an event who's purpose is to listen for $dispatch
ed events coming up from child components and immediately $broadcasts
a corresponding event to different child components, passing data along with it if needed. We'll look at this in more detail later.
My index file will contain the placeholders for the list
and modal
components which will be replaced by each corresponding component's template:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<style>
...
</style>
</head>
<body>
<div class="list-container">
<list :items="items"></list>
</div>
<modal></modal>
<script src="main.js"></script>
</body>
</html>
Note the line <list :items="items"></list>
. Here we are passing the items
from the parent component into the list
component.
Then I create my list component that will display my list:
// also in main.js
var List = Vue.component('list',{
props:['items'],
template: `
<div class="list-row" v-for="item in items" @click="showModal(item)">
<span>{{ item.name }}</span>
</div>
`,
methods:{
showModal: function(item){
this.$dispatch('showModal', item)
}
}
})
The list component takes in the items
as a property so that it can display each item via v-for="item in items"
in the list component's template.
For each row that is rendered in the list, I attach a click event that calls the method showModal
and passes the current item
in to it. That method then dispatches the showModal
event up to the parent.
This is where the bridging event on the parent comes in. The parent's showModal
event hears the dispatch from the list and immediately broadcasts a showModal
event down to all children, passing the current item with it.
The only child that has an event listener for showModal
is the modal
component:
// also in main.js
var Modal = Vue.component('modal',{
template:`
<div class="modal-container" v-show="visible">
<div class="modal-body">
<div clas="modal-content">
{{ item | json }}
</div>
<button @click="closeModal">Close</button>
</div>
</div>
`,
data: function(){
return {
item: null,
visible: false
}
},
events:{
showModal: function(item){
this.item = item
this.visible = true
}
},
methods:{
closeModal: function(){
this.visible = false
this.item = null
}
}
})
When the modal component detects that showModal
has been broadcasted down from the parent, it fires it's showModal
event logic which sets the passed in item as a local prop (which gives the modal's template access to it) and the sets the visibility to true.
I do this kind of a pattern to show modals, loading masks, notifications, etc.
Let me know if you have any questions on this approach.
Upvotes: 6