21

I have a list of items:

  <ul>
    {{#each applications}}
      <li>
        <a {{bindAttr href="url"}} 
        {{action "appClicked" on="click"}}>                
           {{name}}
        </a>
      </li>
    {{/each}}
  </ul>

On click it calls the method appClicked of the view, that this template belongs to. I want to pass some information (for example, the name of the application) to the method appClicked. Something like, {{action "appClicked(name)" on="click"}}.

Is it possible, and how?

Ry-
  • 218,210
  • 55
  • 464
  • 476
Panagiotis Panagi
  • 9,927
  • 7
  • 55
  • 103
  • 1
    There isn't currently a way to do what you want and I'd think that doing so doesn't quite sound right. I know this is just a small snippet of whatever you're trying to do but you shouldn't need to pass the `name` property (or any for that matter) to your action. The target should be the current view in the list. Could you provide a jsFiddle and maybe explain a bit more what problem you're trying to solve? – Roy Daniels Feb 07 '12 at 18:37
  • It is possible to do the answer here from the API http://stackoverflow.com/a/18473842/551811 – BraveNewMath Aug 28 '13 at 05:48

6 Answers6

19

Apparently, Ember has evolved now and there is an ability to pass a parameter to an action:

{{action "functionName" parameter}}

In your case, that would be:

<a {{bindAttr href="url"}} 
   {{action "appClicked" name on='click'}}>                
       {{name}}
   </a>

However, you could pass any attribute from the model (like the id) instead of the name.

See http://emberjs.com/guides/templates/actions/ for more information.

lauhub
  • 894
  • 1
  • 15
  • 27
19

The API says you can pass in multiple parameters.

html and handlebars:

{{officename}} 
<button {{action "actionTest" "hello" "goodbye" officename}}>See parameters through action in the console</button>

controller:

actionTest: function(a, b, c){
   console.log(a);
   console.log(b);
   console.log(c);
},

See it in action in this jsbin

HaoQi Li
  • 11,970
  • 14
  • 58
  • 77
6

I was thinking something more along the lines of this since you'll have access to a bunch more through an actual view. But Zack, if you could explain a bit more what exactly you're trying to do if this isn't what you're looking for?

App = Ember.Application.create();

App.peopleController = Ember.ArrayController.create({
    content: [ { name: 'Roy', url: '#' },
               { name: 'Mike', url: '#' }, 
               { name: 'Lucy', url: '#' } ]
});

App.PersonView = Ember.View.extend({
    tagName: 'li',
    content: null,
    linkClicked: function() {
        console.log(this.getPath('content.name'));
    }
});
<ul>
{{#each App.peopleController}}
    {{#view App.PersonView contentBinding="this"}}
        <a {{bindAttr href="content.url"}} {{action "linkClicked" on="click"}}>
            {{content.name}}
        </a>
    {{/view}}
{{/each}}
</ul>
Liam
  • 27,717
  • 28
  • 128
  • 190
Roy Daniels
  • 6,309
  • 2
  • 27
  • 29
  • I saw that solution, somewhere on SO (answered by Katz). As I understand, you have to create a separate View for *every* element that you want track events from (click, focus, etc.). Am I correct? I also found this pull https://github.com/emberjs/ember.js/pull/451 , not sure if this what I'm looking for. – Panagiotis Panagi Feb 08 '12 at 08:05
  • I explained it in a [previous answer](http://stackoverflow.com/questions/8870785/positional-index-in-ember-js-collections-iteration/) too and yes you are correct. There are some performance concerns with rendering very large lists using regular views (one of the reasons the #collection helper is being depreciated I believe). However, if you look at my solution I change the child view to a Metamorph view which just about eliminates the performance difference between #collection and #each helpers. Anyway, this is the way you probably should do this. I wouldn't be too concerned w/ that pull req. – Roy Daniels Feb 08 '12 at 13:10
  • I've created a version of the jsfiddle in this answer that is compatible and idiomatic for Ember 1.0. Feel free to update your answer with this link, Roy: http://jsfiddle.net/tL4Xt/ – Luke Melia Sep 03 '13 at 03:10
1

From subviews, you can attach data-attributes and access them in your controller.

For example, in your view, if you have:

{{#view Ember.Button target="App.controller" action="publish" data-publish=false}}Unpublish{{/view}}

Then in your controller,

App.controller = Ember.Object.extend({
  publish: function(v){
    var status = v['data-publish'];//your additional information is appended to the view.
  }
}
Rajat
  • 32,970
  • 17
  • 67
  • 87
0

An improvement to Veeb's answer, remember you have the jQuery event so you can do:

// template
<ul>
  {{#each applications}}
    <li>
      <a {{bindAttr href="url"}} param="abc" {{action "appClicked" on="click"}}>
         {{name}}
      </a>
    </li>
  {{/each}}
</ul>

// In your js code
appClicked: function (event) {
    var param = $(event.target).attr('param');
    ...
}
lacorbeille
  • 325
  • 1
  • 4
  • 8
-2

You can try to make the parameter an attribute of the <li> or <a> tag and then use jQuery to access it.

Maybe something like

// template
<ul>
  {{#each applications}}
    <li>
      <a {{bindAttr href="url"} param="abc"} 
      {{action "appClicked" on="click"}}>                
         {{name}}
      </a>
    </li>
  {{/each}}
</ul>

// In your js code
appClicked: function (event) {
    // You may have to play around and check which DOM element
    // has the the param attribute. From memory it is the parent.
    var param = this.$().parent().attr('param');
    ...
}
Veebs
  • 2,390
  • 13
  • 10