on… handlers
Native-style on<event> attributes. Inside component markup they work for every event name, native or custom. On a plain page, REALM adds handler attributes and properties for the custom events its components send.
<button onclick="save(item)">Save</button>
<rating-stars onrate="saveRating(event.detail.value)"></rating-stars>In component markup
The attribute value is JavaScript, compiled together with the component script (no eval at event time). It runs as a listener on that element.
| Name | Value |
|---|---|
event |
The event object |
this |
The element the attribute is on |
| Loop variables | The as and index names of every enclosing repeat / <repeat-list> |
| Script names | Every top-level name of the component script |
| Helpers | The script helpers (host, dispatch, refs, …) |
| Any other name | Looked up when the handler runs: parent components first, then globalThis |
- Returning
falsecallsevent.preventDefault(). - Listeners are added with the element's
signaland removed with it. debounceandthrottleon the same element time the handler, except on elements with fetch attributes, where they time the request instead.- A component compiles its handler code once per definition, not per instance.
On a plain page
Browsers only support handler attributes for native event names. For each REALM component, REALM finds the custom events it sends and adds:
- an
on<name>attribute whose value is JavaScript, compiled when the element connects and recompiled when the attribute changes, and - an
on<name>property that accepts a function (ornull) and stays in sync with the attribute.
<rating-stars onrate="console.log(event.detail.value)"></rating-stars>
<script>
document.querySelector("rating-stars").onrate = (event) => {
if (event.detail.value < 2) return false;
};
</script>| Detail | Behaviour |
|---|---|
| Event names | Read from the component script: dispatch("name", new CustomEvent("name" and new Event("name" |
| Native names | Names that already have an on… property on HTMLElement (change, input, toggle, close, …) are left to the browser |
this |
The element |
return false |
Calls preventDefault() |
| Syntax errors | The attribute is ignored |
| Attributes set before the element was defined | Compiled when it connects |
Page handler attributes run in the page scope, so a strict Content Security Policy blocks them like any inline handler.
Example
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>on… handlers demo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
<script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
</head>
<body>
<import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/button.html"></import-element>
<import-element from="./like-button.html"></import-element>
<like-button onlike="document.getElementById('like-log').value = 'Liked ' + event.detail.count + ' times'"></like-button>
<output id="like-log">No likes yet.</output>
</body>
</html><custom-element name="like-button">
<script>
const likes = useState({ count: 0 });
function like() {
likes.count++;
dispatch("like", { count: likes.count });
}
</script>
<ui-button variant="outline" onclick="like()">Like (<slot name="#likes.count"></slot>)</ui-button>
</custom-element>