There are two kinds of {{action}} in Ember Classic: the modifier, and the helper—and both of them had their own special sauce. Octane simplifies this by providing the {{on}} modifier and the {{fn}} helper, each of which does just one thing.
{{on}}In Ember Classic, the {{action}} modifier can be applied to a component to bind its event handling, handling click events by default, and it looks up methods in the actions object on a backing class by string name:
<button type="button" {{action "doIt" on="doubleClick"}}>Click me twice!</button>
There are three changes for using {{on}} instead:
click events on a <div>—don't do that!).actions object is no longer used; instead, any method on the backing class may be used—so simply doing this.doIt is appropriate.dblclick instead of doubleClick.Putting them all together, and we would rewrite the example above like this:
<button type="button" {{on "dblclick" this.doIt}}>Click me twice!</button>
<aside>
💡 Note: the action on the backing class should always be decorated with @action to make sure it's safe to call and pass around! The details: @action binds the context of the method: it keeps the this the same no matter what—like using the bind method.
</aside>
{{fn}}In Ember Classic, the {{action}} helper does two things: partial application of arguments, and looking up methods in the actions object on a backing class. So for example, when passing an action to a component:
<FancyButton @onClick={{action "doIt" 1}} />
Then in the body of FancyButton, we might have something like this:
<button type="button" {{on "click" (action @onClick "two")}}>click!</button>
Here, the doIt method on the backing class would receive both 1 and "two" as arguments.
This ability to partially apply arguments is very useful, so we now do that with {{fn}}. As noted above in the discussion of {{on}}, we no longer need the ability to look up values in the actions object!
We would rewrite the above example like this:
<FancyButton @onClick={{fn this.doIt 1}} />