The dependency injection pattern is used to declare and instantiate classes of objects and handle dependencies between them. In Ember, we can take objects or services and inject them into routes, controllers, or components.
In this recipe, we'll take a logger object and inject it into our controllers using dependency injection.
moment
library and create a new initializer
:$ bower install moment –save $ ember g initializer application
This will install the Bower Moment.js library. We'll use this for our custom logger.
// ember-cli-build.js /*jshint node:true*/ /* global require, module */ var EmberApp = require('ember-cli/lib/broccoli/ember-app'); module.exports = function(defaults) { var app = new EmberApp(defaults, { // Add options here }); app.import('bower_components/moment/min/moment.min.js'); return app.toTree(); };
The app.import
statement adds the moment
library to the application.
application.js
file in the initializers
folder, add a new logger:// app/initializers/application.js /* global moment */ import Ember from 'ember'; export function initialize( application) { let MyLogger = Ember.Object.extend({ log(info){ let time = moment().format(); Ember.Logger.debug(`(${time}):`,info); } }); application.register('myLogger:zzz', MyLogger); application.inject('controller','myLogger','myLogger:zzz'); } export default { name: 'application', initialize };
This creates a new logger called myLogger
. It uses the built-in Ember.Logger
and adds a timestamp to it using the moment
library that was installed earlier.
Let's take a look at this in more detail:
application.register('myLogger:zzz', MyLogger);
The application.register
method registers a new factory. The first argument is the registration key. The registration key is always two parts separated by a colon :
. The first part is the type of factory and the second part is the name of the factory. The type of factory can be a template, component
, controller
, or service
, or you can create your own. In this example, I called it myLogger
. The second argument is the object you want to register, MyLogger
:
application.inject('controller','myLogger','myLogger:zzz');
This application inject makes the new myLogger:zzz
factory available in all controllers. The value of myLogger
comes from the myLogger:zzz
factory.
myLogger
debugger:// app/controllers/application.js import Ember from 'ember'; export default Ember.Controller.extend({ actions: { press(){ this.myLogger.log('Hello World!'); } });
When a new press
action occurs, it logs to the console, Hello World
.
action
to the application template:<h2 id="title">Welcome to Ember</h2> {{outlet}} <button {{action 'press'}}>Button</button>
ember server
and you'll see the following screen:Press Button and you'll see something as follows in the console:
Each time you click the button, it logs a debug statement to the console.
Dependency injection occurs when we take objects and inject them into other objects during instantiation. Ember can do this with the application.inject
method. To accomplish this in Ember, we must create factories. Factories are simply objects that return other objects.
Ember registers these factories in Ember.Application
. Ember.Application
acts as a registry of sorts that holds different factories. After being registered, they can be injected into other parts of the Ember application such as components or controllers.