What is better when creating a controller in AngularJs:
1-
angular.module('myApp')
.controller('MyController',['$scope','dependencies','myService', function($scope, dependencies, myService ) {
}]);
2-
angular.module('myApp')
.controller('MyController', function($scope, dependencies, myService ) {
});
Performance wise, the first is technically better, although that cost is probably negligible. If you do it the second way, angular literally calls the .toString() function on your controller function, and then parses the string to determine the dependencies. So you can either declare them yourself, or angular will parse your function as a string to determine them.
As a developer, I find it easier to read and write the second version. Just be aware that you have to change things to the first form if you plan on uglifying/minifying your code. Some tools will do this for you automatically (ngAnnotate, for example), so that you can write it the 2nd way, but have it deployed the first way.
With this method you have the advantage of function hoisting , function name for debugging , ability to mutate $inject;
also easier to reason about & debugging.
function myController(){
}
myController.$inject = ['$scope','dependencies','myService'];
angular.module('myApp' ,myController);
Related
I'm fairly new to Ionic and Angular and I've been reading that working with the dependency injection design pattern is recommended. Now I'm fairly new to DI as well so this is a double whammy for me.
If I have a controller for example:
app.controller('myController', ['$scope', '$localstorage', 'myService'
function($scope, $localstorage, myService) {
// Calls function in service
myService.concatStrings();
}
And I have a service:
app.service('myService', ['$localstorage', function ($localstorage) {
// Reads strings from local storage and concatenates them
function concatStrings () {
// ...
}
}
And say I can read the two strings from local storage like this:
var string1 = $localstorage.getStringOne();
var string2 = $localstorage.getStringTwo();
Where is the recommended place where I get these strings? Do I get them in my controller from $localstorage and pass them to the service, or do I not pass anything to the service and obtain the strings from $localstorage in the service?
I'm of the opinion that I actually read the strings from $localstorage in the controller and then pass it to the service. This way I can easily write unit tests for my services... But I'm not sure :\
Services are best used as reusable blocks of self contained code. I would think a concatStrings() method should be given strings to concatenate. If the method is to be concatStringsFromLocalStorage(), then perhaps it should be given some identifier to retrieve the strings from the storage, like perhaps a key or list of keys. The code which then uses localStorage (the service) can know about it, while the calling code (the controller) doesn't have to dirty itself with that knowledge.
The more you can easily reuse your code the more mileage you can get from it. Angular's DI, when used correctly, typically makes writing good tests with separate concerns quite easy.
you can read the strings from service's only it is recommended because we are going to inject the service as dependency to controller but not vice-versa and you can use $window.localStorage for storing the string values
What is the difference between these 2:
angular.module('myapp' ,[])
.controller('MyController', function($scope){...});
and
angular.module('myapp' ,[])
.controller('MyController, ['$scope', function($scope){...})];
This is quite complicated for those who new to AngularJS like me. The syntax is too different from Java and C.
Many thanks.
There's nothing difference between them. Both code works same way. But if you use first code and when you minify the code then it will confuse.
Look for an example:
.controller('MyController', function(a){...});//$scope is changed to a
And your code won't work as angularjs code uses $scope variable as it doesn't take first, second, third, and so on parameters.
So, the second code is safer than first as if when you minify the code, it still takes same variable i.e. $scope.
Look for an example:
.controller('MyController', ['$scope', function(a){...})];//a refers to $scope
So, the above code works fine when you minify the code as $scope is injected in place of a. So, if you pass multiple parameters then ordering matters in this example. Look at the following:
.controller('MyController', ['$scope','$timeout', function(s,t){...})]; s is injected as $scope and t is injected as $timeout. So if you change the order of them like ['$timeout','$scope', function(s,t){...})] then s is $timeout and t is $scope. So, ordering matters in this example but in your first example code ordering won't matter as name matters like $scope, $timeout.
There's also another way to inject variables if you use your first example code like below:
MyController.$inject = ['$scope'];
For multiple parameters,
MyController.$inject = ['$scope','$timeout'];
So, there are mainly three kinds of annotation:
Implicit Annotation - your first example code
$inject Property Annotation - the $inject method
Inline Array Annotation - your second example code
The second is minification safe.
Since Angular infers the controller's dependencies from the names of
arguments to the controller's constructor function, if you were to
minify the JavaScript code for PhoneListCtrl controller, all of its
function arguments would be minified as well, and the dependency
injector would not be able to identify services correctly.
Source
I usually declare one controller this way:
.controller('myController', function($scope,/*other dependecies go here*/){
// controller definition
};
However in some examples (including one from AngularJS's official documentation) I found something like:
angular.module('controllerExample', [])
.controller('SettingsController2', ['$scope', SettingsController2]);
function SettingsController2($scope) {
// controller definition
};
or simply (which is equivalent, I guess):
angular.module('controllerExample', [])
.controller('SettingsController2', ['$scope', function(){
// controller definition
}
]);
Now, I don't understand what is the actual difference between snippet 1) and snippets 2) and 3)
Also, I don't understand why sometimes the same dependency is both outside the function definition and in function parameters (like snippet 3) ) but outside is without $ and inside is with (sorry I can't find an example now. But I'm sure I had this situation).
Thank you in advance
The array syntax is to prevent angular from breaking when the code goes through a minifier. If you are not minifying your javascript, there really isn't a big difference other than you get to type more/less. Angular reads in these functions as a string and processes them. Some minifiers screw that up, so that weird syntax is the current solution.
#jwimmer's answer is correct but I want to offer one more possibility. You can clean up the syntax a bit and keep your code minification safe using $inject.
someCtrl.$inject = ['$scope', 'someDependency'];
function someCtrl($scope, someDependency) {
...
}
angular.module('someApp')
.controller('someCtrl', someCtrl);
I'm kind of a big angularJS newbie and I'd like some highlights concerning dependency injection.
I've done some research and here is what I understand so far.
I have 2 service files (using factories) :
-mogService.js
angular.module('anglober.services').factory('mogService', ['$http', function($http) {
var mogService = {};
//mogService code here
return mogService;
}]);
-modalService.js
angular.module('anglober.services').factory('modalService', ['$modal',
function ($modal) {
//modalService code here
}]);
One controller file :
-mogCtrl.js
angular.module('anglober.controllers').controller('mogCtrl', ['$scope', 'mogService','modalService', function ($scope, mogService, modalService) {
//code using mogService and modalService parameters
}]);
As I understand it, the dependency injection is done by passing my services as parameters of the function parameter in my controller declaration, the array of string is here so that after minification, angular still knows which variable is what.
However, the modalService variable is undefined when I test my code. The mogService is recognized alright though (only if I remove any call to the modalService variable).
What am I doing wrong ?
I've read things about using $inject, which is the better practice and why ?
I'm declaring modules in the app.js as follows :
angular.module('anglober.services', ['ui.bootstrap']);
angular.module('anglober.controllers', []);
var app = angular.module('anglober', ['anglober.controllers', 'anglober.services', 'anglober.directives']);
Is this good practice ? Declaring modules and their respective dependencies in one file then only use "getters" without the dependencies array parameter in module files ?
Thanks for your time.
Three steps that work for me (plunkr):
1. Be sure you define a module's dependencies only once.
Indeed, check that angular.module('anglober.services', [...]); is indeed called only once with the second argument.
At the same time, be sure to call these lines before the actual services/controllers /... definitons.
2. Wire every dependency
You should add 'anglober.services' dependency to 'anglober.controllers': the last requires modalService which requires $modal, it may help angular anyway.
3. Add possible missing lib requirements, in the right order
First jQuery, then angular, bootstrap and eventually bootstrap.ui and your modules.
Both of these work, but what is the actual difference between each implementation? I'm sure there is a logical reasoning behind each method, and I wish to be enlightened.
angular.module('app').controller('GeneralCtrl',
function($scope, $location, exampleService) {
$scope.variable = exampleService.getExampleVariable();
}
);
angular.module('app').controller('GeneralCtrl',
['$scope', '$location', 'exampleService', function($scope, $location, exampleService) {
$scope.variable = exampleService.getExampleVariable();
}]
);
What is the actual difference between these? Where would you use them differently? Why?
Answer: Turns out the latter is minification safe as minifiers rename parameter names, so dependencies cannot be inferred from their names, and so must be annotated.
This is what Angular calls "inline notation" for dependency injection (see http://docs.angularjs.org/guide/di for a whole lot of detail).
In the example you gave, the ng-controller directive is actually doing the work behind the scenes, of hooking up $scope, $location, and exampleService into the variables you're providing to that first function. It's doing this by default based on variable names (that is, it assumes that a variable called $scope is asking for the $scope dependency).
That said, when you minify your code, the variable names get chopped down also (ie, $scope might become a). When that happens, Angular now doesn't know what you meant by the variables anymore.
One option is to add
GeneralCtl.$inject('$scope', '$location', 'exampleService')
Another is to provide those strings like you did in the second example. This makes sure that even if the variable names get changed around, you're telling Angular what they were supposed to represent, and it knows how to set them properly.