Everything you know from that line still applies here. The name of the event, the object it hands
you, the properties on it, the methods you can call on it: all the same.
An event prop is on plus the DOM event name, and the argument is the browser's own event
object.
<inputanyonInputonInput · Event handlerRuns when this element fires the matching DOM event, and receives the native event object.={(event(parameter) event: any) => (name = event.currentTarget.value)} />
There is no wrapper object in between. event.currentTarget, event.key, event.target and
event.preventDefault() are the real ones, described by the same documentation you already read
when you learned the DOM.
Try it: type, then press Enter
Type your name into the field and watch the line under it keep up. Then, with the cursor still in
the field, press Enter and watch the page not reload:
The echo moved because onInput assigned to a watched variable. The page stayed put because the
submit handler called event.preventDefault(), exactly as it would in a script tag.
Here is the file, all of it:
import { state } from '@markless/core';export default functionNameEchofunction NameEcho(): Element() @{@{ · Component bodyOpens the body of a component, where ordinary statements and the markup they produce sit together. letnamelet name: string=statestate · Watched valueDeclares a variable the page follows, which you read and assign exactly like any other variable.(''); <form(property) form: GlobalAttributes & MarklessAttributes<HTMLFormElement> & NativeEventAttributes<HTMLFormElement> & {onSubmitonSubmit · Event handlerRuns when this element fires the matching DOM event, and receives the native event object.={(event(parameter) event: EventWithCurrentTarget<SubmitEvent, HTMLFormElement>) => event.preventDefault(method) preventDefault(): voidThe **`preventDefault()`** method of the Event interface tells the user agent that if the event does not get explicitly handled, its default action should not be taken as it normally would be. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/preventDefault)()}> <label(property) label: GlobalAttributes & MarklessAttributes<HTMLLabelElement> & NativeEventAttributes<HTMLLabelElement> & {> Your name <input(property) input: GlobalAttributes & MarklessAttributes<HTMLInputElement> & NativeEventAttributes<HTMLInputElement> & FormAttributes & {value(property) value?: string | number | readonly string[] | undefined={name} onInputonInput · Event handlerRuns when this element fires the matching DOM event, and receives the native event object.={(event(parameter) event: EventWithCurrentTarget<Event, HTMLInputElement>) => (name = event.currentTarget.value)} /> </label(property) label: GlobalAttributes & MarklessAttributes<HTMLLabelElement> & NativeEventAttributes<HTMLLabelElement> & {> <p(property) p: GlobalAttributes & MarklessAttributes<HTMLParagraphElement> & NativeEventAttributes<HTMLParagraphElement>>Hello, {name}</p(property) p: GlobalAttributes & MarklessAttributes<HTMLParagraphElement> & NativeEventAttributes<HTMLParagraphElement>> <button(property) button: GlobalAttributes & MarklessAttributes<HTMLButtonElement> & NativeEventAttributes<HTMLButtonElement> & FormAttributes & {type(property) type?: "button" | "reset" | "submit" | undefined="submit">Say hello</button(property) button: GlobalAttributes & MarklessAttributes<HTMLButtonElement> & NativeEventAttributes<HTMLButtonElement> & FormAttributes & {> </form(property) form: GlobalAttributes & MarklessAttributes<HTMLFormElement> & NativeEventAttributes<HTMLFormElement> & {>}
The name is the DOM event name in camel case
click becomes onClick. input becomes onInput. dblclick becomes onDblClick. For the
capture phase, add Capture to the end, as in onClickCapture.
import { state } from '@markless/core';export default functionKeysfunction Keys(): Element() @{@{ · Component bodyOpens the body of a component, where ordinary statements and the markup they produce sit together. letcountlet count: number=statestate · Watched valueDeclares a variable the page follows, which you read and assign exactly like any other variable.(0); <section(property) section: GlobalAttributes & MarklessAttributes<HTMLElement> & NativeEventAttributes<HTMLElement>> <button(property) button: GlobalAttributes & MarklessAttributes<HTMLButtonElement> & NativeEventAttributes<HTMLButtonElement> & FormAttributes & {onClickonClick · Event handlerRuns when this element fires the matching DOM event, and receives the native event object.={() =>countlet count: number++}>Increment</button(property) button: GlobalAttributes & MarklessAttributes<HTMLButtonElement> & NativeEventAttributes<HTMLButtonElement> & FormAttributes & {> <button(property) button: GlobalAttributes & MarklessAttributes<HTMLButtonElement> & NativeEventAttributes<HTMLButtonElement> & FormAttributes & {onKeyDownonKeyDown · Event handlerRuns when this element fires the matching DOM event, and receives the native event object.={(event(parameter) event: any) => { if (event.key === 'Escape') count = 0; }} > Reset </button(property) button: GlobalAttributes & MarklessAttributes<HTMLButtonElement> & NativeEventAttributes<HTMLButtonElement> & FormAttributes & {> <output(property) output: GlobalAttributes & MarklessAttributes<HTMLOutputElement> & NativeEventAttributes<HTMLOutputElement>>{count}</output(property) output: GlobalAttributes & MarklessAttributes<HTMLOutputElement> & NativeEventAttributes<HTMLOutputElement>> </section(property) section: GlobalAttributes & MarklessAttributes<HTMLElement> & NativeEventAttributes<HTMLElement>>}
A prop can also take an array of handlers instead of one. They run in the order you wrote them, and
the run stops at the first one that throws.
import { state } from '@markless/core';export default functionSaveButtonfunction SaveButton(): Element() @{@{ · Component bodyOpens the body of a component, where ordinary statements and the markup they produce sit together. letnotelet note: string=statestate · Watched valueDeclares a variable the page follows, which you read and assign exactly like any other variable.('nothing saved yet'); constsaveDraftconst saveDraft: () => string = () => (note = 'saved'); constcloseDialogconst closeDialog: () => string = () => (note = 'saved, and the dialog is closed'); <section(property) section: GlobalAttributes & MarklessAttributes<HTMLElement> & NativeEventAttributes<HTMLElement>> <button(property) button: GlobalAttributes & MarklessAttributes<HTMLButtonElement> & NativeEventAttributes<HTMLButtonElement> & FormAttributes & {onClickonClick · Event handlerRuns when this element fires the matching DOM event, and receives the native event object.={[saveDraft, closeDialog]}>Save</button(property) button: GlobalAttributes & MarklessAttributes<HTMLButtonElement> & NativeEventAttributes<HTMLButtonElement> & FormAttributes & {> <output(property) output: GlobalAttributes & MarklessAttributes<HTMLOutputElement> & NativeEventAttributes<HTMLOutputElement>>{note}</output(property) output: GlobalAttributes & MarklessAttributes<HTMLOutputElement> & NativeEventAttributes<HTMLOutputElement>> </section(property) section: GlobalAttributes & MarklessAttributes<HTMLElement> & NativeEventAttributes<HTMLElement>>}
Forms are forms
Nothing about a form is special here. The input event carries the new value, the change event on
a checkbox tells you it flipped, and the submit event is where you stop the browser navigating.
import { state } from '@markless/core';export default functionSignupfunction Signup(): Element() @{@{ · Component bodyOpens the body of a component, where ordinary statements and the markup they produce sit together. letnamelet name: string=statestate · Watched valueDeclares a variable the page follows, which you read and assign exactly like any other variable.(''); letsubscribedlet subscribed: boolean=statestate · Watched valueDeclares a variable the page follows, which you read and assign exactly like any other variable.(false); <form(property) form: GlobalAttributes & MarklessAttributes<HTMLFormElement> & NativeEventAttributes<HTMLFormElement> & {onSubmitonSubmit · Event handlerRuns when this element fires the matching DOM event, and receives the native event object.={(event(parameter) event: EventWithCurrentTarget<SubmitEvent, HTMLFormElement>) => event.preventDefault(method) preventDefault(): voidThe **`preventDefault()`** method of the Event interface tells the user agent that if the event does not get explicitly handled, its default action should not be taken as it normally would be. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/preventDefault)()}> <label(property) label: GlobalAttributes & MarklessAttributes<HTMLLabelElement> & NativeEventAttributes<HTMLLabelElement> & {> Name <input(property) input: GlobalAttributes & MarklessAttributes<HTMLInputElement> & NativeEventAttributes<HTMLInputElement> & FormAttributes & {value(property) value?: string | number | readonly string[] | undefined={name} onInputonInput · Event handlerRuns when this element fires the matching DOM event, and receives the native event object.={(event(parameter) event: EventWithCurrentTarget<Event, HTMLInputElement>) => (name = event.currentTarget.value)} /> </label(property) label: GlobalAttributes & MarklessAttributes<HTMLLabelElement> & NativeEventAttributes<HTMLLabelElement> & {> <label(property) label: GlobalAttributes & MarklessAttributes<HTMLLabelElement> & NativeEventAttributes<HTMLLabelElement> & {> <input(property) input: GlobalAttributes & MarklessAttributes<HTMLInputElement> & NativeEventAttributes<HTMLInputElement> & FormAttributes & {type(property) type?: string | undefined="checkbox"checked(property) checked?: boolean | undefined={subscribed} onChangeonChange · Event handlerRuns when this element fires the matching DOM event, and receives the native event object.={() => (subscribed = !subscribed)} /> Updates </label(property) label: GlobalAttributes & MarklessAttributes<HTMLLabelElement> & NativeEventAttributes<HTMLLabelElement> & {> <output(property) output: GlobalAttributes & MarklessAttributes<HTMLOutputElement> & NativeEventAttributes<HTMLOutputElement>>{name}</output(property) output: GlobalAttributes & MarklessAttributes<HTMLOutputElement> & NativeEventAttributes<HTMLOutputElement>> </form(property) form: GlobalAttributes & MarklessAttributes<HTMLFormElement> & NativeEventAttributes<HTMLFormElement> & {>}
The specification puts the rule this way: only browser-critical cancellation and propagation is
allowed to run synchronously, and if the condition cannot be proven, compilation fails "rather than
silently emitting a handler whose default action is too late".
One thing to watch in a handler
Read event.target rather than event.currentTarget if your handler does its work after an
await. currentTarget is only populated while the browser is dispatching the event, and a handler
that resumes later can find it empty. Everything on this page runs straight through, so
currentTarget is the right one and is what the examples use.
Coming from another framework?
There is no synthetic event system, so there is no pooled event object, no wrapper class, and no separate documentation to learn. The event you receive is the one the browser dispatched. There is also no attribute in the shipped HTML pointing at your handler: the compiler records the node, the event name and the handler it needs, and the runtime wires that up at the container, so the handler chunk is fetched the first time it is genuinely needed.
Try it yourself
Add a line to the echo demo showing how many characters you have typed. You only need
{name.length}, and the handler does not change. Then swap onInput for onChange and notice when
the echo updates instead: on every keystroke against on leaving the field. Both are the browser's
own behaviour, unchanged.