Skip to content

useDispatch

Adds a dispatch helper function to emit custom events. Useful to communicate between different controllers.

Reference

Mixin

useDispatch(controller, options = {})

controller : a Stimulus Controller (usually 'this')

options :

OptionDescription           Default value               
elementThe element the event will be emitted from.The controller element
eventPrefixWhether to prefix or not the emitted event. Can be a boolean or a string.
- true prefix the event with the controller identifier item:add
- someString prefix the event with the given string someString:add
- false to remove prefix
true
bubblesWhether the event should bubble.true
cancelableWhether the event is cancelable.true
debugWhether to log debug information. See debug for more information on the debugging toolsfalse

The dispatch function

Once the useDispatch mixin is applied, your controller has a new this.dispatch function available you may use to emit custom events.

dispatch(eventName, detail = {})
ParamDescription
eventNamea mandatory string for the name of the event to emit.
detailA payload object that will be passed through the event and available for the receiver with event.detail

Usage

// item_controller.js
import { Controller } from '@hotwired/stimulus'
import { useDispatch } from 'stimulus-use'

export default class extends Controller {
  connect() {
    useDispatch(this)
  }

  add() {
    // dispatch a custom event item:add
    this.dispatch("add")
  }
}

Bubbling events

The emitted event sent by the dispatch function will bubble up the tree of the DOM. Therefore all parent elements can listen to it directly.

<div data-controller="reciever" data-action="emitter:add->reciever#update">
  <div data-controller="emitter" data-action="click->emitter#add" ></div>
</div>

If both are at the same level or if the reciever controller is even nested within the controller, you should listen to event with @window to catch it.

<div data-controller="reciever" data-action="emitter:add@window->reciever#update"></div>
<div data-controller="emitter" data-action="click->emitter#add" ></div>

Example building a cart counter with the dispatch helper

The HTML markup. See the custom event item:add that the cart controller is listening to

<div data-controller="cart"
     data-action="item:add->cart#refreshTotal"
     data-cart-counter="0">

  <button data-controller="item" data-action="item#add">
    Add
  </button>

  <div>
    <span>No of items : </span>
    <span data-target="cart.counterView">0</span>
  </div>
</div>

The item controller dispatching the event

//item_controller.js
import { useDispatch } from 'stimulus-use'

export default class extends Controller {
  connect() {
    useDispatch(this)
  }

  add() {
    this.dispatch('add', { quantity: 1 })
  }
}

The cart controller receiving the event

//cart_controller.js
import { ApplicationController } from 'stimulus-use'

export default class extends ApplicationController {
  static targets = ['counterView']

  refreshTotal(e) {
    this.counter += e.detail.quantity
    console.log(e.detail.controller) // the emitting item_controller
  }

  renderCounter() {
    this.counterViewTarget.textContent = this.counter
  }

  set counter(value) {
    this.data.set('counter', value)
    this.renderCounter()
  }

  get counter() {
    return this.data.get('counter')
  }
}