Computed property in Ember based on async data

2019-04-29 17:09发布

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: 'peep@example.com' },
    { id: 2, name: 'mypeep2', email: 'peep2@example.com' }

];

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?

1条回答
不美不萌又怎样
2楼-- · 2019-04-29 17:32

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..

查看更多
登录 后发表回答