lu-on
lu-on is used to attach event listeners to elements. It supports both inline expressions and method calls from your scope.
Shorthand
The @ character is a shorthand for lu-on.
<!-- full syntax -->
<button lu-on:click="doSomething">Click Me</button>
<!-- shorthand (preferred) -->
<button @click="doSomething">Click Me</button>Event Handlers
Inline Handlers
You can write JavaScript expressions directly in the @ directive.
<button @click="count++">Increment: {{ count }}</button>Method Handlers
If the logic is complex, use a method on the scope. Template object literals hold data only — they cannot declare methods — so return the method from a factory and hand the factory to the app:
<script type="module">
import { createApp } from "lune-js";
function Greeter() {
return {
greet(name) {
alert("Hello " + name);
}
};
}
createApp({ Greeter }).mount();
</script>
<div lu-scope="Greeter()">
<button @click="greet('User')">Greet</button>
</div>Accessing the Original Event
If you need the original DOM event object in an inline handler, you can pass the special $event variable.
<button @click="handleClick($event)">Click Me</button>If using a method handler, the event is automatically passed as the first argument if no arguments are provided in the template.
<!-- handleClick(event) will be called -->
<button @click="handleClick">Click Me</button>Event Modifiers
Lune provides modifiers to simplify common event handling tasks. Modifiers are postfixed with a dot.
.stop: Callsevent.stopPropagation().prevent: Callsevent.preventDefault().self: Only triggers the handler if the event was dispatched from the element itself (not a child).once: The handler will be triggered at most once.capture: Adds the listener in capture mode.passive: Adds the listener with{ passive: true }.exact: Only triggers if no additional system modifier keys are pressed
.once, .capture, and .passive are forwarded to addEventListener as listener options; the rest are checked when the event fires.
<!-- the click event's propagation will be stopped -->
<a @click.stop="doThis"></a>
<!-- the submit event will no longer reload the page -->
<form @submit.prevent="onSubmit"></form>
<!-- modifiers can be chained -->
<a @click.stop.prevent="doThat"></a>Keyboard Modifiers
You can use any valid key name (in kebab-case) as a modifier for keyboard events.
<!-- Only call `submit` when the `key` is `Enter` -->
<input @keyup.enter="submit" />
<!-- Works with other keys too -->
<input @keyup.page-down="onPageDown" />System Modifier Keys
You can restrict handlers to specific keyboard modifier keys.
.ctrl.shift.alt.meta
<!-- Only triggers when Ctrl+Enter is pressed -->
<input @keyup.ctrl.enter="submit" />.exact Modifier
The .exact modifier ensures the event only triggers when exactly the specified modifier keys are pressed (no additional system keys).
<!-- Only triggers when Ctrl is pressed, without Shift, Alt, or Meta -->
<button @click.ctrl.exact="onCtrlClick">Ctrl + Click</button>Mouse Button Modifiers
Restrict handlers to specific mouse buttons.
.left.right.middle
<button @click.right="showMenu">Right click for menu</button>On a click binding these two also swap the event being listened to: .right listens for contextmenu, and .middle listens for mouseup.
Special Lifecycle Events
Lune emits special events when an element is mounted or unmounted. These must be prefixed with lune: — the bare @mounted / @unmounted names log a development error telling you to add the prefix.
@lune:mounted: Fired when the element is mounted to the DOM.@lune:unmounted: Fired when the element is removed from the DOM.
<input @lune:mounted="$el.focus()" />Limitations
Handlers Run Through the Expression Engine
Inline handlers are compiled by Lune's expression engine, not by new Function(). Everyday handler code is unaffected, but window, document and fetch are not reachable from the attribute, and async/await and loops are not part of the supported subset. Put that logic in a scope method and call it:
<!-- will not run: `fetch` is not available to expressions -->
<button @click="fetch('/api/save', { method: 'POST' })">Save</button>
<!-- call a method instead, where it is ordinary JavaScript -->
<button @click="save">Save</button>Object Syntax Not Supported
The lu-on="eventHandlers" object syntax (passing an object of event handlers) is not supported in Lune. You must use individual @event bindings:
<!-- NOT supported -->
<button lu-on="{ click: onClick, focus: onFocus }">...</button>
<!-- Use individual bindings instead -->
<button @click="onClick" @focus="onFocus">...</button>