Ember.Application

public

An instance of Ember.Application is the starting point for every Ember application. It helps to instantiate, initialize and coordinate the many objects that make up your app.

Each Ember app has one and only one Ember.Application object. In fact, the very first thing you should do in your application is create the instance:

1
window.App = Ember.Application.create();

Typically, the application object is the only global variable. All other classes in your app should be properties on the Ember.Application instance, which highlights its first role: a global namespace.

For example, if you define a view class, it might look like this:

1
App.MyView = Ember.View.extend();

By default, calling Ember.Application.create() will automatically initialize your application by calling the Ember.Application.initialize() method. If you need to delay initialization, you can call your app's deferReadiness() method. When you are ready for your app to be initialized, call its advanceReadiness() method.

You can define a ready method on the Ember.Application instance, which will be run by Ember when the application is initialized.

Because Ember.Application inherits from Ember.Namespace, any classes you create will have useful string representations when calling toString(). See the Ember.Namespace documentation for more information.

While you can think of your Ember.Application as a container that holds the other classes in your application, there are several other responsibilities going on under-the-hood that you may want to understand.

Event Delegation

Ember uses a technique called event delegation. This allows the framework to set up a global, shared event listener instead of requiring each view to do it manually. For example, instead of each view registering its own mousedown listener on its associated element, Ember sets up a mousedown listener on the body.

If a mousedown event occurs, Ember will look at the target of the event and start walking up the DOM node tree, finding corresponding views and invoking their mouseDown method as it goes.

Ember.Application has a number of default events that it listens for, as well as a mapping from lowercase events to camel-cased view method names. For example, the keypress event causes the keyPress method on the view to be called, the dblclick event causes doubleClick to be called, and so on.

If there is a bubbling browser event that Ember does not listen for by default, you can specify custom events and their corresponding view method names by setting the application's customEvents property:

1
2
3
4
5
6
let App = Ember.Application.create({
  customEvents: {
    // add support for the paste event
    paste: 'paste'
  }
});

To prevent Ember from setting up a listener for a default event, specify the event name with a null value in the customEvents property:

1
2
3
4
5
6
7
let App = Ember.Application.create({
  customEvents: {
    // prevent listeners for mouseenter/mouseleave events
    mouseenter: null,
    mouseleave: null
  }
});

By default, the application sets up these event listeners on the document body. However, in cases where you are embedding an Ember application inside an existing page, you may want it to set up the listeners on an element inside the body.

For example, if only events inside a DOM element with the ID of ember-app should be delegated, set your application's rootElement property:

1
2
3
let App = Ember.Application.create({
  rootElement: '#ember-app'
});

The rootElement can be either a DOM element or a jQuery-compatible selector string. Note that views appended to the DOM outside the root element will not receive events. If you specify a custom root element, make sure you only append views inside it!

To learn more about the events Ember components use, see components/handling-events.

Initializers

Libraries on top of Ember can add initializers, like so:

1
2
3
4
5
6
7
Ember.Application.initializer({
  name: 'api-adapter',

  initialize: function(application) {
    application.register('api-adapter:main', ApiAdapter);
  }
});

Initializers provide an opportunity to access the internal registry, which organizes the different components of an Ember application. Additionally they provide a chance to access the instantiated application. Beyond being used for libraries, initializers are also a great way to organize dependency injection or setup in your own application.

Routing

In addition to creating your application's router, Ember.Application is also responsible for telling the router when to start routing. Transitions between routes can be logged with the LOG_TRANSITIONS flag, and more detailed intra-transition logging can be logged with the LOG_TRANSITIONS_INTERNAL flag:

1
2
3
4
let App = Ember.Application.create({
  LOG_TRANSITIONS: true, // basic logging of successful transitions
  LOG_TRANSITIONS_INTERNAL: true // detailed logging of all routing steps
});

By default, the router will begin trying to translate the current URL into application state once the browser emits the DOMContentReady event. If you need to defer routing, you can call the application's deferReadiness() method. Once routing can begin, call the advanceReadiness() method.

If there is any setup required before routing begins, you can implement a ready() method on your app that will be invoked immediately before routing begins.

Show:

Defines the properties that will be concatenated from the superclass (instead of overridden).

By default, when you extend an Ember class a property defined in the subclass overrides a property with the same name that is defined in the superclass. However, there are some cases where it is preferable to build up a property's value by combining the superclass' property value with the subclass' value. An example of this in use within Ember is the classNames property of Ember.View.

Here is some sample code showing the difference between a concatenated property and a normal one:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const Bar = Ember.Object.extend({
  // Configure which properties to concatenate
  concatenatedProperties: ['concatenatedProperty'],

  someNonConcatenatedProperty: ['bar'],
  concatenatedProperty: ['bar']
});

const FooBar = Bar.extend({
  someNonConcatenatedProperty: ['foo'],
  concatenatedProperty: ['foo']
});

let fooBar = FooBar.create();
fooBar.get('someNonConcatenatedProperty'); // ['foo']
fooBar.get('concatenatedProperty'); // ['bar', 'foo']

This behavior extends to object creation as well. Continuing the above example:

1
2
3
4
5
6
let fooBar = FooBar.create({
  someNonConcatenatedProperty: ['baz'],
  concatenatedProperty: ['baz']
})
fooBar.get('someNonConcatenatedProperty'); // ['baz']
fooBar.get('concatenatedProperty'); // ['bar', 'foo', 'baz']

Adding a single property that is not an array will just add it in the array:

1
2
3
4
let fooBar = FooBar.create({
  concatenatedProperty: 'baz'
})
view.get('concatenatedProperty'); // ['bar', 'foo', 'baz']

Using the concatenatedProperties property, we can tell Ember to mix the content of the properties.

In Ember.Component the classNames, classNameBindings and attributeBindings properties are concatenated.

This feature is available for you to use throughout the Ember object model, although typical app developers are likely to use it infrequently. Since it changes expectations about behavior of properties, you should properly document its usage in each individual concatenated property (to not mislead your users to think they can override the property in a subclass).

The DOM events for which the event dispatcher should listen.

By default, the application's Ember.EventDispatcher listens for a set of standard DOM events, such as mousedown and keyup, and delegates them to your application's Ember.View instances.

If you would like additional bubbling events to be delegated to your views, set your Ember.Application's customEvents property to a hash containing the DOM event name as the key and the corresponding view method name as the value. Setting an event to a value of null will prevent a default event listener from being added for that event.

To add new events to be listened to:

1
2
3
4
5
6
let App = Ember.Application.create({
  customEvents: {
    // add support for the paste event
    paste: 'paste'
  }
});

To prevent default events from being listened to:

1
2
3
4
5
6
7
let App = Ember.Application.create({
  customEvents: {
    // remove support for mouseenter / mouseleave events
    mouseenter: null,
    mouseleave: null
  }
});

The Ember.EventDispatcher responsible for delegating events to this application's views.

The event dispatcher is created by the application at initialization time and sets up event listeners on the DOM element described by the application's rootElement property.

See the documentation for Ember.EventDispatcher for more information.

Destroyed object property flag.

if this property is true the observers and bindings were already removed by the effect of calling the destroy() method.

Destruction scheduled flag. The destroy() method has been called.

The object stays intact until the end of the run loop at which point the isDestroyed flag is set.

Defines the properties that will be merged from the superclass (instead of overridden).

By default, when you extend an Ember class a property defined in the subclass overrides a property with the same name that is defined in the superclass. However, there are some cases where it is preferable to build up a property's value by merging the superclass property value with the subclass property's value. An example of this in use within Ember is the queryParams property of routes.

Here is some sample code showing the difference between a merged property and a normal one:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
const Bar = Ember.Object.extend({
  // Configure which properties are to be merged
  mergedProperties: ['mergedProperty'],

  someNonMergedProperty: {
    nonMerged: 'superclass value of nonMerged'
  },
  mergedProperty: {
    page: { replace: false },
    limit: { replace: true }
  }
});

const FooBar = Bar.extend({
  someNonMergedProperty: {
    completelyNonMerged: 'subclass value of nonMerged'
  },
  mergedProperty: {
    limit: { replace: false }
  }
});

let fooBar = FooBar.create();

fooBar.get('someNonMergedProperty');
// => { completelyNonMerged: 'subclass value of nonMerged' }
//
// Note the entire object, including the nonMerged property of
// the superclass object, has been replaced

fooBar.get('mergedProperty');
// => {
//   page: {replace: false},
//   limit: {replace: false}
// }
//
// Note the page remains from the superclass, and the
// `limit` property's value of `false` has been merged from
// the subclass.

This behavior is not available during object create calls. It is only available at extend time.

In Ember.Route the queryParams property is merged.

This feature is available for you to use throughout the Ember object model, although typical app developers are likely to use it infrequently. Since it changes expectations about behavior of properties, you should properly document its usage in each individual merged property (to not mislead your users to think they can override the property in a subclass).

Set this to provide an alternate class to Ember.DefaultResolver

The root DOM element of the Application. This can be specified as an element or a jQuery-compatible selector string.

This is the element that will be passed to the Application's, eventDispatcher, which sets up the listeners for event delegation. Every view in your application should be a child of the element you specify here.