Skip to content
Ilha
Esc
navigateopen⌘Jpreview
On this page

.on()

Register a delegated or host event listener with a CSS selector, island-host listener, full handler context, and optional modifiers.

.on() registers an event listener for a CSS selector, the island host, or both, with the full island handler context. Use it when a native event prop cannot express the target — a selector that matches conditionally rendered elements, an island-host listener, or combined modifiers.

Prefer lowercase native JSX event props when one rendered element owns the event. Use .on() when you need a selector, a host listener, the full handler context, or multiple listener modifiers.

Selector syntax

The first argument combines an optional selector and event name with @:

.on("button@click", handler) // descendant buttons
.on("@click", handler) // island host
.on("button@click:once:capture", handler) // combined modifiers

Combined with actions

Declare actions before .on() to expose them through the handler context:

import { 
const ilha: RootBuilder & DirectIslandFactory & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 6 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
} from "ilha";
const const Registration: Island<RootInput, RootState>Registration =
const ilha: RootBuilder & DirectIslandFactory & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 6 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<RootInput, RootState, RootDerived, RootActions>.action<"registerUser", SubmitEvent, Promise<void>>(key: "registerUser", fn: (props: SubmitEvent, ctx: ActionContext<RootInput, RootState, RootDerived>) => Promise<void>): IlhaBuilder<RootInput, RootState, RootDerived, RootActions & Record<"registerUser", (props: SubmitEvent, ctx: ActionContext<RootInput, RootState, RootDerived>) => Promise<void>>>action( "registerUser", async (event: SubmitEventevent: SubmitEvent, { signal: AbortSignalsignal }) => { event: SubmitEventevent.Event.preventDefault(): void
The **`preventDefault()`** method of the Event interface tells the user agent that the event is being explicitly handled, so its default action, such as page scrolling, link navigation, or pasting text, should not be taken. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/preventDefault)
preventDefault
();
const const form: HTMLFormElementform = event: SubmitEventevent.Event.currentTarget: EventTarget | null
The **`currentTarget`** read-only property of the Event interface identifies the element to which the event handler has been attached. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/currentTarget)
currentTarget
as HTMLFormElement;
await function fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/fetch)
fetch
("/api/register", {
RequestInit.method?: string | undefined
A string to set request's method.
method
: "POST",
RequestInit.body?: BodyInit | null | undefined
A BodyInit object or null to set request's body.
body
: new var FormData: new (form?: HTMLFormElement, submitter?: HTMLElement | null) => FormData
The **`FormData`** interface provides a way to construct a set of key/value pairs representing form fields and their values, which can be sent using the fetch(), XMLHttpRequest.send() or navigator.sendBeacon() methods. It uses the same format a form would use if the encoding type were set to "multipart/form-data". [MDN Reference](https://developer.mozilla.org/docs/Web/API/FormData)
FormData
(const form: HTMLFormElementform),
RequestInit.signal?: AbortSignal | null | undefined
An AbortSignal to set request's signal.
signal
,
}); }, ) .IlhaBuilder<RootInput, RootState, RootDerived, RootActions & Record<"registerUser", (props: SubmitEvent, ctx: ActionContext<RootInput, RootState, RootDerived>) => Promise<...>>>.on<"form@submit">(selectorOrCombined: "form@submit", handler: (ctx: HandlerContextFor<RootInput, RootState, "submit", RootDerived, RootActions & Record<"registerUser", (props: SubmitEvent, ctx: ActionContext<RootInput, RootState, RootDerived>) => Promise<void>>>) => void | Promise<void>): IlhaBuilder<RootInput, RootState, RootDerived, RootActions & Record<...>>on("form@submit", ({ action: IslandActions<RootActions & Record<"registerUser", (props: SubmitEvent, ctx: ActionContext<RootInput, RootState, RootDerived>) => Promise<void>>>action, event: SubmitEventevent }) => action: IslandActions<RootActions & Record<"registerUser", (props: SubmitEvent, ctx: ActionContext<RootInput, RootState, RootDerived>) => Promise<void>>>action.registerUser: (props: SubmitEvent) => voidregisterUser(event: SubmitEventevent), ) .IlhaBuilder<RootInput, RootState, RootDerived, RootActions & Record<"registerUser", (props: SubmitEvent, ctx: ActionContext<RootInput, RootState, RootDerived>) => Promise<...>>>.render(fn: (ctx: RenderContext<RootInput, RootState, RootDerived, RootActions & Record<"registerUser", (props: SubmitEvent, ctx: ActionContext<RootInput, RootState, RootDerived>) => Promise<void>>>) => string | RawHtml): Island<RootInput, RootState>render(() => ( <"form": WithRawHtmlAttributeValues<JSX.HTMLAttributes<HTMLFormElement> & FormAttributes>form> <
"input": WithRawHtmlAttributeValues<JSX.HTMLAttributes<HTMLInputElement> & InputAttributes & {
    popovertarget?: string;
    popoverTarget?: string;
    popovertargetaction?: "hide" | "show" | "toggle";
    popoverTargetAction?: "hide" | "show" | "toggle";
}>
input
name?: string | RawHtml | undefinedname="email" type?: "number" | RawHtml | "submit" | "reset" | "button" | "search" | "time" | "image" | "text" | "hidden" | "email" | "checkbox" | "color" | "date" | "datetime-local" | "file" | "month" | "password" | "radio" | "range" | "tel" | "url" | "week" | undefinedtype="email" />
<
"button": WithRawHtmlAttributeValues<JSX.HTMLAttributes<HTMLButtonElement> & ButtonAttributes & {
    popovertarget?: string;
    popoverTarget?: string;
    popovertargetaction?: "hide" | "show" | "toggle";
    popoverTargetAction?: "hide" | "show" | "toggle";
}>
button
>Register</
"button": WithRawHtmlAttributeValues<JSX.HTMLAttributes<HTMLButtonElement> & ButtonAttributes & {
    popovertarget?: string;
    popoverTarget?: string;
    popovertargetaction?: "hide" | "show" | "toggle";
    popoverTargetAction?: "hide" | "show" | "toggle";
}>
button
>
</"form": WithRawHtmlAttributeValues<JSX.HTMLAttributes<HTMLFormElement> & FormAttributes>form> ));

Handler context

The handler receives state, derived, action, input, host, target, event, and signal. Synchronous signal writes are batched, listeners clean up on unmount, and thrown errors route through .onError().

Ilha resolves selectors again after each morph. Use .on() when template composition prevents a direct native event interpolation or when matching elements appear conditionally.

Error handling

A throw or rejection in an .on() handler reaches the island error sink with source: "on":

  1. Local .onError() handlers
  2. Global onUncaughtError() handlers
  3. console.error

An AbortError caused by cancellation (via :abortable race-cancel or unmount) is filtered out and does not reach the sink.

Notes

  • Prefer native event props for element-owned events.
  • .on() also runs client-only — it never runs during SSR.
  • AbortError rejections are filtered, not treated as errors.

Was this page helpful?