Route loading multiple models and controllers


#1

I’m building an Ember app in which the homepage displays 5 modules, each of which has its own M/V/C combo and links to a page to drill down into the data. However, this page does not have one central model that I could put into the route’s model callback. Instead, I think I have to load each module’s model in the setupController callback and assign them to their respective controllers. Basically, thinking it would look like:

setupController: function(_,_){
   // load the first model
   // find the first controller and set its content
  // load the second model
  // find the second controller and set its content
  // and so on for each module on the page
}

This doesn’t seem very modular, but it keeps model-loading in the route. Is there a way to do this that would allow me to encapsulate the model loading & controller setup for each module even though they don’t correspond to route states?


#2

This is a copy of one of my routes, maybe it’s workable for you too.

App.ProjectsEditRoute = Ember.Route.extend({
  redirect: function() {
    if (this.controllerFor('currentUser').get('isSignedIn') === false) {
      this.transitionTo('user.login');
    }
  },

  model: function(params) {
    var record = App.Project.find(params.project_id);
    var promise = Ember.Deferred.create();
    record.addObserver('isLoaded', function() {
      promise.resolve(record);
    });

    return promise;
  },

  setupController: function(controller, model) {
    this.controllerFor('activedataset.index').set('content', App.ActiveDataSet.findAll(model.id));
  }
});

#3

That’s basically what I’m doing right now:

setupController: function(controller, model){
  this.controllerFor('punctualitySummary').set('content', App.PunctualitySummary.find());
  this.controllerFor('reconnectSummary').set('content', App.ReconnectSummary.find());
  this.controllerFor('someOtherSummary').set('content', App.SomeOtherSummary.find());
  // .... and so on
}

Was wondering if there’s an acceptable way to componentize this a little better so that each component is responsible for loading its own data, interacting with its own controller, but still being loaded in the route. Would that still follow Ember’s “models are loaded in the routes” principle"?


#4

I’m not aware of a way that keeps everything together. One line per module to set it up seems pretty concise to me.


#5

How about:

App.PunctualitySummaryController = Ember.ArrayController.extend({
  content: function() {
    return App.PunctualitySummary.find();
  }.property()
});

App.ReconnectSummaryController = Ember.ArrayController.extend({
  content: function() {
    return App.ReconnectSummary.find();
  }.property()
});

Then you get modularity.


#6

Here is where {{render}} and {{control}} may be handy: http://darthdeus.github.com/blog/2013/02/10/render-control-partial-view/


#7

I like that, it looks much cleaner, am I losing anything by having the controller load the model instead of the route?


#8

Well… I guess it does make it a little harder to test that controller if you want to test it completely isolated and feed stuff into it’s content property.


#9

in your model method i think you can replace

var record = App.Project.find(params.project_id);

var promise = Ember.Deferred.create(); record.addObserver(‘isLoaded’, function() { promise.resolve(record); });

return promise;

with just

return App.Project.find(params.project_id);

as ember-data now returns a promise


#10

shhh … don’t tell … I’m not using ember-data.

A choice I made in the beginning and I’m asking myself every day whether it was the right one. It goes well without ember-data, but I like where ember-data is going.

Reason not to go with ember-data was the issues that are there with a rails has_many through relation.