Reputation: 4441
I'm adding a way for the parent App.vue
tell all child components to close every modal you have open and for any given child to tell the parent to hide the overlay if someone clicks on the main app div. So for example if the services page has a modal open to view some details, an overlay will be active that is set in the parent App.vue
component, and if I click anywhere outside of the modal, the modal will close and the child will tell the parent to close the overlay. I have it setup this way so that it's something globally available and not isolated to a single component.
<template>
<div id="app" v-cloak :class="{'overlay-layer' : overlay.active}" v-on:click="close($event)">
<Header/>
<transition>
<router-view v-on:overlay="overlay.active = $event" :closeAllModals="overlay.close"/>
</transition>
<Footer/>
</div>
</template>
<script>
import Header from '@/components/header/Header.vue';
import Footer from '@/components/footer/Footer.vue';
export default {
components: {
Header,
Footer
},
props: {
closeAllModals: Boolean
},
data: function() {
return {
overlay: { active: false, close: false }
};
},
methods: {
close(e) {
if (this.overlay.active && e.toElement.id === 'app') {
this.overlay = {
active: false,
close: true
}
}
}
}
};
</script>
The problem is that this only executes once, so for example in the services page I have:
import Header from '@/components/header/Header.vue';
import Footer from '@/components/footer/Footer.vue';
export default {
name: 'services',
components: {
Header,
Footer
},
props: {
closeAllModals: Boolean
},
data: function() {
return {
overlay: false,
activeMember: Object,
};
},
methods: {
setActiveMember(member, open) {
this.activeMember = member;
if (open) {
this.activeMember.active = true;
this.overlay = true;
} else {
this.activeMember.active = false;
this.overlay = false;
}
this.$emit('overlay', this.overlay);
this.$forceUpdate();
},
watch: {
closeAllModals: function() {
this.activeMember.active = false;
this.overlay = false;
this.$forceUpdate();
console.log('runs once');
}
}
};
So this works, but only works the first time. The prop only sends the updated value to the child only once. I've tried watching the prop in the child and using forceUpdate too but it isn't working. How do I make this run every single time?
Upvotes: 0
Views: 163
Reputation: 394
A global event bus could help when components have to talk to each other across different parent/child levels. Below is a good write up on that:
https://alligator.io/vuejs/global-event-bus
Note: but be sure to use it only when necessary and remove the listeners in beforeDestroy
life cycle of the component
Upvotes: 1