EmberJS - Dependency Injection



It is a process of supplying dependencies of one object to another and used by an Ember application to declare and instantiate the objects and dependency classes between them. The Ember.Application and Ember.ApplicationInstance classes play an important role in the Ember's Dependency Injection implementation.

The Ember.Application class declares and configures the objects and used as 'registry' for dependency declarations, where as the Ember.ApplicationInstance class acts as 'owner' for instantiated objects. However, the Ember.Application class acts as primary registry for an application and each Ember.ApplicationInstance class serves as registry.

Factory Registrations

A factory specifies an application part such as route, template, etc. and is registered with a particular key. For instance, index template is defined with template:index and application route is defined with route:application.

Registration key includes two parts; one is factory type and second is the name of factory and both segments split by colon(:). For instance, you can initialize the application by registering the Logger factory with the logger:main key.

application.register('mylog:logmsg', MyLogger);

Factory Injections

The factory can be injected, once it is registered. For instance, consider the following code −

application.inject('route', 'mylog', 'mylog:logmsg');

All the type of route factories will be represented with the mylog property and the value for this property will come from the mylog:logmsg factory. You can also inject on specific factory by using the full key as −

application.inject('route:index', 'mylog', 'mylog:logmsg');

Here only mylog property will get injected on the index route.

Factory Instance Lookups

You can use the factory instance's lookup method on an application instance to get an instantiated factory from the running application. It uses a string to determine the factory and returns an object.

For instance, you can call the lookup method on an application instance to fetch an instantiated factory as shown below −

applicationInstance.lookup('factory-type:factory-name');

Example

The example given below shows the use of factory registration, injection and instance lookups in the Ember application. Create a component with the name dependency-inject which will get define under app/components/. Open the dependency-inject.js file and add the following code −

import Ember from 'ember';
var inject = Ember.inject;

export default Ember.Component.extend ({
   //load the service in the file /app/services/message.js
   message: inject.service(),
   message: 'Click the above button to change text!!!',
   actions: {
      pressMe: function () {
         
         //after clicking button, above message will get display at console
         var testText = this.get('start').thisistest();
         this.set('message', testText);
         //after clicking button, it will enter in the component page
         this.get('logger').log('Entered in component!');
      },
      
      scheduleTasks: function () {
         //scheduling work on specific queues like "sync" or "afterRender" 
         Ember.run.schedule('afterRender', this, function () {
            console.log("CUSTOM: I'm in afterRender");
            Ember.run.schedule('sync', this, function () {
               console.log("CUSTOM: I'm back in sync");
            });
         });
      }
   }
});

Now open the component template file app/templates/components/dependency-inject.hbs and enter the following code −

<button {{action "pressMe"}}>Click Here</button><br> 
<h2>{{message}}</h2>
<button {{action "scheduleTasks"}}>Schedule Tasks!</button>
{{yield}}

Open the application.hbs file and add the following line of code −

{{dependency-inject}}
{{outlet}}

We need to create an initializer to configure an application by using the following command −

ember generate initializer init

Open the init.js file which is created under app/initializers/ and add the following code −

export function initialize(app) {
   //injecting the 'start' property into the component
   app.inject('component', 'start', 'service:message');
}

export default {
   //initializer name
   name: 'init',
   initialize: initialize
};

Create a service which can be made available in the different parts of the application. Use the following command to create the service −

ember generate service message

Now open the message.js service file which is created under app/services/ with the following code −

import Ember from 'ember';

export default Ember.Service.extend ({
   isAuthenticated: true,
   //after clicking the button, 'thisistest()' triggers and display the below text
   thisistest: function () {
      return "Welcome to Tutorialspoint!!!";
   }
});

Next, create an initializer which configures the application as it boots. The initializer can be created by using the following command −

ember generate initializer logger

Open the logger.js initializer file which is created under app/initializers/ with the following code −

import Ember from 'ember';

//it is an application initializer that run as your application boots
export function initialize(application) {
   var Logger = Ember.Object.extend({
      log(m) {
         console.log(m);
      }
   });
   
   //Registration key includes two parts; one is factory type and second is 
      name of factory
   application.register('logger:main', Logger);
   
   //Once a factory is registered, it can be injected by using 'application.inject' 
      along with 'logger' property 
   //and value for this property will come from 'logger:main'factory
   application.inject('component:dependency-inject', 'logger', 'logger:main');
}

export default {
   name: 'logger',
   initialize: initialize
};

Next, create the instance initializer for an application by using the following command −

ember generate instance-initializer logger

Open the logger.js initializer file which is created under app/instance-initializers/ with the following code −

//Application instance initializers run as an application instance is loaded
export function initialize(applicationInstance) {
   var logger = applicationInstance.lookup('logger:main');
   
   //it indicates that instance has booted at console log
   logger.log('Hello...This message is from an instance-initializer!');
}

export default {
   //it is an instance initializer name
   name: 'logger',
   initialize: initialize
};

Output

Run the ember server; you will receive the following output −

Ember.js Dependency Injection

Next, click on the Click Here button, it will display the text from the service page as shown in the screenshot below −

Ember.js Dependency Injection

Now go to console and check for log messages which are displayed from the instance initializers after the text is displayed as in the abve screenshot −

Ember.js Dependency Injection

Next, click on the schedule Tasks button to schedule the work on queues that are processed in the priority order −

Ember.js Dependency Injection
emberjs_application_concerns.htm
Advertisements