Full or partial load async fields of model in route, is it possible?


#1

Hello, my friends! I have model with many nested async relationships, example:

//model1 export default DS.Model.extend({ fields1: DS.hasMany('model2',{async:true}) }); //model2 export default DS.Model.extend({ fields2: DS.hasMany('model3',{async:true}) });

When i use it in template - all is fine, promise resolve automatically. But i need to change model in controller (groups, calculate and etc.) and i had to manually handle all promises, as:

[code]import Ember from ‘ember’; export default Ember.Controller.extend({ results:function(){ var all = []; this.model.get(‘fields1’).then((fields1)=>{ fields1.forEach((field1)=>{ field1.get(‘fields2’).then((field2)=>{ all.concat(field2); //Group and other operation withs all here this.set(‘all’, all); }); }); });

}.observes(‘model’).on(‘init’) });[/code] And question, can i set what fields (or full) i need automatically resolve before use model in controller? Example:

//ROUTE import Ember from 'ember'; export default Ember.Route.extend({ model:function(){ //LOAD ALL NESTED ASYNC FIELD !!! return this.store.find('model1',{}); }, setupController:function(controller, model){ controller.set('model', model); } }); //controller export default Ember.Controller.extend({ results:function(){ var all = []; this.model.get('fields1').forEach((field1)=>{ all.concat(field1.get('fields2)); }); //Group and other operation withs `all` here this.set('all', all); }.observes('model').on('init') });


#2

I wrote method findSync for DS.store class:

Signature: findSync(modelName, params, fieldsScheme)

Example, calling: this.store.findSync('model1',{},{'model1':['fields1'],'model2':['fields2']});

Source:

export function initialize( container, application ) {
  container.lookup('store:main').reopen({
    findSync:function(model, params, fields){
      var getClassNameByModel = function(model){
        var className = model.__ember_meta__.proto.constructor.toString();
        var i = 0;
        if (className == 'DS.AdapterPopulatedRecordArray'){
            var row;
            model.forEach(function(row_){
              if (i++){
                return;
              }
              row = row_;
            });
            return getClassNameByModel(row);
        }
        var x = className.indexOf(':');
        className = className.substr(x+1, className.length - x - 2);

        return className;
      };
      var loadModelSyncRec = function(model, fields){
        var className = getClassNameByModel(model).replace(/\//gi,'.');

        if (!fields[className]){
          return Ember.RSVP.Promise.resolve(model);
        }
        return new Ember.RSVP.Promise((resolve, reject)=>{
          var promises = [];
          if (model.__ember_meta__.proto.constructor.toString() == 'DS.AdapterPopulatedRecordArray'){
              model.forEach((row)=>{
                promises.push(loadModelSyncRec(row, fields));
              });
          }else{
            fields[className].forEach((fieldName)=>{
              promises.push(model.get(fieldName).then((row)=>{
                return loadModelSyncRec(row, fields);
              }));
            });
          }
          Ember.RSVP.all(promises).then(()=>resolve(model));
        });
      }


      return this.find(model, params).then((rows)=>{
        return loadModelSyncRec(rows, fields);
      });
    }
  });
}
export default {
  name: 'store-sync',
  after: 'store',
  initialize: initialize
};