NicOwen
NicOwen

Reputation: 241

How can I emit from a nested component to higher parent?

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

Answers (1)

Daniel
Daniel

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

Related Questions