ThreeAccents
ThreeAccents

Reputation: 1882

changing the value of a model property emberjs

I'm trying to achive a toggle effect in Emberjs for some dynamically loaded data. Here is my adapter:

export default Ember.Object.extend({
    findAll: function(){
        return ajax('http://localhost:8000/api/v1/address-book/companies?includes=details')
            .then(function(response){
                return response.data.map(function(c){
                    return {
                        name: c.name,
                        website: c.details.data.website_url,
                        dev_website: c.details.data.development_website_url,
                        showDetails: false
                    };
                });
            });
    }
});

Here is the HTML handlebars:

{{#each m in model}}
    <tr>
        <td >
            <p style="cursor:pointer; color:#009688" {{ action 'displayDetails' m}}>{{m.name}}</p>
            {{#if m.showDetails}}
                <div class="">
                    <p><strong>Wesbite URL: </strong><a href="{{m.website}}">{{m.website}}</a></p>
                    <p><strong>Development Wesbite URL: </strong><a href="{{m.dev_website}}">{{m.dev_website}}</a></p>
                </div>
            {{/if}} 
        </td>
    </tr>
{{/each}}

and here is the controller:

export default Ember.ArrayController.extend({
    searchText: null,

    actions: {
        displayDetails: function(item){
            item.toggleProperty('showDetails')
        }
    }
});

I've also tried this in my controller:

export default Ember.ArrayController.extend({
    searchText: null,

    actions: {
        displayDetails: function(item){
            item.showDetails = true;
        }
    }
});

Which gives me the error I must use Ember.set to change the value of a property show then I did this:

export default Ember.ArrayController.extend({
    searchText: null,

    actions: {
        displayDetails: function(item){
            item.set('showDetails', true);
        }
    }
});

but this gives me the error item.set is not a function

Now I'm trying to switch the models showDetails property from true to false every time the company name (p tag) is clicked. I know what I did works with properties of the controller itself but how can I achieve this in my model object?

Upvotes: 1

Views: 2532

Answers (3)

Kuba Niechciał
Kuba Niechciał

Reputation: 974

In your adapter you have return as follows:

return response.data.map(function(c){
    return {
        name: c.name,
        website: c.details.data.website_url,
        dev_website: c.details.data.development_website_url,
        showDetails: false
    };
});

This means that you return array of plain JavaScript objects that does not have implemented #set method directly on them. Ember provides Ember.set that can be used both on Ember objects and JavaScript objects. What is more important, it is compliant with Ember's binding mechanism and probably this is the reason you got a warning.

To make your return objects more flexible in Ember environments consider wrapping them in Ember Object class. This way you would have straightly implemented #set, #get and #togglePropert method. As an example:

return response.data.map(function(c){
    return Ember.Object.create({
        name: c.name,
        website: c.details.data.website_url,
        dev_website: c.details.data.development_website_url,
        showDetails: false
    });
});

More info about Ember.set

More info about #togglePropert

Upvotes: 0

Kevin Boucher
Kevin Boucher

Reputation: 16705

Have you tried using Ember.set() as the message said?

Ember.set(m, 'showDetails', true);

http://emberjs.com/api/classes/Ember.html#method_set

Upvotes: 3

Christopher Milne
Christopher Milne

Reputation: 938

you need either:

1) an item controller (soon to be deprecated)
- looks into the 'needs' api for controllers
2) a component that you can set the property on.

You cannot set a model property for an individual object with an Array Controller.

If you had an identity map, you could do something like:

actions: {
  actionName: function() {
    this.store.find('modelName', someID).toggleProperty('propertyName')
  }
}

Upvotes: 0

Related Questions