How to bind an action to a parent event?

The way Stimulus works each component is independent and communicate with others with events but so, I did not find any way for parent to trigger an event on itself and each child listening this event reacts and do what it have to.

So, how to bind a child action to an event triggered on parent ?

It works with @window but the event must be triggered to the window element, I would it to the parent’s controller element.

Note that globally, stimulus makes it harder to communicate between controllers, if a parent has 2 childrens, one triggers an event, the parent must bind it and triggers it back for the other child to get it.

You can target the childs when dispatching the events from the parent. So, you would save a reference for the children you want to notify when the parent event happens, most likely as targets.

In your parent controller, when you dispatch the event, you can specify the child element via the associated target, and the child element can listen to the event, without the @window directive.

<div data-controller="parent" data-action="child:event->parent#doSomething">
    <div data-parent-target="child" 
         data-controller="child"
         data-action="parent:event->child#doSomething" />

      <div data-parent-target="child" 
         data-controller="child"
         data-action="parent:event->child#doSomething" />
</div>

Then, in the controller, you can target the child when dispatching event,

parent_controller.js

export default class extends Controller {
   static targets=["child"]

   doSomething() {
      this.childTargets.forEach(child => {
          this.dispatch("event", {
             target: child,
            details: {}
          })
      })
   }
}

This matches the issue you described. When the parent event happens, it loops over every child target, dispatches the event, setting the event target as the child.

Hope this helps out!.

1 Like