Skip to content

@dispatch

Fire a bubbling, composed CustomEvent from the element (Alpine’s $dispatch). Components can talk upwards without sharing signals; anything with data-on:<name> on an ancestor hears it.

@dispatch('saved', { id: 3 })
@dispatch('close')
detail travels with the event

parent heard:

<div data-signals="{ last: 'nothing yet' }" data-on:ping="$last = 'ping with ' + JSON.stringify(evt.detail)">
<button data-on:click="@dispatch('ping', { at: Date.now() % 1000 })">Dispatch from inside</button>
<p>parent heard: <code data-text="$last"></code></p>
</div>

Two unrelated parts of the page: one dispatches, the other listens on window.

global bus

cart badge (component B):

<div data-signals="{ received: 0 }">
<div class="row"><button data-on:click="@dispatch('cart-add', { sku: 'X1' })">add to cart (component A)</button></div>
<p data-on:cart-add__window="$received++">cart badge (component B): <b data-text="$received"></b></p>
</div>

The event bubbles from the element the expression runs on (el) and is composed, so it also leaves a shadow root. Use kebab-case event names: the listener side converts its key to kebab-case unless you add __case.camel.

import { dispatch } from 'sigmx/plugins'

Registering dispatch adds 34 bytes brotli (73 gzip, 166 minified) on top of the core. See bundle sizes.