Reputation: 241
I have a custom event to close a modal window and it works perfectly as long as the component is a direct child of the parent. But when I want to call the event from a deeper nested component it doesn’t work.
Here is my parent component:
<Modal @modal-close="close" />
Here is my close button inside <Modal>
:
<a @click="$emit('modal-close')">CLOSE</a>
As said, this works. But inside <Modal>
I’m importing a component for the content of <Modal>
and now I want to call the event from inside the content component like this:
const emit = defineEmits(['modal-close']);
emit('modal-close');
I get no warning or errors. But the parent-parent component <Modal>
does nothing. Are events not available globaly? How can I solve this problem?
SOLVED:
I chose the non-event based way by creating a function in the parent for closing the <Modal>
and pass it as a prop to the children. It seems to me that this is the simplest solution and also provides flexibility to add custom actions when closing the modal.
This is my parent component now:
const close = (data) {
// close the modal
// process data
};
<Modal :close="close" />
And my child component:
const $$ = defineProps({
close: Boolean | Function,
});
<a @click="$$.close">CLOSE</a>
Upvotes: 3
Views: 8108
Reputation: 35684
One way (probably the simplest) is to get the intermediary components to bubble the events up. That would mean that a component listens to the modal-close
event, and emits it to its parent. This may be the simplest way, but it's not very scalable and something you might do for a one-off use.
Vue 3 doesn't provide a global listener (event bus in vue2), but you could use a library like mitt to handle global events.
_Event Bus
The event bus pattern can be replaced by using an external library implementing the event emitter interface, for example mitt or tiny-emitter._
— docs
There is another, non-event based option though.
Instead of listening to an event, you can use a ref
variable that will manage open closed state. Modals are often handled as singletons/globals so the variable can be accessible globally. If you have a single modal, you can export that variable from the component or you can use Provide/Inject.
Upvotes: 3