Events
Tag-prefixed custom events, cancelable default actions, cross-instance broadcasts, and listeners that clean themselves up.
Emit, default actions, broadcasts
Neutron({
tag: "save-button",
props: {},
events: {
// emitted and listened to as `save-button-save`
save: { prefixWithTag: true },
},
broadcasts: {
"app-toast": {},
},
})
.onEvent("save", (_el, e) => {
/* runs during dispatch, before the default action */
})
.onEventDefault("save", () => ({
/* runs in the next task; skipped if e.preventDefault() was called synchronously */
broadcast: ["app-toast", { detail: { message: "Saved" } }],
}))
.onBroadcast("app-toast", (_el, e) => {
/* cross-instance channel */
})
.onConnected(() => ({
emit: ["save", { detail: { id: 1 } }],
}));Neutron({
tag: "save-button",
props: {},
events: {
// emitted and listened to as `save-button-save`
save: { prefixWithTag: true },
},
broadcasts: {
"app-toast": {},
},
})
.onEvent("save", (_el, e) => {
/* runs during dispatch, before the default action */
})
.onEventDefault("save", () => ({
/* runs in the next task; skipped if e.preventDefault() was called synchronously */
broadcast: ["app-toast", { detail: { message: "Saved" } }],
}))
.onBroadcast("app-toast", (_el, e) => {
/* cross-instance channel */
})
.onConnected(() => ({
emit: ["save", { detail: { id: 1 } }],
}));prefixWithTagis off by default. When on, the configured short name is prefixed foremit,onEvent,onEventDefault, andaddListeneralike. Always prefix events with the tag name to avoid clashing with native events.emitdefaultsbubbles/cancelable/composedtotrue, returns the event, and warns when the element is not connected. Passtargetin the init to dispatch from another element.onEventDefaultruns only when the element itself is the event target, after the event has finished dispatching, and never whenpreventDefault()was called. Consumers cancel withpreventDefault()instead of forking the element.broadcastdispatches a non-bubbling event on a shared channel (not on the element), so any instance of any element canonBroadcastit.- An instruction aimed at the element ("submit", "reload", "open") is not an event of its own: handle it as a command — see
Commands .
Listener cleanup
Listeners registered by onEvent / onBroadcast or added through addListener, addListeners, …) are tracked per element: removed on disconnect, re-added on reconnect (once listeners are not re-added). addListener accepts a target option to listen on another node with the same cleanup.
Typing events
Document Neutron-emitted events with TEvent plus type and detail — do not repeat the flags:
import { TEvent } from "@excom/neutron";
export type SaveButtonSaveEvent = TEvent & {
type: "save-button-save";
detail: { id: number };
};import { TEvent } from "@excom/neutron";
export type SaveButtonSaveEvent = TEvent & {
type: "save-button-save";
detail: { id: number };
};Native listeners (form submit) are not Neutron emits — type those as the DOM event with its real flags (composed: false on SubmitEvent).