berimbolo
berimbolo

Reputation: 3829

Angular Dependencies

Recently I have been learning Angular and getting on ok but there is something about the dependency injection that is still not clear to me.

Is there any reason to declare in my app.js file the other pieces of my application (services, controllers etc)?

It seems sometimes tutorials show this and sometimes they dont:

var calculatorApp = angular.module('calculatorApp', [
 'config',
 'ngRoute',  
 'calculatorControllers', //Do I need to declare these comnponents here?
 'calculatorServices'
]);

Equally do I need to declare ALL of the dependencies for the entire app in app.js? It seems I can also declare dependencies in any module (here ngResource is not declared in app.js just in services.js):

var calculatorServices = angular.module('calculatorServices', ['ngResource']);

If dependencies are only passed into the function and not first declared in an array does this mean the libraries are not preloaded, is there a benefit to doing this (calculatorService is not declared in app.js this time):

angular.module('myApp')
.controller('MainCtrl',  function ($scope, $location, calculatorService)

Finally is there any difference in the way these modules are declared? The first doesnt reference the main module, the second example does:

var calculatorServices = angular.module('calculatorServices', ['ngResource']);

angular.module('myApp')
.controller('MainCtrl',  function ($scope, $location, calculatorService)

Upvotes: 2

Views: 178

Answers (3)

CozyAzure
CozyAzure

Reputation: 8468

General rule of thumb: First parameter is the name, second parameter is the the list of dependencies.

AngularJs, in general, has a very standard way of doing things. All declarations of angular objects follow the same convention:

angular.Object(NameOfObject,ArrayOfDependencies[])

where NameOfObject must be a string and ArrayOfDependencies is an array that contains either string or callback functions.

For example, if you want to declare an angular module with a name called myApp that depends on another angular module with the name of ngAnimate, you do the following:

angular.module('myApp',['ngAnimate']);

If you can't visualize it, let's breakdown into parts. The following code is the same as the single line code above.

var myModuleName = "myApp"; //this is your app name
var myDependenciesArray= ['ngAnimate']; // this is a list of dependencies your app is gonna depend on

angular.module(myModuleName,myDependenciesArray); //voila, module declared!

To answer your question, you will need to know what type of dependencies can be injected to which angular objects. You must not confuse.

module can only take in injection of another module, and cannot take in service types (or provider types to be exact).The following syntax is correct:

angular.module('module1',[]);
angular.module('module2',['module1']) // this is okay, module 2 depends on module1.

If you however do this:

angular.module('module2',['$http']) //this is NOT okay

You will get [$injector:modulerr] thrown by angular because $http is a service name and not a module name.

For the same reason, if you are not declaring a module, then you cannot inject a module in that declaration but have to inject services instead. The following syntax is correct:

angular.module('demo')
   .controller('myCtrl',['$scope',function($scope){}] // this is okay, your controller depends on the $scope service

If you however do this:

angular.module('demo')
    .controller('myCtrl',['ngResource']) // this is NOT okay

You will get [$injector:unpr] thrown by angular, stating that no such provider is found.

Let's answer your questions:

Q: Do you need to inject all your dependencies?

A: Definitely, as long as you need them. But make sure you inject them at the correct position.

Q: If dependencies are only passed into the function and not first declared in an array does this mean the libraries are not preloaded, is there a benefit to doing this?

A: As I have mentioned, the second argument of an angular object can take in an array, and that array can take in callback functions. If you however provide only one callback function, you will have problems later when you minify your JavaScript code.

Your app will break when javascript is minified if you write like this:

angular.module('myApp')
   .controller('demoCtrl',function($scope){}); //will break

Your app will not break when javascript is minified if you write like this:

angular.module('myApp')
   .controller('demoCtrl',['$scope',function($scope){}]

Q: Is there any difference in the way these modules are declared?

A: No. Look at the following:

angular.module('myApp',[])
    .controller('demoCtrl',['$scope',function($scope){}]

The above code can be written like this, and they are the same:

var app = angular.module('myApp',[]);

app.controller('demoCtrl',['$scope',function($scope){}]

Upvotes: 1

Kazimieras
Kazimieras

Reputation: 615

If a module depends on services, controllers or directives of other modules they must be injected. However, you do not need to inject the dependencies of your dependencies, since Angular flattens the hierarchy for you.

In your example, the calculatorApp will have available to itself the four dependencies that you injected, as well as anything they depend on in their definitions. However, if your calculatorApp needs to use ngResource directly, it should still inject it in its own definition, because if you decide to rewrite your calculatorServices so that it doesn't need ngResource any more, it will probably not be desirable to rewrite calculatorApp as well.

Note, that in reality, dependencies are only instantiated once. Therefore, if calculatorApp and calculatorServices both inject someDependency, then one instance will be shared among these two modules.

Angular does not perform lazy-loading automatically, so there is little difference if you use the array notation or just pass the object to the function directly. The difference between these two syntaxes is that the array notation will not break during minification and uglification of your app. This is so, because strings are not altered during either of these processes, and variable names can be changed to make the file smaller.

Your last point demonstrates the creation of an angular module and the use of an angular module.

var calculatorServices = angular.module('calculatorServices', ['ngResource']);

This creates an empty calculator services module and injects ngResource into it.

angular.module('myApp')
    .controller('MainCtrl',  function ($scope, $location, calculatorService)

This adds the MainCtrl controller to the already existing myApp module. More about this can be found in the Angular docs.

Upvotes: 1

BetaRide
BetaRide

Reputation: 16834

First you only need to declare what you need. If you do not make direct use of a module in the module you are working with, there's no need to include it. Transient includes are handled by the DI injector for you.

Using the list-function format is highly recommended, but you will not notice any difference until you start to minifiy your code for production. If you just use the function angular takes the parameter names for DI. But once your javascript code is minified the parameternames are minified as well. Now the angular DI needs your string array to find the correct names.

Upvotes: 1

Related Questions