Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Computed property in Ember based on async data

I'm trying to use a computed property based on the values from an async, hasMany model property, but cannot get it to display in my view.

MyApp.Foo = DS.Model.extend({

    title: DS.attr('string'),
    peeps: DS.hasMany('peep', { async: true });

});

MyApp.Peep = DS.Model.extend({

    name: DS.attr('string'),
    email: DS.attr('string')

}); 

MyApp.Foo.FIXTURES = [

    { id: 1, title: 'nice', peeps: [1,2] }

];

MyApp.Peep.FIXTURES = [

    { id: 1, name: 'mypeep', email: '[email protected]' },
    { id: 2, name: 'mypeep2', email: '[email protected]' }

];

MyApp.FooController = EmberObjectController.extend({

    showPeeps: function() {

        // This one works for this test data. 
        // return [{name: 'baz', email: 'bar'}];

        var peepList = this.get('content.peeps.[]').then(function(c) {

            // This one does not work, even for this test data.
            return {name: 'baz', email: 'bar'}];

        });

    }.property('content.peeps.[]');

});

In my view, something along the lines of:

{#each peep in controller.showPeeps}}{{peep.name}}{{/each}}

I can see all the data in the "then()" using console.log(), and as it indicates in the code comments, it works if I take the return out of the "then()" - but then the real data is empty because it is returned as async. If I try to make it non-async, I get

Uncaught TypeError: Cannot call method 'resolve' of undefined

I've tried many variants of the computed property code (using @each, using model.peeps - all of which correctly show the data in console.log(), but not in the view. In the view, it is always undefined unless I just return dummy data outside of the then() - which displays correctly)

What am I missing?

like image 502
J B Avatar asked Feb 28 '14 07:02

J B


People also ask

What is computed property in Ember?

What are Computed Properties? In a nutshell, computed properties let you declare functions as properties. You create one by defining a computed property as a function, which Ember will automatically call when you ask for the property. You can then use it the same way you would any normal, static property.

What is promise in ember?

A promise can be in one of three states: pending, fulfilled, or rejected. Promises that are fulfilled have a fulfillment value and are in the fulfilled state. Promises that are rejected have a rejection reason and are in the rejected state. A fulfillment value is never a thenable.

How do I use Ember data?

Ember Data is also designed to work with streaming servers, like those powered by WebSockets. You can open a socket to your server and push changes into Ember Data whenever they occur, giving your app a real-time user interface that is always up-to-date.


1 Answers

Don't treat the hasMany relationship as a promise, treat it as an array. That's the whole point of DS.PromiseArray. If you just want the users, don't even bother with the computed property, just use peeps in your template. But, if you need to convert the data somehow, use map.

showPeeps: function() {
    return this.get('peeps').map(function(peep) {
        return { name: peep.name, email: peep.email };
    });
}.property('peeps.@each')

Also, don't watch the [] property. That only updates when an item is added or removed from the array. Your array contents aren't changing, the contents of the contents are changing. You should watch the @each property instead. You also don't need to add [] to the end of the property name, and you don't need to prefix the property with content..

like image 135
GJK Avatar answered Oct 12 '22 01:10

GJK