0đź‘Ť
First, it is not a good idea to use JQuery lib in Vue. It will make your life complicated.
You can define one prop=modalButtons as one array, then the parent can pass the button spec to Modal component like [{'type':'close','text':'Close', 'action':function () {modal2 = false} }, {'type':'other','text':'Check', 'action':function () {/*check something*/} }]
Then v-modal will generate the buttons like below demo:
Vue.config.productionTip = false
Vue.component('v-modal', {
template: `
<!-- Modal -->
<div class="modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true" :class="value?'show':'fade'">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">{{ modalTitle }}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" @click="computedCloseButton.action($event)">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
{{ modalBody}}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal" v-for="(modalButton, index) in modalButtons" :key="index" @click="modalButton.action($event)">
{{ modalButton.text}}
</button>
</div>
</div>
</div>
</div>`,
props: {
modalTitle: {
type: String,
default: ''
},
modalBody: {
type: String,
default: ''
},
value: {
type: Boolean,
default: false
},
modalButtons: {
type: Array,
default: () => [{'type':'close', 'text':'Close', 'action': function () {}}]
}
},
computed: {
computedCloseButton: function () {
return this.modalButtons.find((item) => {
return item.type === 'close'
})
}
}
})
app = new Vue({
el: "#app",
data: {
modal1: false,
modal2: false
},
methods: {
openModals: function () {
this.modal1 = true
this.modal2 = true
},
checkSomething: function () {
console.log('check something')
}
}
})
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet"/>
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
<div id="app">
<button @click="openModals()">Open Both Modals</button>
<v-modal modal-title="Test1" modal-body="I am test1" :modal-buttons="[{'type':'close','text':'Close', 'action':function () {modal1 = false} }]" v-model="modal1"></v-modal>
<v-modal modal-title="Test2" modal-body="I am test2" :modal-buttons="[
{'type':'other','text':'Check', 'action':checkSomething},
{'type':'close','text':'Close', 'action':function () {modal2 = false}}]" v-model="modal2"></v-modal>
</div>
0đź‘Ť
You can use refs
and trigger modals programmatically.
Add a ref on each component and a new prop (modal-ref
for example) to retrieve the ref name inside the component:
<modal-decision v-on:decision="handleDirectImport" modal-button-text="title 1" modal-title="Title 1" modal-body="Content 1" modal-ref="modal1" ref="modal1"></modal-decision>
<modal-decision v-on:decision="handleDirectImport" modal-button-text="title 2" modal-title="Title 2" modal-body="Content 2" modal-ref="modal2" ref="modal2" ></modal-decision>
[Vue tip]: Note that HTML attributes are case-insensitive and camelCased props need to
use their kebab-case equivalents when using in-DOM templates. You
should probably use “modal-button-text” instead of “modalButtonText”. (same for the other props)
In your component, add a new ref
on the modal element and trigger it with a method:
<template>
<div>
<button type="button" class="btn btn-primary" @click="showModal()">
{{ modalButtonText}}
</button>
<div class="modal fade" ref="exampleModal" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<!-- Modal content here -->
</div>
</div>
</template>
props: {
modalTitle: String,
modalBody: String,
modalButtonText: String,
modalRef: String
},
methods: {
showModal() {
let element = this.$parent.$refs[this.modalRef].$refs.exampleModal
$(element).modal('show')
}
}