0
votes

In Ember, when is a model accessible to the controller?

Below is a simple Ember application with a static model and a controller that attempts to access the model on init. You'll notice that on init the model title attribute is undefined. However, the setTimeout illustrates that the model is later accessible.

I was under the impression that Ember wouldn't initiate the controller until the model is ready. Is this correct? The Ember documentation (http://emberjs.com/guides/routing/specifying-a-routes-model/) indicates that models, even when loaded asynchronously are available when the controller is instantiated.

http://jsfiddle.net/vu263uwq/1/

App = Ember.Application.create({});

App.IndexRoute = Ember.Route.extend({
    model: function() {
        return posts[0];
    }
});

App.IndexController = Ember.ObjectController.extend({
    alertTitle: function() {
        var that = this;

        jQuery(".output").append("1. "+this.get("title")+"<br />"); //Returns "undefined"

        setTimeout(function() {
            jQuery(".output").append("2. "+that.get("title")); //Returns the correct title
        }, 1000);
    }.on("init")
});

var posts = [
    {
        id: 1,
        title: "First title",
        body: "Cras mattis consectetur purus sit amet fermentum. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Nullam quis risus eget urna mollis ornare vel eu leo. Cras justo odio, dapibus ac facilisis in, egestas eget quam."
    },{
        id: 2,
        title: "Second title",
        body: "Maecenas faucibus mollis interdum. Vestibulum id ligula porta felis euismod semper. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum."
    }
];
1

1 Answers

2
votes

Your impression is actually wrong. The setupController hook is where you set any properties on the controller, including the model. Actually, all setupController does by default is set the model on the controller. That's why if you override the hook and still need the model set, you must explicitly set the model or make a call to this._super(controller, model).

Notice the signature for setupController:

setupController: function(controller, model)

In order for this to work, the controller must already be instantiated by the point where Ember sets the model. Init is fired during the instantiation of the controller. So a call to init happens before a model is set`

As for the asynchronous fetching of models, if your model hook returns a promise, Ember will block until a fulfilled promise can be passed into the setupController function so that the model is assigned to the promise's fulfillment and not the promise itself. It lets you avoid calls like:

setupController: function(controller, model){  
   var self = this;
   makeAsyncCallReturningPromise().then(function(result){
       self._super(controller, result);
   }
}

which would basically accomplish the same thing