Can someone explain if this from the docs?


#1

In the docs at:

http://emberjs.com/guides/concepts/naming-conventions/

We have:

App.ApplicationRoute = Ember.Route.extend({
  setupController: function(controller) {
    // `controller` is the instance of ApplicationController
    controller.set('title', "Hello world!");
  }
});

App.ApplicationController = Ember.Controller.extend({
  appName: 'My First Example'
});

This is basic - but I want to understand.

I understand that ember creates objects in memory - so I would expect App.ApplicationController to be created when the application is booted/created. And then

    controller.set('title', "Hello world!");

would set a property on that controller called title to the value 'Hello world!".

What I don’t understand is that the next line

App.ApplicationController = Ember.Controller.extend({
  appName: 'My First Example'
});

seems to create the App.ApplicationController (and set the property appName.

Is it the case that ember runs all object creation first?

Is the App.ApplicationController object ‘always’ created on application start up? Would it show in the Chrome Ember inspector extension?

Why was this code not

    App.ApplicationController.set('appName', "My First Example");

or

    App.ApplicationController.appName = "My First Example";

#2

When Ember.Thing.extend({}) is called, this is basically a constructor. .set isn’t required because the object is not yet instantiated. Later when the application is actually being ‘booted’ these various objects are create (or left to be lazy created when needed).

Hope this helps.


#3

Sorry - but I’m still puzzled.

If the App.ApplicationController is created in memory automatically when the Ember application is booted up why are we calling:

App.ApplicationController = Ember.Controller.extend({

to create the object (again).


#4

If the App.ApplicationController is created in memory automatically when the Ember application is booted up

It’s created automatically if it’s not already present when it boots up.

App.ApplicationController = Ember.Controller.extend({

You are not creating it again here but defining the classes functionality. You “extend” from Ember.Controller because you want it to act as a controller class. When Ember looks for an instance of ApplicationController then it will use your App.ApplicationController class to create it.

If you haven’t defined your own App.ApplicationController then Ember will create an instance of Ember.Controller (or Object/ArrayController) for you automatically - this cuts down the amount of boilerplate code you need to write but it does increase the apparent “magic” when learning.


#5

You don’t have to call it. Ember does it automatically. If you don’t define extend it, it will be created anyway, just without any overridden properties.

The ApplicationController becomes a property in the registry and is insantiated for you by calling create on the constructor.


#6

OK - thanks.

I didn’t realise that .extend is an ember addition.

http://emberjs.com/api/classes/Ember.CoreObject.html#method_extend

Just looking further.

Trying to figure out out when classes/subclasses are created and when actual instances are created.


#7

To answer with my own findings…

Say we have an app with nothing in it apart from the js script src files and

var App = Ember.Application.create();

According to Ember inspector under routes the ApplicationRoute is created and assigned a generated ApplicationController controller and ApplicationRoute and this route contains a single index route with URL of #/

According to the view tree nothing else exists.

If I then add in a template:

  <script type="text/x-handlebars" data-template-name"application">
    <h1>Ordr</h1>
  </script>

I then get a template in the view tree with a generated controller of Ember.Controller and a view of Ember.View

Say I then add in to app.js

App.ApplicationRoute = Ember.Route.extend({
    setupController: function(controller) {
    // `controller` is the instance of ApplicationController                       
        controller.set('appName', "Hello world!");
    }
});

App.ApplicationController = Ember.Controller.extend({
    appName: 'My First Example'
});

The application listed in the view tree has the controller ApplicationController - but appName is set to ‘Hello world!’

So my (probably JS) question has changed to -

So, my question now is - how come this comes first:

App.ApplicationRoute = Ember.Route.extend({
    setupController: function(controller) {
    // `controller` is the instance of ApplicationController                       
        controller.set('appName', "Hello world!");
    }
});

but has precedence over

App.ApplicationController = Ember.Controller.extend({
    appName: 'My First Example'
});

which is written after?


#8

Routes are higher up the hierarchy than Controllers. The ‘My First Example’ get overwritten with ‘Hello world’ after it’s instantiated. So appName is ‘My First Example’, but for a very short period of time, before being set to ‘Hello world!’


#9

You’re asking the wrong question. It’s not really a matter of hierarchy. It’s just that route holds a singleton controller instance for the entire app lifespan, and offers you a way to make changes to it so that the controller can be updated as the user navigates different pages. Here is a code complete example:

App.Router.map(function() {
    this.resource('users', { path: '/users/:username' });
});

App.UserRoute = Ember.Route.extend({
    model: function(urlParams) {
          return urlParams;
    },
    setupController: function(controller, model) {
        controller.get('name') == "instance default name"; //only the first time this is called!

        //called once each time the route is entered or the route's model changes
        controller.set('name', model.username);

        controller.constructor.prototype.name == "class default name";
    }
});

App.UserController = Ember.Object.extend({
    init: function() {
         this.set('name', "instance default name");
    },
    name: "class default name"
});

With this example you will get the desirable, standard behavior: a single backing object for your templates that will have it’s propert[y/ies] updated as the user navigates around.

The distinction between class and instance properties is more a normal OO javascript difference. In plain OO javascript class values, stored on the prototype, are never deleted but only masked by instance values. You might delete an instance property using the delete keyword, and you would see the prototype’s definition instead. With ember’s get/set there is no delete operation, so the distinction bears no relevance unless you’re considering performance. “class default name” will appear in memory only once, whereas “instance default name” would end up in memory many times if you, created many instances of UserController.