Series: Ember Actions

Closure Actions in Ember 2.0 Components-Metaprogramming with Parameter Currying

Published on Sep 25, 2015

Closure actions don't just save you code in what you're already doing- they allow you to do things that you had previously rejected as too difficult or verbose.

In this video we focus on parameter currying, first showing a basic use of it that eliminates some repetition, and then diving deep into metaprogramming in order to make a more dynamic page.


Links

Code

In the controller we take the list of item names then automatically generate an array of items with the color and name attributes. Then the changeItem method can change an arbitrary item to an arbitrary color.

export default Ember.Controller.extend({
  items: ['hat', 'necklace', 'shoe'],
  itemDetails: Ember.computed(function(){
    return this.get("items").map(function(itemName){
      return {
        itemName: itemName,
        itemColor: 'none'
      }
    })
  }),

  actions: {
    changeItem(itemName, newColor){
      this.set(`itemDetails.${itemName}.itemColor`, newColor)
    }
  }
})

We loop through the array of items, displaying each while currying the appropriate parameters.

{{#each itemDetails as |item index|}}
  {{control-accessory changeItem=(action "changeItem" index) itemName=item.itemName itemColor=item.itemColor}}
{{/each}}

Adding new items to the page is now as simple as adding their name to the array

  items: ['hat', 'necklace', 'shoe', 'slap bracelet', 'scarf'],

Transcript

In today’s episode, we’re going to be talking about using one of the really cool features of closure actions in Ember 2.0, and that’s parameter currying. We’ll also see some great applications of its metaprogramming.

So to refresh your memory, we’re working on the site Accessor.ly, and you can put on and remove accessories. So most of that action happens within the control-accessory component, with the exception of the changeItem action, which we’re passing down three different actions as the changeItem action. And the reason we’re passing down those different items is because they need to change different variables. So changeHat changes hatColor, changeNecklace changes necklaceColor, and changeShoe changes shoeColor.

So what if we wanted to condense this all into a changeItem method? There are ways to do this without closure actions and currying, but they’re messy, so we won’t go into them. What you need to know is that for this, we can change it to changeItem, and then we give it HatColor. So within changeItem, it not only gets the color, it’ll get the colorToBeChanged. And then we set the colorToBeChanged. So hatColor is using this new changeItem method. Let’s see that it works. We can indeed change the color of the hat. Now we can get rid of these two actions and change changeNecklace and changeShoe to changeItem, and we’ll see that they all work using the same action.

Let’s look at the details of how this works. So here in the action helper, we’re giving it the name of the action that we want, and then we’re giving it the name of the first parameter. So here that parameter is colorToBeChanged. And then the other parameters that are passed up will be second, third, etc. So it goes the curry parameters first and then the rest of the parameters.

So this is good so far. We’ve changed three almost identical actions into one action, but we can do more. What we’re about to do is a little complicated, so I’ll just change it with a snap of my fingers, and then explain what’s happening.

So now instead of having hatColor, necklaceColor, and shoeColor, what we have is a list of all our items. And then we have another list, an array of all the itemDetails. And that will include the itemName and the itemColor which by default is none. This is a computed property that gets set at the beginning based on the list of items. Then in our changeItem action, it’s getting passed the itemIndex and the newColor, so we’re setting... we’re taking the itemDetails array, we’re finding the correct index and then setting that color on it with the newColor that’s being passed.

In the template, we’re looping through the itemDetails. Instead of having the name of the color like we did before, we’re having the index that that item is at, and that’s what we’re passing as the curry parameter. And of course we have to change the itemName and itemColor so that it’s being passed correctly. And this of course works exactly like before, but the difference is that to add something new is incredibly easy. So if we want to add say snap bracelets and scarves, that’s all we have to do. We now have snap bracelets and scarves, and the code is already working.

So this type of metaprogramming is incredibly useful when you want your application to be flexible. For example, you might have the user being able to choose what type of accessories they want to show. Or you might have stuff pulled from a database that shows differently depending on the user or what screen you’re on. So while not all of this is technically impossible without parameter currying, it definitely would be much harder and less elegant.

I hope you find a fun way to apply this in your own app and I’ll see you next week with more applications of Ember 2.0’s closure actions.

Ember Actions

Subscribe to our mailing list