HelixOverviewComponentsMapsGraphIntroductionInstallationDeriving a themeSandboxTheme builderVisual testingCortexDocsEngramBuildingTraceBuildingRecallDeclaredServicesInsightsGet in touchSource on GitHub
Essentials
EventsEach state change sends two events. The first is a request that you can cancel.
The second is a notification that the change happened.// The request. Cancelable, carries what is being proposed, and fires before// anything moves. This is how you take the decision.element.addEventListener('helix-before-change',(event)=>{if(locked){event.preventDefault()}})// The notification, under the platform's own name. Fires after the value moved,// so it is on the target where every handler ever written expects it.element.addEventListener('change',(event)=>{save(event.target.value)})Most of the time you need the notification. Bind onChange in React or
onchange= in HTML and read the target, as you would for an <input>. Use the
prefixed event when you want to cancel the change.Each event has its own class. The class gets the event's type to you in three
ways:The class name is in the manifest, so the framework typings can emit a typed
callback. A bare CustomEvent would give (detail: unknown).The package augments HTMLElementEventMap, which types addEventListener
when you write plain HTML.The name is defined on the class, so a dispatch and a listener always use the
same string.Why the request has a prefix and the notification does notRetargetingAn event dispatched inside a shadow root is retargeted so that it appears to
come from the host. A bare input from a <helix-input> would look the same
as the input from the control inside it. A prefixed event cannot be mistaken
for either one.React's event namesReact's synthetic event system handles change, input, submit, copy,
focus, and its other event names. A prop that matches one of those names is
connected to the native event of that name. onhelix-before-change matches none
of them, so it reaches our event. A request needs exactly that.The notification uses the native nameThe notification has no prefix for the same reason. onChange on a Helix
element goes through React's synthetic system to the native change event the
element sends. You use it the way you already use it on any input.The type map is globalHTMLElementEventMap is shared by every element in your application. Our event
classes extend Event, so an entry named select would still compile. It would
silently retype textarea.addEventListener('select', …) as carrying our detail,
which is undefined at runtime. We measured this. We would not see a collision
from an unprefixed name, and you would.Which events bubbleLifecycle events do not bubble and are not composed. These are
helix-before-open and helix-before-close. Overlays nest, and an inner
overlay's lifecycle must never reach the outer overlay that contains it. A
menu that closes inside a dialog does not close the dialog.Coordination events bubble and are composed. These are helix-select,
helix-dismiss, and helix-before-change. A parent or a router can intercept
them across a shadow boundary, so you can use a Tree as navigation.If you listen on a container and receive nothing, the event is probably a
lifecycle event. Add the listener to the element itself.Cancel a changeYou can cancel the events sent before a state change. Canceling is the only way
to stop the change:dialog.addEventListener('helix-before-close',(event)=>{if(unsaved){event.preventDefault()}})Every dispatched event is checked against a declaration, and every declaration
against a dispatch, so every event you can listen for is documented.Helix eventsEventMeaninghelix-before-changeA value is about to change, cancelablehelix-before-toggleA checked state is about to flip, cancelablehelix-before-open, helix-before-closeAn open state is about to change, cancelablehelix-before-activate, helix-activateA set is about to make a different child current, cancelable, and then didhelix-before-pin, helix-pinA chat transcript is about to be pinned to the bottom or let go of it, cancelable, and then washelix-before-resize, helix-resizedA splitter's divider is about to settle, cancelable, and then didhelix-before-collapse, helix-collapseA splitter's pane is about to shut or reopen, cancelable, and then didhelix-selectAn item was chosen from a sethelix-dismissA user asked for something to closehelix-next, helix-previousMovement through a sequencehelix-filterA query changed in a filtering controlhelix-navigateA component is about to navigatehelix-copySomething was copiedhelix-caretThe cursor moved in a text controlhelix-completeA control that fills up has filledhelix-createA new item was made from a queryhelix-consoleThe sandbox passes on a log messagehelix-tour-ask, helix-sample-start, helix-sample-endTour and color samplingEvery stateful component also sends native events once the change is applied:input and change on a value controltoggle on anything that opens, carrying newState and oldState as
<details> does. It is a ToggleEvent in browsers that have one, and it is
sent whether the change came from a reader or from assigning openclose on a dialogload and error on an imageEach component's page lists the events it dispatches, with the class and the
detail. The table above lists the common ones.Requests under a plain nameA few events with no before in their name are also cancelable requests. Each
is sent before the change, and you refuse the change with preventDefault():helix-navigate on Pagination, Data Table, and Date Pickerhelix-sort, helix-filter, helix-select, and helix-reorder on Data Tablehelix-select on CarouselEach of these requests had its name before the library had a word for the
notification, so the notification has its own name. It is sent after the
change, is not cancelable, and carries the new state:helix-activate after the page moves on Pagination and Data Table, and after
the slide moves on Carouselhelix-sorted, helix-filtered, helix-selected, and helix-reordered on
Data Tableinput and change together on Pagination Size, as a native <select>
sends themA request that is refused sends no notification. Date Picker's helix-navigate
moves the month on show, and the month sends no notification.Events in a frameworkNative events use their usual props, such as onChange, onInput, and
onToggle, which every framework already understands. A prefixed event uses
on followed by the exact name, such as onhelix-before-change. Nothing
removes the prefix or converts it to camel case. That is React's own behavior.
See React, Vue, and Svelte.