Last active
August 29, 2015 13:56
-
-
Save sfarthin/8871692 to your computer and use it in GitHub Desktop.
Coding Tidbits
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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