Hello All,
In last two post, we discussed about DI, various types available in AngularJS and some insights around it. It is going to be another post on DI itself but here we’ll talk about annotations.I would recommend to go through last two posts before going further.
- Dependency Injection (DI) in {{AngularJS}} – Part 16
- Dependency Injection (DI) in {{AngularJS}} Contd.– Part 17
Note – This post is a part of series of posts on AngularJS and it is 18th one. Click here to view all the post. Apart from that you can also use the navigation links for next and previous post in each post at the bottom to check all.
In our previous posts, we have seen that services are passed as a parameter with same name which was used defining like Circle and this is crucial because Angular internally locate the services using the name itself. So if the name does not match then dependencies won’t be resolved. As the name should be same so minifying the script would break the application which cannot be accepted. So let’s first see that the number of options provided by AngularJS.
So as we have seen, we have three ways to inject the dependencies. Lets discuss one by one
Implicit parameter
This is the way that we have used in our last two post, where we use the same name in parameter which we defined while creating. This is most vulnerable as discussed in the first paragraph as well in case we minify our script files. As we used in one of our example
var myangularapp = angular.module('myangularapp', []); myangularapp.service('Circle', function () { var pi = 3.14; this.Area = function (r) { return pi * r * r; } this.Circuimference = function (r) { return 2 * pi * r; } }); myangularapp.controller("mycontroller", function ($scope, Circle) { $scope.AreaofCircle = Circle.Area(5); $scope.CircuimferenceOfCircle = Circle.Circuimference(5); })
Here we are using Circle as parameter as Circle was used while creating the service. As discussed in the previous post, while resolving the dependencies injector comes into picture and as here there there are two parameters passed $scope and Circle services, injector uses the names and creates the instance using the provider.
This is simplest way to resolve the dependencies but it breaks if minifiers or obfuscators are used as we know these changes the name of parameters based on there algorithm which later does not match with the providers. But if you are sure that minifiers/obfuscators are not going to be used on production then you can happily use this.
$inject property
This is another way to pass the dependency which does not break in case of minification. In this case even if the name of the parameters gets changed still all the dependencies correctly get resolved. Let’s see how
var myangularapp = angular.module('myangularapp', []); myangularapp.service('Circle', function () { var pi = 3.14; this.Area = function (r) { return pi * r * r; } this.Circuimference = function (r) { return 2 * pi * r; } }); var mycontroller = function ($scope, customCircle) { $scope.AreaofCircle = customCircle.Area(5); $scope.CircuimferenceOfCircle = customCircle.Circuimference(5); }; mycontroller.$inject = ['$scope', 'Circle']; myangularapp.controller('mycontroller', mycontroller);
Here we can see that we annotate $inject property of the function, here we provide the right name of the services in an array. In controller function we have chosen an arbitrary name (customCircle here) but code still runs fine.
As provider names are assigned as values in the array, no minifier or obfuscator changes the values so it works perfectly fine.
Using Inline Array
This approach is preferable way to resolve the dependencies in the Angular. It is just another way of using array values to provide the service names to appropriate functions but much simpler than above. Let’s take the similar example as above and implement it using inline array
var myangularapp = angular.module('myangularapp', []); myangularapp.service('Circle', function () { var pi = 3.14; this.Area = function (r) { return pi * r * r; } this.Circuimference = function (r) { return 2 * pi * r; } }); myangularapp.controller("mycontroller", ['$scope','Circle', function ($scope, customCircle) { $scope.AreaofCircle = customCircle.Area(5); $scope.CircuimferenceOfCircle = customCircle.Circuimference(5); }]);
Here we can see that we create an inline array then we pass all the dependencies in the array and at end we pass the function where the dependencies need to be passed. Here function takes the input parameter which gets resolved to the dependencies based on the values passed in the inline array. We can pass all the services in similar way. This trick requires less code and easily understandable than the previous one.
Here the key thing to be noted that it orderof the values in the array and parameter name is very important if that gets changed then the right dependencies be initialized to right parameters. Same holds true for second option as well.
Important Note – As it is a common practice to use minifier while putting the code at production and somehow the dependency got resolved via first way then it could be disastrous for your application. In case of big application, where many developers working on same application everybody may use its own choice which could lead issues at production. So to avoid this, Angular provide us a way which makes sure that no body uses implicit injection and that is called Strict Dependency Injection. For this we need add one directive ng-strict-di where we provide ng-app as
<div ng-app=”myangularapp” ng-strict-di>
Hope you all have enjoyed this post including two earlier posts on dependency injection in AngularJS. Do share your feedback.
Cheers
Brij
Pingback: Dependency Injection (DI) in {{AngularJS}} Contd.– Part 17 | Code Wala
Reblogged this on Dinesh Ram Kali..
Pingback: Getting started with Unit Testing in {{AngularJS}} – Part 19 | Code Wala