Here is the list of AngularJS’s core types of objects and components:
- Value
- Factory
- Service
- Provider
- Constant
AngularJS dependency injection mechanism is useful for injecting these core types into each other. Now, we will discuss how to define and inject these components into each other.
Value
A value component in AngularJS is a simple object. Value can be a number, string or JavaScript object. You can inject the values into factories, services or controllers.
A value must belong to an AngularJS module. Below are three examples that adds value to an AngularJS module:
var demoModule = angular.module("demoModule ", []);
demoModule.value("numberTypeValue", 777);
demoModule.value("stringTypeValue", "xyz");
demoModule.value("objectTypeValue", { value1 : 123, value2 : "pqr"} );
AngularJs’s value() function on the module is used for defining values. The first parameter of value() function is the name of value, and second parameter of value() function is value itself. Factories, services and controllers refer these values by their name.
Injecting a Value
Injection of a value into an AngularJS controller function is done by adding a parameter controller function. Parameter name should be same as the name of first parameter passed to the value() function when the value is defined. Below is an example:
var demoModule = angular.module("demoModule ", []);
demoModule.value("numberTypeValue ", 777);
demoModule.controller("MyController", function($scope, numberTypeValue) {
console.log(numberTypeValue);
});
Factory
Factory function creates values. The factory creates the value on demand when a service, controller etc. needs a value injected from a factory. Once the value is created, it is reused for all services, controllers etc. which needs it injected. You can also inject values into a factory and use these injected values when creating the object.
Below is an example that defines a factory on a module, and a controller which gets the factory created value injected:
var demoModule = angular.module("demoModule ", []);
demoModule.factory("demoFactory", function() {
return "value";
});
demoModule.controller("MyController", function($scope, demoFactory) {
console.log(demoFactory);
});
Injecting and defining factory is very similar to defining and injecting a value object. When you inject factory into service or controller it is not the actual factory function that is injected, but the value produced by the factory function.
Injecting Values into a Factory
Values can be injected into a factory same as value is injected into a controller. Here is an example:
var demoModule = angular.module("demoModule ", []);
demoModule.value("stringTypeValue ", “xyz”);
demoModule.factory("demoFactory", function(stringTypeValue) {
return "value: " + stringTypeValue;
});
In this example, the value ‘stringTypeValue’ is injected into factory ‘demoFactory’ and value ‘stringTypeValue’ is used to create the object using the factory function.
Service
AngularJS services are singleton object which contains a set of functions. The functions contain logic which is necessary for services to carry out its work.
Services in AngularJS are created using the service() function on a AngularJs’s module. Below is an example:
var demoModule = angular.module("demoModule ", []);
demoModule.service("demoService",[function(){
this.doAction = function() {
console.log("Completed");
}
}]);
You can inject a service into a controller like this:
var demoModule = angular.module("demoModule ", []);
demoModule.service("demoService",[function(){
this.doAction = function() {
console.log("Completed");
}
}]);
demoModule.controller("DemoController",[‘$scope’,’demoService’ ,function($scope, demoService) {
demoService.doAction();
}]);
Injecting Values into a Service
You can inject values into a AngularJS’s service, same as you inject values into controllers, Below is an example:
var demoModule = angular.module("demoModule ", []);
demoModule.value ("myValue" , "987654");
demoModule.service("demoService",[‘myValue’,function(myValue){
this.doAction = function() {
console.log("Injected value is: " + myValue;
}
}]);
Note that parameter injected into service should be named the same as value registered on the module. Thus, you can inject the value into the service when it is created.
Dependencies between Modules
AngularJS modules can be dependent on each other. One AngularJS module can use the factories, services and values of another AngularJS module. When one AngularJs module want to use values, factories and services of another module then a module needs to declare a dependency on the module which contains values, factories and services it wants to use. Here is an example:
var myModule = angular.module("myModule ", []);
myModule.value ("myValue" , "4567");
var otherModule = angular.module("otherModule ", [‘myModule’]);
otherModule.controller("myController", function($scope, myValue) {
});
In above example ‘otherModule’ depends on ‘myModule’.
Here the second module (otherModule) is dependent on the first module (myModule).
‘otherModule’ lists the name of the first module (myModule) in the second parameter (inside the array) passed to the angular.module() function. This tells AngularJS that all values, factories and services defined inside the myModule should be available inside the otherModule module too.
Minification Safe Dependency Injection in AngularJS
When you minify JavaScript code, JavaScript minifier replaces names of local variables and parameters with shorter names. But, AngularJS uses parameter names of controller functions, factories, services and providers to decide what to inject into their factory functions. If parameter names are changed, AngularJS cannot able inject the correct objects.
To make minification safe dependency injection in AngularJS, you need to provide object’s name to inject as strings. These strings are wrapped inan array along with the function that needs the values injected. Below is an AngularJS minification safe dependency injection example:
var demoApp = angular.module("demoApp", ['myServices']);
demoApp.controller("myController", ['$scope', function(param1) {
param1.myvar = "the value";
}]);
This example injects the $scope object into the param1 parameter of the controller function.
In above example the controller function is registered with AngularJS module ‘demoApp’. Here we are passing an array to the angular.Controller function instead of passing the controller function directly. This array contains the name of the value to inject into the last value in this array. If you are injecting more than one value, the names of value are listed in the beginning of the array and in the sequence they are to be injected into the function. Below is a minification safe multi value example:
var demoApp = angular.module("demoApp", ['myservice']);
demoApp.controller("MyController", ['$scope', '$http', function(param1,param2) {
param1.myvar = "the value";
param2.get("/myservice.json");
}]);
This example injects the $scope object into the param1 parameter, and the $http service into the param2 parameter of the controller function.
Now, it no longer matters what parameter names of controller function are. AngularJS will use strings in the beginning of array to determine what to inject into the controller function.
The same mechanism of dependency injection can be used for services, factories and providers to achieve minification safe dependency injection.