Let's experiment with the new {{on}} modifier that shipped with Ember 3.11, and is the new recommended way to handle events in Ember.

We'll take a look at an existing template in EmberMap's code base:

< button onclick = {{ action 'increasePlaybackRate'}} > {{fa-icon 'plus'}} </ button >

Currently, we're using closure actions to wire up this click event.

Closure actions are one of two existing ways to wire up actions in Ember. The other way is using the action modifier:

< button {{ action 'increasePlaybackRate'}} > {{fa-icon 'plus'}} </ button >

The action modifier is the original way events were handled in Ember, and it has some drawbacks:

it binds the correct this context in a magical and non-intuitive way

context in a magical and non-intuitive way it listens for the click event by default, and uses a strange on="mouseenter" option to allow users to change the event

event by default, and uses a strange option to allow users to change the event it's become more confusing with the addition of the action helper, which has completely different functionality from the action modifier

When closure actions were introduced, they improved on the action modifier in many ways. But they too have some drawbacks:

the <div onclick={{action 'handleClick'}}> syntax works because of an inconsistent DOM API, reflection. The template is setting the onclick attribute, which is then reflected to the actual DOM node's onclick property. This ambiguity causes a few problems: it doesn't work the same for all events, and it's not robust to server-side rendering.

The {{on}} modifier was introduced to address these shortcomings. It looks like this:

< button {{on 'click' (action 'increasePlaybackRate')}} > {{fa-icon 'plus'}} </ button >

and it's effectively sugar for the addEventListener API:

buttonEl.addEventListener( 'click' , this .increasePlaybackRate);

There are several benefits to {{on}} :

it's explicit

it works consistently for all events

it works with web components

it is robust to SSR, because all modifiers are stripped out and ignored in a server-side environment

it can be used multiple times

The biggest thing to note is that on does not bind this context. It's important to understand this, and the role it will play along with the other new primitives coming to Octane, notably the action decorator and the fn modifier. Those will be addressed in a future video.

on is solely about setting up (and tearing down) event listeners via the addEventListener API, all from templates. action can still be used to bind the correct context.

< button {{on 'click' (action 'increasePlaybackRate')}} > {{fa-icon 'plus'}} </ button >

So give the new on modifier a shot in your own apps! I think you'll appreciate the clarity and explicitness of this new modifier.

Here's some links for reference: