@event
Attach event listeners right inside the component template with @-prefixed attribute names.
Syntax
<element @event="handler"></element>
Parameters
- @event
- The event type, as passed to .addEventListener(). For example @click, @focus or @change.
- handler
- A block of JavaScript, to be executed when the event fires. This may include not only expressions, but also statements such as if statements and for loops. It is treated as a regular (non-asynchronous) function body. Inside the function body, the event parameter is made available. The this value inside the handler resolves to the element the handler was attached to.
Details
Like other in-template shorthands, the @event syntax removes any listeners when the component is disconnected from the DOM. Upon reconnecting, listeners are re-attached. The event handler, i.e. the function body, does not run in a monitored context.
Examples
Spoilers
Let's create a custom element for spoilers. It will be an inline element, rendering its contents inside a <span> in its shadow root. By default, the span hides the content and shows a black bar. When clicked, the contents are revealed.
<title>spoiler-text</title>
<template mode="closed">
<span
@click="$.revealed = true"
:class+revealed="$.revealed"
>
<slot></slot>
</span>
</template>
<style>
span:not(.revealed) {
background: black;
slot { visibility: hidden; }
}
</style>
Theoretically, we can optimize this by removing the event listener after it has run once, since users can't un-reveal the spoiler. In cases like such, where event listeners need to be configured in a more granular or specific way, write them out explicitly using connected()
and when()
.
List items
For a more complex example, let's write a component that includes a text input, and lets the user enter lines of text. When they press Enter, the input is cleared and the text is inserted into a <pre> element. We can do this using a @keydown expression with an if() statement inside:
<title>list-items</title>
<template mode="closed" delegates-focus="true">
<input
type="text"
@keydown="if (event.key == 'Enter') {
$.$lines.unshift(this.value);
this.value = '';
}"
>
<pre>{{ $.lines.join('\n') }}</pre>
</template>
<script>
$.lines = [];
</script>
While it is not recommended to write full function bodies inline in the <template>, it is certainly possible and the example demonstrates both usage of the event argument as well as the this value (which resolves to the <input> here).
See also