Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save sfarthin/8871692 to your computer and use it in GitHub Desktop.
Save sfarthin/8871692 to your computer and use it in GitHub Desktop.
Coding Tidbits
# Learning Angular.js Dependency Injection with examples
The hardest part for me to grasp with Angular.js was Dependency Injection and distinctions between services/factories/providers. I have provided some simple examples that made these concepts more clear.
## Modules
Create a new module like this (second argument is for dependencies).
angular.module('myModule', []);
Refer to the module like this.
angular.module('myModule');
Define a main method to run after your app is bootstrapped.
angular.module('myModule').run(function() {
console.log("Here we go!!");
});
Bootstrap your angular application this way. The first argument is the DOM element, the second is an array of dependencies (described later).
angular.bootstrap(document, ['myModule']);
## Value Recipe
We can attach key/value pairs to this module.
angular.module('myModule').value('appName', 'MyCoolApp');
angular.module('myModule').value('appVersion', '0.0.1');
## Factory Recipe
A Factory is a lot like the "value recipe." The returned value of a factory is the value that will be provided. The value recipe is in fact shorthand for a factory recipe. The two examples below function the same.
angular.module('myModule').value('appName', 'MyCoolApp');
angular.module('myModule').factory('appName', function() {
return 'MyCoolApp';
});
One advantage of factories is that they can have dependencies. In this example the appName and appVersion recipes are invoked using Angular's inferred dependency injection described below.
angular.module('myModule').factory('informationFactory', function(appName, appVersion) {
return {
fullname: appName + " " + appVersion,
appname: appName,
version: appVersion
}
});
## Inferred Dependency Injection
To use these providers, one must use a injector. The invoke method will take the dependencies defined (such as appName) and inject it into a function. In the examples below, both code blocks log "MyCoolApp 0.0.1" because the dependencies are inferred by matching the argument name (appName, appVersion) to the dependency name. The two examples below function the same. More about the injector later.
angular.injector(['myModule']).invoke(function(appName, appVersion) {
console.log(appName + " " + appVersion);
});
angular.injector(['myModule']).invoke(function(appVersion, appName) {
console.log(appName + " " + appVersion);
});
## Service Recipe
With a service, you will be provided with an instance of a function. In other words "new FunctionYouPassedToService()"
angular.module('myModule').service('informationService', function(appName, appVersion) {
this.fullname = function() {
return appName + " " + appVersion;
};
});
## Controllers
One can create a controller like so. A controller is just a function. All the console logs will output "MyCoolApp 0.0.1".
angular.module('myModule').controller("myController", function(appName, appVersion, informationFactory, informationService) {
console.log(appName + " " + appVersion);
console.log(informationFactory.fullname);
console.log(informationService.fullname());
});
## Provider
This is the most verbose way to create a provider. Provider expects a $get method. The code block below demonstrates how we can make this provider act like a factory recipe.
angular.module('myModule').provider('informationProvider', function() {
this.$get = function(appName, appVersion) {
return {
fullname: appName + " " + appVersion,
appname: appName,
version: appVersion
}
};
});
The code block below demonstrates how we can make this provider act like a service recipe.
angular.module('myModule').provider('informationService', function() {
this.$get = function(appName, appVersion) {
return new function() {
this.fullname = function() {
return appName + " " + appVersion;
};
}
};
});
Remember: Service recipes, Factory recipes, and Value recipes are all just providers! The code block below represents the two ways to write the "appName" provider.
angular.module('myModule').provider("appName", function() {
this.$get = function($injector) {
return "MyCoolApp";
};
});
angular.module('myModule').value('appName', 'MyCoolApp');
## Configuration
Angular runs your application in two-phases: the configuration and run phases. Configurations happen before providers are initialized (Before the $get method is run). The run phase compiles the DOM and starts your app.
All these methods on the module can be chained.
angular.module('myModule', [])
.value("appName", "MyCoolApp")
.config(function() {
console.log("Cannot refer to appName here!");
})
.run(function(appName) {
console.log(appName);
});
angular.bootstrap(null, ['myModule']);
This verbose way of creating Providers allows for configurations to be done before the application starts. See below. "MyCoolApp" is logged to the console. Whenever you define a provider (lets say 'info'), one can inject that provider in the config function with the name (in this case "info") plus "Provider" (so "infoProvider").
angular.module('myModule', [])
.value('appName', 'MyCoolApp')
.value('appVersion', '0.0.1')
.provider('info', function() {
var hideVersion = false;
this.hideVersion = function() {
hideVersion = true;
}
this.$get = function(appName, appVersion) {
return new function() {
this.fullname = function() {
if(hideVersion) {
return appName;
} else {
return appName + " " + appVersion;
}
};
}
};
})
.config(function(infoProvider) {
infoProvider.hideVersion();
})
.run(function(info) {
console.log(info.fullname());
});
angular.bootstrap(null, ['myModule']);
In fact, providers (module.value, module.service, module.factory, module.provider) are actually shorthand configurations. One can inject the $provide service into the config function and define a provider that way. The two blocks below are the same. Under the hood, AngularJS is calling the the $provider.provide version for us either way.
angular.module('myModule')
.value("appName", "MyCoolApp");
angular.module('myModule')
.config(function($provide) {
$provide.provider("appName", function() {
this.$get = function() {
return "MyCoolApp";
}
});
});
## Injector
Anything given to $provide.provider can be injected using the injector. One can also get an instance by calling the "get" function or inject dependencies into functions with the invoke function.
console.log(angular.injector(["myModule"]).get('appName'));
or..
angular.injector(["myModule"]).invoke(function(appName) {
console.log(appName);
});
Any time you write a function that takes injected arguments (module.value, module.service, module.factory, module.provider, module.controller), you're seeing the injector at work. Remember, in the configuration phase ONLY providers can be injected.
angular.module('myModule').config(function(appName) {
// WON'T WORK -- appName is an *instance* of a service.
// Only providers for services can be injected in config blocks.
});
Whenever you define a provider (lets say 'foo'), that provider gets named 'fooProvider'. The code below prints "heyo"
angular.module("myModule",[])
.provider("foo", function() {
var foo;
this.setFoo = function(myFoo) { foo = myFoo; }
this.$get = function() { return foo; }
})
.config(function(fooProvider) {
fooProvider.setFoo("heyo");
})
.run(function(foo) {
console.log(foo);
});
angular.bootstrap(null, ['myModule']);
#### References and furthor reading
- [Understanding Dependency Injection](https://github.com/angular/angular.js/wiki/Understanding-Dependency-Injection)
- Angular.js Developer guide: [Providers](http://docs.angularjs.org/guide/providers)
- Angular.js Developer guide: [Registering Services](http://docs.angularjs.org/guide/dev_guide.services.creating_services)
- StackOverflow question "[Angular.js: service vs provider vs factory?](http://stackoverflow.com/questions/15666048/angular-js-service-vs-provider-vs-factory/15666049#15666049)"
- Gist [Difference between Service, Factory and Provider in AngularJS](https://gist.github.com/Mithrandir0x/3639232)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment