Events
Marko’s event API supports:
- Browser events on native tags
- Custom events from custom tags
Note that you can’t mix event targets and event types: custom tags can only listen for custom events, and native tags can only listen for native events.
Listening to events
Both kinds of events are received with an on-*
attribute and the attribute arguments syntax:
<input type="checkbox" on-change(event => console.info(`Checked? ${event.target.checked}`)) />
input [ type="checkbox" on-change((event) => console.info(`Checked? ${event.target.checked}`)) ]
The first argument for the attribute can be a function, or a string matching a method name on the component’s class
declaration.
Function handler
If you provide a function as the first argument of the on-*
attribute, the function is called whenever the event fires, like standard event listeners.
Below we use the static
prefix to define a function, then use it as a click
handler:
static function handleClick(event) { event.preventDefault(); console.log("Clicked!"); } <button on-click(handleClick)> Log click </button>
static function handleClick(event) { event.preventDefault(); console.log("Clicked!"); } button on-click(handleClick) -- Log click
In the above example, any time the <button>
is clicked the handleClick
function is called.
You can also use an inline arrow function:
<button on-click(() => alert("Clicked! 🎉"))> Celebrate click </button>
button on-click(() => alert("Clicked! 🎉")) -- Celebrate click
…or anything that evaluates to a function:
$ const handler = ( input.dontBreakMyApp ? () => console.error("Clicked!") : () => { throw Error("Clicked!") } ); <button on-click(handler)> Do not click </button>
$ const handler = ( input.dontBreakMyApp ? () => console.error("Clicked!") : () => { throw Error("Clicked!"); } ); button on-click(handler) -- Do not click
Method handler
When a string is the first argument, Marko calls a matching method on the component's class
.
class { logChange(newTab) { console.log(`changed to: ${newTab}`); } } <my-tabs on-switch-tab("logChange")> … </my-tabs>
class { logChange(newTab) { console.log(`changed to: ${newTab}`); my-tabs on-switch-tab("logChange") -- …
When <my-tabs>
emits the switch-tab
event, it will call its logChange
method.
Within the handler you can access the current component instance, read data, emit events, update state, etc.
Binding additional arguments
Arguments after the handler are prepended when the handler is called:
static function removeFriend(friendId, event) { event.preventDefault(); window.myAPI.unfriend(friendId); } <for|friend| of=input.friends> <button on-click(removeFriend, friend.id)> Unfriend ${friend.name} </button> </for>
static function removeFriend(friendId, event) { event.preventDefault(); window.myAPI.unfriend(friendId); } for|friend| of=input.friends button on-click(removeFriend, friend.id) -- Unfriend ${friend.name}
Here we share the logic for removeFriend()
with each friend
in the friends
array. When the <button>
is clicked, the id
of the removed friend
is passed to the removeFriend()
, handler followed by the DOM click
event.
Emitting custom events
The recommended way for a custom tag to communicate with its parent is through custom events.
All components implement a Node.js-style event emitter to send events to parent components.
email-input.marko
class { handleChange(event) { if (event.target.validity.valid) { // Only emit email-changes if they are valid. this.emit("email-change", { email: event.target.value }); } } } <input type="email" name=input.name on-change("handleChange")/>
class { handleChange(event) { if (event.target.validity.valid) { // Only emit email-changes if they are valid. this.emit("email-change", { email: event.target.value }); input type="email" name=input.name on-change("handleChange")
The above code listens to native change
events from the <input>
element, and then emits its own email-change
event if the change was valid.
<form> <email-input name="email" on-email-change("...")/> </form>
form email-input name="email" on-email-change("...")
EDITNote: Events are not received as
input
; you cannot accessinput.onEmailChange
. Instead, they set up subscriptions.
Contributors
Helpful? You can thank these awesome people! You can also edit this doc if you see any issues or want to improve it.