Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

item-specific actions in ember.js collection views

Tags:

ember.js

I'm just starting to play around with the ember.js library to see what it's all about. I want to display a table of data, and to the right of each row, have a delete button to delete that item from the table. I have no idea how to do this though.

Note, I also tried to create a child view (ItemView) and use it inline within the {{#each ...}}...{{/each}} section, but ember.js complains about expecting a view class instead of ItemView, even though ItemView is defined using Ember.View.create. I would also like to know why that isn't working. Even the sample code for using a child view in an #each block in the documentation doesn't work.

Even if I could declare a child view called ItemView to render each individual Item, I still wouldn't know how to get that particular view's removeItem action to know which item to remove from the itemsController collection. Is there a property of the View to get back the Item instance that the child view is bound to in a collection?

Here is the part of my view template that has the list:

{{#each App.itemsController}}
            <tr>
              <td>{{itemName}}</td>
              <td><a href="#" {{action "removeItem" on="click"}}>Delete</a></td>
            </tr>
{{/each}}

And here is my javascript:

window.App = Ember.Application.create();

window.App.Item = Ember.Object.extend({
    itemName: "defaultItemName"
});

window.App.itemsController = Ember.ArrayProxy.create({
    content: []
});

window.App.ListView = Ember.View.create({
    templateName: 'listView',

    removeItem: function (event) {
        // ??? How do I figure out what item
        // the user wanted to remove?
    }
});
like image 739
Jeremy Bell Avatar asked Feb 06 '12 22:02

Jeremy Bell


2 Answers

Yehuda's post Michael linked to demonstrates the correct approach, using a child ItemView inside the each. Not sure why that didn't work for you, you've removed that bit of code from your question unfortunately.

Some of the syntax in Yehuda's answer is slightly out of date so I've updated it and changed it to be a bit more like your question. You can check it out here: http://jsfiddle.net/wmarbut/67GQb/130/ (updated link to jsfiddle 1/21/12)

The thrust of it is

Handlebars

{{#each App.peopleController}}
    {{#view App.PersonView personBinding="this"}}
        <td>{{view.person.fullName}}</td>
        <td><button {{action removeItem target="view"}}>Delete</button>
    {{/view}}
{{/each}}

Javascript

App.PersonView = Ember.View.extend({
    tagName: 'tr',
    person: null,
    removeItem: function() {
        var person = this.get('person');
        App.peopleController.removeObject(person);
    }
});
like image 181
Tom Whatmore Avatar answered Sep 22 '22 12:09

Tom Whatmore


Thanks to Tom Whatmore fiddle I found answer to the same question.

After reading trek intro, instead of personBinding="this", I'd rather use {{action removeItem person}} to explicitly indicate object on which action should be performed.

<script type="text/x-handlebars">
<table>
    {{#each person in App.peopleController}}
        {{#view App.PersonView}}
            <td>{{person.fullName}}</td>
            <td><button {{action removeItem person}}>Delete</button>
        {{/view}}
    {{/each}}
</table>
</script>

In the view I'd use var person = evt.context; to get person object.

App = Ember.Application.create();

App.Person = Ember.Object.extend({
    fullName: function() {
        return this.get('firstName') + ' ' + this.get('lastName');
    }.property('firstName', 'lastName')
});

App.peopleController = Ember.ArrayProxy.create({
    content: [App.Person.create({ firstName: "Yehuda", lastName: "Katz" }),
    App.Person.create({ firstName: "Tom", lastName: "Dale" })]
});

App.PersonView = Ember.View.extend({
    tagName: 'tr',
    removeItem: function(evt) {
        var person = evt.context;
        App.peopleController.removeObject(person);
    }
});

You can play with this fiddle jsfiddle.net/67GQb/127

like image 40
penkovsky Avatar answered Sep 24 '22 12:09

penkovsky