Topic: Call modals from other components
jay2jam pro asked 5 years ago
Hello,
i am creating several components, also i created 1 Modals.vue, which shoud includes all modals, sure :-)
Now i import this component into App.vue and call them.
From component Content.vue, i want to call a modal, i am using a MDB standard Modal. Normally it should work like that, also i get no errors, so compiling is fine. But nothing happens, when i click on mdb-button.
Do i have to miss anything?
Rgds
Mikołaj Smoleński staff answered 5 years ago
Hello Stefan,
So everything is fine ;) No we can move to the second part of Your project - emiting close event. You'll need to make a method for all close events, like this:
<mdb-modal side position="top-right" v-if="showModal5" @close="closeModal">
<mdb-modal-header class="divider-outside-bottom">
<mdb-modal-title><img src="../assets/ecommerce-icon.png" class="img-fluid modalIcons"> <span class="modalTitle">Unsere eCommerce Angebote</span></mdb-modal-title>
</mdb-modal-header>
<mdb-modal-body>
<div class="container">
Hier kommt der Text rein
</div>
</mdb-modal-body>
<mdb-modal-footer>
<mdb-btn flat size="lg" darkWaves @click.native="closeModal"><img class="img-fluid modalBackIcon" src="../assets/arrow-right.png"/></mdb-btn>
</mdb-modal-footer>
</mdb-modal>
import { mdbModal, mdbModalHeader, mdbModalTitle, mdbModalBody, mdbModalFooter,
mdbBtn, mdbInput, mdbTextarea, mdbIcon } from 'mdbvue';
export default {
name: 'Overlays',
components: {
mdbModal,
mdbModalHeader,
mdbModalTitle,
mdbModalBody,
mdbModalFooter,
mdbBtn,
mdbInput,
mdbTextarea,
mdbIcon
},
props: {
show: {
type: Boolean,
default: false
}
},
data() {
return {
showModal5: this.show
}
},
methods: {
closeModal() {
this.showModal5 = false;
this.$emit('closeModal');
}
},
watch: {
show(newVal) {
this.showModal5 = newVal;
}
}
And then in Your App.vue You have to get the closeModal
event:
<template>
<div>
<Overlays :show="show" @closeModal="closeModal" />
<button @click="openModal">Open</button>
</div>
</template>
(...)
import Overlays from '@/components/Overlays.vue';
export default {
name: 'App',
components: {
Overlays
},
data() {
return {
show: false
}
},
methods: {
openModal() {
this.show= true
},
closeModal() {
this.show= false
}
}
}
Mikołaj Smoleński staff answered 5 years ago
Hi there again,
This article can be very helfpful for You: https://mdbootstrap.com/articles/vue/vuex-or-emit-basics-of-communication-between-vue-components/
Best!
Mikołaj Smoleński staff answered 5 years ago
Hi there again,
As the warning says - You should avoid mutating prop. You just need to update closeModal method in Modal Component to this:
methods: {
closeModal() {
this.impressum = false;
this.$emit('closeModal');
}
},
Best regards
jay2jam pro answered 5 years ago
Sorry Mikolaj, i have to ask you again. This is working but i get a warning:
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever
the parent component re-renders. Instead, use a data or computed property based on the
prop's value. Prop being mutated: "show"
found in
---> <ModalImpressum> at src/modals/site/ModalImpressum.vue
<Footer> at src/components/Footer.vue
<App> at src/App.vue
<Root>
Part of Modal template:
<mdb-modal side position="top-right" v-if="impressum" @closeModal="closeModal">
<mdb-modal-header v-sticky>
<mdb-modal-title> <span class="modalTitle">Impressum</span></mdb-modal-title>
<mdb-btn flat size="xs" darkWaves @click="closeModal" class="modalHeaderButton"><img
class="img-fluid modalBackIcon" src="../../assets/arrow-right-gray.png"/></mdb-btn>
</mdb-modal-header>
<mdb-modal-body>
Modal Component:
import { mdbModal, mdbModalHeader, mdbModalTitle, mdbModalBody, mdbModalFooter,
mdbBtn, mdbInput, mdbTextarea, mdbIcon, mdbCol, mdbRow,Sticky } from 'mdbvue';
export default {
name: 'ModalImpressum',
components: {
mdbModal,
mdbModalHeader,
mdbModalTitle,
mdbModalBody,
mdbModalFooter,
mdbBtn,
mdbInput,
mdbTextarea,
mdbIcon,
mdbCol,
mdbRow
},
props: {
show: {
type: Boolean,
default: false
}
},
data() {
return {
impressum: this.show
}
},
directives:{
'sticky': Sticky
},
methods: {
closeModal() {
this.show = false;
this.$emit('closeModal');
}
},
watch: {
show(newVal) {
this.impressum = newVal;
}
}
}
Call from Footer:
<ModalImpressum :show="show" @closeModal="closeModal" />
<mdb-btn @click="openModal" flat class="hi-icon hi-icon-archive text-
muted">Impressum</mdb-btn> <span class="ibull">•</span>
export default {
name: 'Footer',
components: {
mdbModal, mdbModalHeader, mdbModalTitle, mdbModalBody, mdbModalFooter,
mdbBtn, mdbInput, mdbTextarea, mdbIcon, mdbCard,
mdbCardBody, mdbContainer, mdbRow, mdbCol, mdbTooltip, mdbJumbotron,
ModalImpressum
},
data() {
return {
show: false
}
},
directives:{
'sticky': Sticky
},
methods: {
openModal() {
this.show= true
},
closeModal() {
this.show= false
}
}
}
Thx again
jay2jam pro answered 5 years ago
Hello Mikolaj,
thank you so much, but it doesn't work :-/ Now i can open the modal and close, but i can't reopen again.
I get no errors.
Rgds Stefan
Mikołaj Smoleński staff answered 5 years ago
In Your App.vue it should be:
<template>
<div>
<Overlays :show="show"/>
<button @click="openModal">Open</button>
</div>
</template>
(...)
import Overlays from '@/components/Overlays.vue';
export default {
name: 'App',
components: {
Overlays
},
data() {
return {
show: false
}
},
methods: {
openModal() { this.show= true
}
}
}
Rgds
jay2jam pro answered 5 years ago
Same problem :-/
Overlay:
<mdb-modal side position="top-right" v-if="showModal5" @close="showModal5 = false">
<mdb-modal-header class="divider-outside-bottom">
<mdb-modal-title><img src="../assets/ecommerce-icon.png" class="img-fluid modalIcons"> <span class="modalTitle">Unsere eCommerce Angebote</span></mdb-modal-title>
</mdb-modal-header>
<mdb-modal-body>
<div class="container">
Hier kommt der Text rein
</div>
</mdb-modal-body>
<mdb-modal-footer>
<mdb-btn flat size="lg" darkWaves @click.native="showModal5 = false"><img class="img-fluid modalBackIcon" src="../assets/arrow-right.png"/></mdb-btn>
</mdb-modal-footer>
</mdb-modal>
import { mdbModal, mdbModalHeader, mdbModalTitle, mdbModalBody, mdbModalFooter,
mdbBtn, mdbInput, mdbTextarea, mdbIcon } from 'mdbvue';
export default {
name: 'Overlays',
components: {
mdbModal,
mdbModalHeader,
mdbModalTitle,
mdbModalBody,
mdbModalFooter,
mdbBtn,
mdbInput,
mdbTextarea,
mdbIcon
},
props: {
show: {
type: Boolean,
default: false
}
},
data() {
return {
showModal5: this.show
}
},
watch: {
show(newVal) {
this.showModal5 = newVal;
}
}
}
App.vue:
Open Modal
import Overlays from '@/components/Overlays.vue';
export default {
name: 'App',
components: {
Overlays
},
data() {
return {
showModal5: false
}
},
methods: {
openModal() { showModal5 = true
}
}
}
Rgds Stefan
Mikołaj Smoleński staff answered 5 years ago
You need also to define showModal in Your App.vue like this:
data() {
return {
showModal: false
}
}
Best regards
Mikołaj Smoleński staff answered 5 years ago
Hi Stefan,
It's almost correct ;) The easiest way will be like this:
<Overlays :show="showModal" />
<button @click="openModal">Open Modal</button>
methods: {
openModal() { this.showModal = true
}
In Overlay.vue:
props: {
show: {
type: Boolean,
default: false
}
},
data() {
return {
showModal5: this.show
}
},
watch: {
show(newVal) {
this.showModal5 = newVal;
}
}
It should work now.
Best regards
jay2jam pro commented 5 years ago
Hello Mikolaj, thx for your help :-) Now i get this message in App.vue:
[Vue warn]: Error in v-on handler: "ReferenceError: showModal is not defined"
I also changed showModal to showModal5, but the same message
What can i do now?
Rgds Stefan
jay2jam pro answered 5 years ago
Hello Mikolaj,
i did this in App.vue(parent):
<Overlays :show="true" />
<button @click="openModal">Open Modal</button>
methods: {
openModal() { this.$refs.showModal5.show()
}
In Overlay.vue i did this:
data() {
return {
showModal5: false
}
},
watch: {
show(newVal) {
this.showModal5 = newVal;
}
}
I get this warning:
[Vue warn]: Error in v-on handler: "TypeError: Cannot read property 'show' of undefined"
Sorry, but i am new to vue and mdb vue
Rgds and thx for helping me Stefan
Mikołaj Smoleński staff answered 5 years ago
Hello,
You have to pass the main modal state to the appropriate component. In most cases it can be done by passing it as a prop. For example:
<Modal :show="true" ...></Modal>
The prop value should be triggered by a function, e.x. after button click.
Then You will have to watch for the prop changes inside Your own component. For example:
watch: {
show(newVal) {
this.showModal = newVal;
}
}
And then inside Modal.vue the mdb-modal should appeal to the showModal value, e.x.:
<mdb-modal v-if="showModal " ... >
Best regards
Mikołaj Smoleński staff commented 5 years ago
Also, if You want to access Modal from another component (not App.vue) at first You will need to $emit the 'show' value from Content.vue file.
FREE CONSULTATION
Hire our experts to build a dedicated project. We'll analyze your business requirements, for free.
Answered
- ForumUser: Pro
- Premium support: No
- Technology: MDB Vue
- MDB Version: 4.8.1
- Device: MAC
- Browser: CHROME
- OS: Moave
- Provided sample code: No
- Provided link: No