Class Application
publicimport Application from '@ember/application';
An instance of Application
is the starting point for every Ember
application. It instantiates, initializes and coordinates the
objects that make up your app.
Each Ember app has one and only one Application
object. Although
Ember CLI creates this object implicitly, the Application
class
is defined in the app/app.js
. You can define a ready
method on the
Application
class, which will be run by Ember when the application is
initialized.
const App = Application.extend({
ready() {
// your code here
}
})
Because Application
ultimately 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 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. It is also important
to understand that an Application
is different from an ApplicationInstance
.
Refer to the Guides to understand the difference between these.
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.
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:
import Application from '@ember/application';
let App = Application.extend({
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:
import Application from '@ember/application';
let App = Application.extend({
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:
import Application from '@ember/application';
let App = Application.extend({
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
Initializers
To add behavior to the Application's boot process, you can define initializers in
the app/initializers
directory, or with ember generate initializer
using Ember CLI.
These files should export a named initialize
function which will receive the created application
object as its first argument.
export function initialize(application) {
// application.inject('route', 'foo', 'service:foo');
}
Application initializers can be used for a variety of reasons including:
- setting up external libraries
- injecting dependencies
- setting up event listeners in embedded apps
- deferring the boot process using the
deferReadiness
andadvanceReadiness
APIs.
Routing
In addition to creating your application's router, 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:
import Application from '@ember/application';
let App = 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.
concatenatedProperties public
Inherited from CoreObject packages/@ember/-internals/runtime/lib/system/core_object.js:428
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 Component
from @ember/component
.
Here is some sample code showing the difference between a concatenated property and a normal one:
import EmberObject from '@ember/object';
const Bar = EmberObject.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:
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:
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 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).
customEvents public
Defined in packages/@ember/application/lib/application.js:230
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 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:
import Application from '@ember/application';
let App = Application.extend({
customEvents: {
// add support for the paste event
paste: 'paste'
}
});
To prevent default events from being listened to:
import Application from '@ember/application';
let App = Application.extend({
customEvents: {
// remove support for mouseenter / mouseleave events
mouseenter: null,
mouseleave: null
}
});
eventDispatcher public
Defined in packages/@ember/application/lib/application.js:213
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.
isDestroyed public
Inherited from CoreObject packages/@ember/-internals/runtime/lib/system/core_object.js:577
Destroyed object property flag.
if this property is true
the observers and bindings were already
removed by the effect of calling the destroy()
method.
isDestroying public
Inherited from CoreObject packages/@ember/-internals/runtime/lib/system/core_object.js:595
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.
mergedProperties public
Inherited from CoreObject packages/@ember/-internals/runtime/lib/system/core_object.js:502
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:
import EmberObject from '@ember/object';
const Bar = EmberObject.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 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).
resolver public
Inherited from Engine packages/@ember/engine/index.js:429
Set this to provide an alternate class to DefaultResolver
rootElement public
Defined in packages/@ember/application/lib/application.js:188
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.