In a component's template, it is useful to be able to register handlers on DOM
elements to some specific events. This is what makes a template alive. This
is done with the t-on
directive. For example:
<button t-on-click="someMethod">Do something</button>
This will be roughly translated in javascript like this:
button.addEventListener("click", component.someMethod.bind(component));
The suffix (click
in this example) is simply the name of the actual DOM
event. The value of the t-on
expression should be a valid javascript expression
that evaluates to a function in the context of the current component. So, one
can get a reference to the event, or pass some additional arguments. For example,
all the following expressions are valid:
<button t-on-click="someMethod">Do something</button>
<button t-on-click="() => this.increment(3)">Add 3</button>
<button t-on-click="ev => this.doStuff(ev, 'value')">Do something</button>
Notice the use of the this
keyword in the lambda function: this is the
correct way to call a method on the component in a lambda function.
One could use the following expression:
<button t-on-click="() => increment(3)">Add 3</button>
But then, the increment function may be unbound (unless the component binds it in its setup function, for example).
In order to remove the DOM event details from the event handlers (like calls to
event.preventDefault
) and let them focus on data logic, modifiers can be
specified as additional suffixes of the t-on
directive.
Modifier | Description |
---|---|
.stop |
calls event.stopPropagation() before calling the method |
.prevent |
calls event.preventDefault() before calling the method |
.self |
calls the method only if the event.target is the element itself |
.capture |
bind the event handler in capture mode. |
.synthetic |
define a synthetic event handler (see below) |
<button t-on-click.stop="someMethod">Do something</button>
Note that modifiers can be combined (ex: t-on-click.stop.prevent
), and that
the order may matter. For instance t-on-click.prevent.self
will prevent all
clicks while t-on-click.self.prevent
will only prevent clicks on the element
itself.
Finally, empty handlers are tolerated as they could be defined only to apply modifiers. For example,
<button t-on-click.stop="">Do something</button>
This will simply stop the propagation of the event.
In some cases, attaching an event handler for each element of large lists has a non trivial cost. Owl provides a way to efficiently improve the performance: with synthetic event, it actually adds only one handler on the document body, and will properly call the handler, just as expected.
The only difference with regular events is that the event is caught at the document body, so it cannot be stopped before it actually gets there. Since it may be surprising in some cases, it is not enabled by default.
To enable it, one can just use the .synthetic
suffix:
<div>
<t t-foreach="largeList" t-as="elem" t-key="elem.id">
<button t-on-click.synthetic="doSomething" ...>
<!-- some content -->
</button>
</t>
</div>
The t-on
directive also works on a child component:
<div>
in some template
<Child t-on-click="dosomething"/>
</div>
This will catch all click events on any html element contained in the Child
sub component. Note that if the child component is reduced to one (or more) text
nodes, then clicking on it will not call the handler, since the event will be
dispatched by the browser on the parent element (a div
in this case).