Ember closure actions

Abhilash L R
ember-titbits
Published in
2 min readFeb 18, 2017

=> for versions above 1.13.x

In old versions of Ember (< 1.13) sendAction was the only way for a component to call an action on a parent scope. In 1.13, with the so called closure actions, a more intuitive and flexible way of calling actions was introduced, yielding the old way redundant.

So what does this offer? Functions down actions up! Yes, in Ember 1.13 and above, a function can be simply passed down to components nested down in deeper hierarchy without writing multiple sendAction calls like it was required in < 1.13

“Enough talking, give us an example” — wasn’t that the statement running in your head? ;) Read below:

The traditional approach using sendAction:

// components/foo-bar-parent.js
export default Ember.Component.extend({
actions: {
sendDataToController() {
this.sendAction('sendData', 1);
}
}
});
// templates/foo-bar-parent.hbs
{{foo-bar-child sendDataToController='sendDataToController'}}
// components/foo-bar-child.js
export default Ember.Component.extend({
actions: {
sendDataToParent() {
this.sendAction('sendDataToController', 1);
}
}
});
// templates/foo-bar-child.hbs
<button {{action 'sendDataToParent'}}>Click me</button>
// controllers/foo/show.js
export default Ember.Controller.extend({
actions: {
sendData(data) {
alert(data);
}
}
});
// templates/foo/show.hbs
{{foo-bar-parent sendData='sendData'}}

The amount of action binding! Isn’t it confusing? Now, transform the same example to closure action:

// components/foo-bar-parent.js
export default Ember.Component.extend({
// No definition required
});
// templates/foo-bar-parent.hbs
{{foo-bar-child sendData=(action @sendData)}}
// components/foo-bar-child.js
export default Ember.Component.extend({
// Nothing required here either.
});
// templates/foo-bar-child.hbs
<button {{action @sendData}}>Click me</button>
// controllers/foo/show.js
export default Ember.Controller.extend({
actions: {
sendData(data) {
alert(data);
}
}
});
// templates/foo/show.hbs
{{foo-bar-parent sendData=(action 'sendData')}}

However, this is a very simple use case, but in real world scenarios we might have to perform some actions in intermediate components. Also, what if the controller did not specify the sendData action and that the action is optional? It would throw an error. This could be prevented by adding a guard on the child component.

Did you also notice the @ sign used in the templates? It means, that the function has been passed from the parent and is not part of that component.

NOTE: This does not mean sendAction is totally removed, but is available until last versions of Ember 3.X and would result in deprecation warnings to help apps/add-on authors to migrate easily. A more detailed explanation into Ember’s closure actions is in here.

If you like this post or find anything misleading, do post your comments!

--

--

Abhilash L R
ember-titbits

Loves to travel, writes about programming, photography, life lessons and sometimes cooking