Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
563 views
in Technique[技术] by (71.8m points)

angularjs - Understanding Angular.js controller parameters

I'm just starting to learn Angular.js and I've been looking at the project.js in the "Wire up a Backend" example on the Angular home page.

I'm confused about the parameters in the controller functions:

function ListCtrl($scope, Projects) {
  ... 
}   

function CreateCtrl($scope, $location, $timeout, Projects) {
  ... 
}

function EditCtrl($scope, $location, $routeParams, angularFire, fbURL) {
   angularFire(fbURL + $routeParams.projectId, $scope, 'remote', {}).
   then(function() {
     ...
   });
}  

These controller functions are called in the routeProvider, but none of the parameters are given.

$routeProvider.
  when('/', {controller:ListCtrl, templateUrl:'list.html'}).
  when('/edit/:projectId', {controller:EditCtrl, templateUrl:'detail.html'}).
  when('/new', {controller:CreateCtrl, templateUrl:'detail.html'}).
  otherwise({redirectTo:'/'});
});

The only thing I could find so far that possibly explains what's going is "Injecting Services Into Controllers", which explains $location, $timeout, but not parameters method angularFire and fbURL.

My specific questions are:

  1. What can the controller parameters be?

  2. Where are the controller functions called with their parameters? Or the parameters are not called but are just stuff associated with the controller where the association occurs with lots of Angular.js magic (if so, can I see the source code on github)?

  3. Where is angularFire defined?

  4. How is the fbURL in the parameter linked to:

    angular.module('project', ['firebase']).
        value('fbURL', 'https://angularjs-projects.firebaseio.com/').
        factory ...
    
  5. Is there a place where I can see all the services, e.g. $location and $timeout, that Angular.js provides? (I tried to find the list but failed.)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
  • 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 or angularFire) 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 and angularFire 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 the name => 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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...