Best way to sort array by async relationship attribute?


#1

Lets say I have three models:

  • A: contains items property which is a hasMany relationship to B

  • B: contains details property which is a belongsTo relationship to an instance of C

  • C: contains property name which I want to be my sort key

    // app/models/a.js import DS from ‘ember-data’; const { hasMany } = DS;

    export default DS.Model.extend({ items: hasMany(‘b’, { async: true }) });

.

// app/models/b.js
import DS from 'ember-data';
const { belongsTo } = DS;

export default DS.Model.extend({
  details: belongsTo('c', { async: true })
});

.

// app/models/c.js
import DS from 'ember-data';
const { attr } = DS;

export default DS.Model.extend({
  name: attr('string')
});

Question: What is the best way to sort the items array in model A by details.name property?


#2

Check out the Ember Data references API outlined in this blog post: http://emberjs.com/blog/2016/05/03/ember-data-2-5-released.html

It allows you to interact with relationships synchronously.


#3

Thank you, Skaterdav, for that link. Shows interesting things I seem to have missed. Anyways, could you explain how that helps me with my problem?

Sure, having all data pre-fetched would work, but I don’t need any new API for that. I could just specify the relationships as { async: false } and fetch all required records before. If that is the only way to achive this, okay, but I thought it might work with the async way, too?


#4

So if I understand correctly, you want to sort items by details.name but all the data might not be in the store so you would need to fetch it if it isn’t already loaded?


#5

Yes. Well, I think I’m looking for a way to get notified when all async relationships have been loaded so that I can sort.

Maybe there is a good way to grab all the Promises and put it into an Ember.RSVP.all?

Something like… (not tested)

// app/models/a.js
import DS from 'ember-data';
const { hasMany } = DS;

export default DS.Model.extend({
  items: hasMany('b', { async: true }),
  setSortedItems: Ember.observer('items', function() {
    let relationshipPromises = this.get('items').map(item => item.get('details.name')); // item.get('details.name')) should return a Promise, right?
    Ember.RSVP.Promise.all(relationshipPromises).then(function() {
       // at this point, shouldn't it be possible to sort the array?
    })
  })
});

#6

Ya, something like that could work.