Event handlers
Edit this pageEvent handlers are functions that are called in response to specific events occurring in the browser, such as when a user clicks or taps on an element.
Solid provides two ways to add event listeners to the browser:
on:__
: adds an event listener to theelement
. This is also known as a native event.on__
: adds an event listener to thedocument
and dispatches it to theelement
. This can be referred to as a delegated event.
Delegated events flow through the component tree, and save some resources by performing better on commonly used events. Native events, however, flow through the DOM tree, and provide more control over the behavior of the event.
Using events
To add an event handler, prefix the event name with either on
or on:
, and assign it to the function you wish to call when the event is dispatched.
Delegated events are not case sensitive, therefore using delegated event handlers in Solid can be written using camelCase or all lowercase. Note that while delegated events can be written both ways, native events are case sensitive.
For any other events, such as custom events or events you wish not to be delegated, the on:
attribute will add an event listener as-is.
This is what makes the event listener case sensitive.
For typing standard or custom events using on:
, the TypeScript page has a section about event handlers.
Binding events
To optimize event handlers, you can pass an array as the event handler, replacing the function. When doing this, the second item passed into the array is supplied as the handler's first argument:
In this example, the Hello!
string is passed as the data
parameter in the handler
function when the button is clicked.
By binding events in this way, Solid avoids the overhead of using JavaScript's bind method and adding an additional closure.
Dynamic handlers
An event handler does not form part of the reactive system. If you were to pass the handler as a signal, it will not respond to the changes of that signal. In other words, events do not dynamically update, and the bindings are not reactive. This is because attaching and detaching listeners is a resource-intensive task.
Since event handlers are called like a standard function, you can design them to call a reactive source, if needed.
In the following example, handleClick
represents a prop that has the flexibility to adopt any function.
As a result, there is no requirement for these functions to be reactive.
Event delegation
Instead of attaching event listeners to every individual element, Solid uses synthetic event delegation, through the on__
form .
In this method event listeners are attached to the document
element, and dispatch events to the relevant elements as they bubble up.
By keeping the number of event listeners to a minimum, events can be captured more effectively. This is especially useful when working with a large number of elements, such as in a table or list.
Supported events such as click
, input
and keydown
are just a few examples that are optimized in this way.
To view the full list see the references below.
If you need to attach an event listener to an element that is not supported by Solid's event delegation, such as a custom event in a custom element, you can use the on:__
form.
Event delegation considerations
While delegated events provide some performance enhancements, there are tradeoffs.
Event delegation is designed for event propagation through the JSX Tree, rather than the DOM Tree. This can differ from the previous expectations of how events work and flow.
Some things to keep in mind include:
- Delegated event listeners are added once per event type and handle all future events of that type.
This means that delegated event listeners remain active even if the element that added them and its handler is removed.
For example, if a
div
listens formousemove
and is later removed, themousemove
events will still be dispatched to thedocument
in case a different element is also listening for mouse moves.
Rather than using delegated events for events that happen infrequently, native events are a better solution. Since these events happen in specific circumstances, they do not benefit from the performance improvements you get with event delegation.
-
event.stopPropagation()
does not work as expected since events are attached to thedocument
rather than theelement
.With cases like this, a native event is recommended. As an example, using a native event would stop the following event from reaching the
div native
handler, which is not the case for delegated events. You can view this example in the Solid Playground.
You can solve this by switching the button
event to using a native event:
See how this solution differs in the Solid Playground.
- Portals propagate events following the component tree and not the DOM tree, making them easier to use.
This means when a
Portal
gets attached to thebody
, any events will propagate up to thecontainer
.
onChange
and onInput
events work according to their native behavior:
onInput
will fire immediately after the value has changed- In
<input>
fields,onChange
will only fire after the field loses focus.
List of delegated events
You can also view this list in our source code (see DelegatedEvents
).