Understanding Angular.js controller parameters
Solution 1:
-
What can the controller parameters be?
The controller parameters are dependencies, which are injected by AngularJS injector service. They can be anything. But they are usually the services that will be used inside the controller.
-
Where are the controller functions called with their parameters?
Controllers, as well as directives, filters, services and so many other things in AngularJS are functions. But the framework manages a lot of when and how these functions are called.
What you call stuff associated has a name: dependency, as mentioned above. What you call magic is AngularJS dependency injection mechanism in action.
When these functions (controllers and others) are called by the injector, it reads the parameters names (for example:
$scope
or$http
orangularFire
) and searches for a registered service with that name, which is then provided as the parameter when the function is called.It is simple. You have several ways to instruct about your "dependencies" (parameters managed by the injector) to the injector.
When you simply declare your function as
function myCtrl($scope) {}
, the injector will be able to find the$scope
service from the parameter name. But if you minify the JavaScript code, the injector will not be able to find the service anymore, because the parameter name will be modified to a smaller string, like "a" or "x". To avoid this problem, it is possible to specify the service name to be injected using the array notation. In this case, you would declare your function like this:myCtrl = ['$scope', function($scope) {}]
You will see a lot of array notation usage in AngularJS world. Now you start to understand it. You could even inject
$scope
andangularFire
and use them with other names in your function (changing the name is not recommended - this example here comes for learning purposes):['$scope', 'angularFire', function(skop, af) {}]
- this way, inside the function you can use $scope as "skop" and angularFire as "af". The order of the services in the array matches the order of the parameters.
Another example:
var myController = ['$scope', '$resource', '$timeout',
function($scope, $resource, $timeout) {
// this controller uses $scope, $resource and $timeout
// the parameters are the dependencies to be injected
// by AngularJS dependency injection mechanism
}
];
-
Where is angularFire defined?
In the firebase module.
As you already know now, the injector will inject anything as long as it has that "thing" name registered and available on its records. If there is a "service" with that name, he is able to provide it.
How, then, is built this
name => stuff
list which the injector uses?Module is the answer. A module is little more than a list of
name => stuff
. It is in a module where you register services, factories, filters, directives, and more.Look carefully at the Module methods at the official documentation... almost all of them receive as parameters: name and some "stuff" (where "stuff" is almost always a function, defining either a controller, or a factory, or a directive). It is all this "stuff" that will become injectable through their specified name.
AngularJS services like "$timeout", "$http" and others are available by default because the ng module is already loaded by the framework.
For additional services, you need to load/require the module. That's what you do with ngRouter, firebase, etc... By loading the module, its registered stuff are available for injection in your module/app.
Let's see a step-by-step example:
// An empty module:
var module = angular.module('myModule', []);
// Now, adding an "injectable" constant:
module.constant('niceStuff', { blip: 'blop', blup: 307 });
// We could add a service:
module.service('entityManager', ['$http', function($http){ }]);
// and so on... if I wanted to use "$resource" instead of "$http"
// in the entityManager service above...
// ...I would need to require the ngResource when creating the module above,
// like this: var module = angular.module('myModule', ['ngResource']);
// because "$resource" is not available by default
// NOW, anywhere else, since the code above already ran
// I can use those NAMES as dependencies like this:
// We are creating another module now:
var koolModule = angular.module('km', ['myModule']);
// Note that I am requiring the previous module through its registered name
// Now, anything I've declared in that module
// - just like "ng" (by default) and "firebase" (required) does -
// is available for "injection"!!!
koolModule.controller('koolController',
['niceStuff', 'entityManager', function(niceStuff, entityManager) {
console.log(niceStuff.blip); // 'blop'
console.log(niceStuff.blup + 10); // 317
}]
);
This is how firebase stuff, like angularFire, becomes available! What have we done? First, we created the "myModule", and registered NAMED stuff to it. Later, we required the "myModule" for our "koolModule" - and those NAMES were already available in the injector name => stuff
list.
-
How is the fbURL in the parameter linked
As we've just seen, most module methods are merely registering things - giving names to things so they can be injected and/or used through these names later.
When
module.value('fbURL', 'https://angularjs-projects.firebaseio.com/')
is called, fbURL (and the specified value) is registered into thename => stuff
list... in this case, the name is "fbURL", and the value/stuff is the URL string - but it could be anything! -
Is there a place where I can see all the services, e.g. $location and $timeout, that Angular.js provides?
Yes, the API reference: http://docs.angularjs.org/api/
Pay attention at how the left-side navigation is organized... by modules! First, the ng module, with tons of directives, services, filters, etc. Then, below, the other modules (ngRoute, ngResource, ngMock, and so on), each one containing their own services, fitlers or directives...
Thanks for the opportunity of sharing these thoughts. I enjoyed writing them.
Solution 2:
First off great job choosing this framework. It is the best. Those variables you see with the $ sign are injected and part of the standard framework. These services will make your life so much easier. The best way to think of controllers are they are script sheets. They help separate the code. Do not think of them as methods. Those variables you see such as $timeout & $scope are services that will come in handy as you need certain things done. All documentation for the framework is at http://docs.angularjs.org/api/ but I would start with this tutorial http://docs.angularjs.org/tutorial/ .
The angularfire is not part of the framework. It is another service that leverages the framework in order to create a powerful real time distributed network. When you load the angularfirejs it comes with the service which is then injected as the parameter you see.
To answer your second question, the parameters you pass could be anything so long as you make a corresponding service. Please refer to this to make your own parameter for controllers : http://docs.angularjs.org/guide/dev_guide.services.creating_services
fbURL is just a variable that you can create and the code you placed in your question is simply the instruction on how to make it.
Angularjs is not the type of framework you can learn by looking at what it offers. Simply because it offers it all. Everything you could possibly bring to make a great app. Instead you should focus on asking google how to solve your problem with angular.
Also check out videos on youtube. You will find some great ones.
Solution 3:
As per toxaq comment, here is the comments as an answer
-
What can the controller parameters be?
It can mostly be services, factories, values, constants, etc... that you have defined somewhere before OR using resolve on a route definition.
-
Where are the controller functions called with their parameters?
Here is the proper way to define a controller:
angular.module('project').controller('EditCtrl', [ '$scope', '$location', '$routeParams', 'angularFire', 'fbURL', function($scope, $location, $routeParams, angularFire, fbURL) { ... } ]);
That way, you first set the name of the services that you want to inject, and then you give those services a different name if you would like. In fact, this is mandatory if you want to minimize your angular code later (since the minimization will rename the variables, angular needs to still be able to find the services names).
-
Where is angularFire defined?
When you defined your project module, you also included the firebase module dependancy. Inside of the firebase module, there must be an angularFire service like the previous fbURL.
-
How is the fbURL in the parameter linked to
Like you seem to understand, the parameters of the controller are being injected by angular from the definition of the controller. Angular will look in all the registered services and try to find a match with the specified name of the parameter and inject the according service!
-
Is there a place where I can see all the services, e.g. $location and $timeout, that Angular.js provides?
For the list of all built in services, filters, directives included in Angular, have a look at the API: http://docs.angularjs.org/api