Skip to content

Latest commit

 

History

History
137 lines (102 loc) · 4.61 KB

event_handling.md

File metadata and controls

137 lines (102 loc) · 4.61 KB

🦉 Event Handling 🦉

Content

Event Handling

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. There are four different use cases.

  1. Register an event handler on a DOM node (pure DOM event)
  2. Register an event handler on a component (pure DOM event)
  3. Register an event handler on a DOM node (business DOM event)
  4. Register an event handler on a component (business DOM event)

A pure DOM event is directly triggered by a user interaction (e.g. a click).

<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.

Business DOM Events

A business DOM event is triggered by a call to trigger on a component.

<MyComponent t-on-menu-loaded="someMethod" />
 class MyComponent {
     someWhere() {
         const payload = ...;
         this.trigger('menu-loaded', payload);
     }
 }

The call to trigger generates an OwlEvent, a subclass of CustomEvent with an additional attribute originalComponent (the component that triggered the event). The generated event is of type menu-loaded and dispatches it on the component's DOM element (this.el). The event bubbles and is cancelable. The parent component listening to event menu-loaded will receive the payload in its someMethod handler (in the detail property of the event), whenever the event is triggered.

 class ParentComponent {
     someMethod(ev) {
         const payload = ev.detail;
         ...
     }
 }

By convention, we use KebabCase for the name of business events.

The t-on directive allows to prebind its arguments. For example,

<button t-on-click="someMethod(expr)">Do something</button>

Here, expr is a valid Owl expression, so it could be true or some variable from the rendering context.

Inline Event Handlers

One can also directly specify inline statements. For example,

<button t-on-click="state.counter++">Increment counter</button>

Here, state must be defined in the rendering context (typically the component) as it will be translated to:

button.addEventListener("click", () => {
  context.state.counter++;
});

Warning: inline expressions are evaluated in the context of the template. This means that they can access the component methods and properties. But if they set a key, the inline statement will actually not modify the component, but a key in a sub scope.

<button t-on-click="value = 1">Set value to 1 (does not work!!!)</button>
<button t-on-click="state.value = 1">Set state.value to 1 (work as expected)</button>

Modifiers

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.
<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.