Series: Ember Actions

Actions and Components in Ember 1.x

Published on Sep 18, 2015

Learn how actions are passed from and between components in Ember 1.x.

Although some of this is superseded by closure actions, these methods are still possible in Ember 2.x, and are key to understanding legacy apps.


Links

Code

Send an action up from a component:

this.sendAction('actionName', arguments)

Catch in the component declaration:

{{component-name actionSentUpFromComponent="nameOfActionInControllerOrParentComponent}}

In demonstrations/actions/template.hbs

{{control-accessory showModalDialog="showModalDialog" pressRelease="pressRelease" takeOffHat="takeOffHat" itemName="hat"}}
{{control-accessory showModalDialog="showModalDialog" pressRelease="pressRelease" takeOffHat="takeOffHat" itemName="necklaces"}}
{{control-accessory showModalDialog="showModalDialog" pressRelease="pressRelease" takeOffHat="takeOffHat" itemName="shoes"}}

In components/control-accessory/component.js

import Ember from 'ember';

export default Ember.Component.extend({
  hasItem: false,
  itemColor: "blue",
  colors: ["blue", "red", "green", "purple", "orange"],
  actions: {
    putOnItem(color){
      this.set('itemColor', color)
      this.set('hasItem', true)
      this.sendAction('pressRelease')
    },
    takeOffItem(){
      this.set('hasItem', false)
      this.sendAction('takeOffItem')
    },
    howToRemoveItem(){
      this.sendAction('showModalDialog', 'we realize it is difficult to remove our proprietary vicelok Items')
    }
  }
})

In components/control-accessory/template.hbs:

{{#if hasItem}}
  <p>You're wearing a <span style="color:{{itemColor}};">{{itemColor}}</span> {{itemName}}.</p>

  <button {{action 'takeOffItem'}}>Take off the {{itemName}} <button {{action 'howToRemoveItem' bubbles=false}}>How?</button></button>
{{else}}
  {{color-selector itemName=itemName itemColor=itemColor putOnItem="putOnItem"}}
{{/if}}

In components/color-selector/template.hbs

Put on a {{itemName}}:
{{#each colors as |color|}}
  <button {{action 'putOnItem' color}} style="color:{{color}};">{{color}}</button>
{{/each}}

In components/color-selector/component.js

export default Ember.Component.extend({
  colors: ["blue", "red", "green", "purple", "orange"],
  actions: {
    putOnItem(color){
      this.sendAction('putOnItem', color)
    }
  }
});

Transcript

In this episode, we’re going to be talking about how to pass actions from one component to another and eventually to a controller. This is how actions will pass through components all throughout the ember 1.x series, and you’re still allowed to do it in the ember 2.0 series. In newer apps, you’ll be wanting to do the ‘Closure Actions’ which we’ll be covering in the next episode and the episode after that. However, you’re still going to be seeing a lot of this old style, especially if you’re working on an older version of ember or working with the legacy app, so it pays to know it.

So where we last left our startup Hat.io,

we had several buttons which they would send up actions and those actions would then put up a message. Now they want to expand their product line to more than just hats, so they’ll need to componentize all the logic they have here.

So just by copying and pasting, we can make it so it looks the same, and even the actions work, except they aren’t sending up and sending messages. Recall those messages were in the route, so these actions are not getting up to the route.

So the first thing to note is that these previous methods we used this.send and return true, those don’t work anymore. this.send we’ll replace with this.sendAction. So when we’re inside a component, we use sendAction, and then we’ll also have to connect it in the template. So here we’re going to take the showModalDialog action, and we’ll link it up like this, because remember, a component is its own encapsulated thing, and we have to poke little holes into it, and we’re going to have to poke holes into it for each one of these actions that we send up. So now when we press this button, it sends the showModalDialog action up to the controller, which then bubbles up to application route.

For the other two, here we’ll just change send to sendAction, and then we replace return true with this.sendAction(‘takeOffHat’).

Then we’ll poke two holes in the component, one for each of those actions that we’re sending up.

It is important to note that the thing on the left side = doesn’t have to be the same word as on the right side of the =. So the one on the left side is what’s used inside the component, and the string on the right is the action that will be passed to outside the component.

We can see that in the modal dialog component we had last time. So close is something that’s defined on the modal dialog, and then closeModalDialog is an action that we define that’s called whenever close is sent up.

So we originally wanted this so we could have different items than just hats. So with a snap we will make it generic. So you replaced all references of hat with item, and then we had an itemName, which in this case will be hat. But we case easily replicate this and make one for necklaces and shoes, so then we come in here

and now we’ve greatly expanded our product line, and it’s all working great. This is all thanks to components and indirectly thanks to component actions.

So to review what we’ve done so far, here for the putOnItem action, we’re taking that action and then in the component, putOnItem is doing something and then it’s doing the sendAction of pressRelease. And then we’ve poked a hole. This hole, a pressRelease sized hole, into the control accessory component when we’re calling it. And then that bubbles up, and eventually hits this action in the route. But this action passing doesn’t have to be just between a component and a controller. It can also be between components.
So here we’re going to abstract away this

and replace it with a color-selector component 04:16 passing it the itemName, the itemColor, and the action putOnItem.

In the color selector template, we’ll paste in what we copied from the previous one, and then in the component, the putOnItem action, we’ll just take the color and then pass on the putOnItem action up the line with the color as well. This sort of thing may seem wasteful and the exact sort of thing that ember is supposed to save you from. But, in the old days before closure actions, this is how you had to do it.

So in this episode we saw how to use actions in ember components in ember 1.x. We focused on poking holes in the component, and then using sendAction from an action in the component to push it up through those holes. So we are basically manually bubbling stuff up. Lots of times this works great, sometimes it can result in inefficiencies. We’ll see how those inefficiencies can be fixed in our next screencast where we look at ‘Closure Actions’. I’ll see you then.

Ember Actions

Subscribe to our mailing list