Series: Ember Actions

Closure Actions in Ember 2.0 Components-Passing Functions

Published on Sep 23, 2015

Closure actions, introduced in Ember 1.13 and gaining prominence in Ember 2.0, are an exciting improvement over the old way of doing actions. Instead of sending up an action call through the component chain, we pass down a function.

In this video we see how closure actions save you lots of code, especially in deeply nested components.


Links

Code

Pass down a function (an action) with the (action ...) subexpression.

{{control-accessory changeItem=(action "changeShoe") itemName="shoe" itemColor=shoeColor}}

In components/control-accessory/template.hbs we continue passing down the function through nested components. Notice we don't need an action in the javascript component file.

{{color-selector itemName=itemName itemColor=itemColor changeItem=attrs.changeItem}}

In the component, call the function like a regular function.

actions: {
  changeItem(color){
    this.attrs.changeItem(color)
  }
}

Transcript

Hey and welcome to EmberScreencasts. Today we’re going to be talking about closure actions. They’re a new feature that was introduced in Ember 1.13, and they’re going to be taking much greater prominence in Ember 2.0.

Let’s take a look at the app we’ll be working with today. It’s changed a little bit since the previous iterations. So we have three different types of accessories, these are done with a component, and then you click what color you want and it’ll change. You can also hit none. Now currently we have this set up with 1.x actions, the type of actions it’s been using for a long time. We’re going to show you how that works, how the new ones work, and how those are different.

So currently we’re using two nested components, color-selector and control-accessory, within the actions route. We’ll start at the lowest level. Here is where we’re looping through all the colors and we’re able to hit a button. And so when we hit that button it calls the changeItem action, and then what it does is it goes to the component file, to the JavaScript part of it, and it finds that action. And then it’s going to send the action up. And so what we have here in the one that’s above it, so when we’re declaring the color-selector, we poke a hole in it for changeItem. And so this will catch that changeItem action, like alright, I know what changeItem is, and I’m going to try and find a changeItem action on me. And what do you know, there is one. Then it does the exact same thing. It’s like alright, I know what changeItem is, I’m going to send changeItem up again.

Now here in the template of our controller, we’re doing something a little bit different. Instead of just sending it up to changeItem, because we have three different iterations to control-accessory, we’re sending it up to different actions. The action we send it up to changes depending on what the item is that we’re talking about within that component. And then of course in the controller we’re defining the different actions as well as the things they change, hatColor, necklaceColor, and shoeColor. If any of this was confusing to you, I recommend you go to my previous episode on Ember 1.x actions and components where it’s explained in more detail. We’re going to be moving on to the Ember 1.13 and 2.0 actions.

So let’s start with the mindset we need to have about these new function-passing actions. So previously we were grabbing an action, we were passing it up, catching it, passing it up again. We kept on passing it up until it hit the controller and we actually did something with it. In our new mindset, we’re going to be taking that function on the controller and pushing it down into the component, and the component can call that action. So let’s see what that looks like in action.

So here in the controller template, we’re going to be passing down an action. And the way we do that is to use the action helper and then the name of the action. We’ll see in the next episode different things you can use this for. So this is much more flexible than the old way.

So we’re sending down the action using handlebars subexpressions. That’s what the parentheses mean. And if you’re confused about that, then you can check out my episode on it, Episode 24.

So now moving down the control-accessory template, here we have the old version where it was recognizing, hey, when you pass up that action, here’s where we’re going to send it. But now we’re passing down the function. So we’re going to call the attrs hash. And attrs is a new thing introduced in 1.13 that takes all the values that you put in a component. So changeItem, itemName, and itemColor are attrs that are available here. So we’re going to use attrs.changeItem and that will pass down the function. And what that means is that this changeItem on the component, it is no longer necessary, so we can get rid of that. And if you have deeply nested components, this is going to save you a lot of code. So then we go down, we go down to the color-selector component and instead of sending the action, what we’re going to do is call this.attrs.changeItem. We’re calling a method instead of sending an action. And so this is the changeItem method that has been passed down through the control-accessory and through the controller.

So getting rid of a lot of code in your nested components is one of the easiest benefits to see from switching to the Ember 1.13 and Ember 2.0 actions. However, there are lots of new cool things you can do with it that just weren’t possible before. In our pro-episode this week, we’re going to be talking about how to use parameter currying, a new feature in closure actions, to do some really cool metaprogramming. Using this metaprogramming, you can add accessories incredibly easily just by adding to a list and then the metaprogramming takes care of the rest for you. So we just added those two, and here they are, already working. I look forward to showing you the details.

Ember Actions

Subscribe to our mailing list