In angular, controller is a javascript function (type/class) that is used as an instance of an angular scope (//www.VeVB.COM/article/91749.htm) that extends except root scope. When we create a new child scope through the scope.$new API (http://docs.angularjs.org/api/ng.$rootScope.Scope#$new), there is an option to pass it into the controller as a parameter of the method (I didn't understand it here, I only know that the first parameter of the controller is a newly created scope, with a binding parent scope). This will tell angular that the controller and the new scope need to be combined, and extend its behavior.
Controller can be used as:
1. Set the initial state of the scope object.
2. Add behavior to scope.
1. Setting up the initial state of a scope object
Usually, when we create an application, we need to set the initialization state for the angular scope.
angular applies a new scope object to the controller constructor (it is estimated to be passed in as a parameter), and establishes the initial scope state. This means that angular never creates controller type instances (i.e., does not use the new operator for controller's constructor). The constructor is always applied to existing scope objects.
We create the initial state of scope by creating the model attribute. For example:
function GreetingCtrl ($scope) {$scope.greeting = "Hola!";}
The controller "GreetingCtrl" creates a model called "greeting" that can be applied to the template.
2. Adding Behavior to a Scope Object
The behavior on an angular scope object is in the form of scope method attributes for templates and views. This behavior can modify the application's model.
As discussed in the guided model chapter (//www.VeVB.COM/article/91777.htm), any object (or primitive type) is assigned to the scope and becomes the model attribute. Any function attached to the scope is available for template views, and can be called via angular expression or via ng event handler directive (such as ngClick).
3. Using Controllers Correctly
Generally speaking, controllers should not try to do too much. It should only contain the business logic required for a single view (and it has not turned around and I have always thought that Controller is just a forwarding...).
To keep the controller simple, the common way is to extract the work that does not belong to the controller into the service, and use these services through dependency injection in the controller. These things will be discussed in the Dependency Injection Services chapter of the wizard.
Don't do the following in the Controller:
4. Associating Controllers with Angular Scope Objects
We can explicitly associate controller and scope objects through scope.$new, or implicitly use ngController directive (http://docs.angularjs.org/api/ng.directive:ngController) or $route service (http://docs.angularjs.org/api/ng.$route).
1. Example of Controller constructor and method
To illustrate how the controller component works in angular, let's create a small application using the following components:
The message in our template contains a binding to the spice model, which is set to "very" by default. Set the value of spice model to "chili" or "jalapeño" according to the button being clicked, and the message will be automatically updated by data binding.
<!DOCTYPE html><html ng-app><head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>spicy-controller</title> <meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible"> <style type="text/css"> .ng-cloak { display: none; } </style></head><body> <div ng-controller="SpicyCtrl"> <button ng-click="chiliSpicy()">Chili</button> <button ng-click="jalapenoSpicy('jalapeño')">Jalapeño</button> <p>The food is {{spice}} spicy!</p> </div> <script src="../angular-1.0.1.js" type="text/javascript"></script> <script type="text/javascript"> function SpicyCtrl($scope) { $scope.spice = "very"; $scope.chiliSpicy = function() { $scope.spice = "chili"; }; $scope.jalapenoSpicy = function(val) { this.spice = val; }; } </script></body></html>Things to note in the above example:
The controller method can take parameters, as shown in the following example:
<!DOCTYPE html><html ng-app><head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>controller-method-arments</title> <meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible"> <style type="text/css"> .ng-cloak { display: none; } </style></head><body> <div ng-controller="SpicyCtrl"> <input ng-model="customSpice" value="wasabi"/> <button ng-click="spicy(customSpice)">customSpice</button> <br/> <button ng-click="spicy('Chili')">Chili</button> <p>The food is {{spice}} spicy!</p> </div> <script src="../angular-1.0.1.js" type="text/javascript"></script> <script type="text/javascript"> function SpicyCtrl($scope) { $scope.spicy = "very"; $scope.spicy = function(spice) { $scope.spice = spice; }; } </script></body></html>Note that the SpicyCtrl controller now only defines a method with a parameter "spice" and called "spicy". template can refer to the controller method and pass a constant string or model value to it.
Controller inheritance in angular is based on scope inheritance. Let's take a look at the following example:
<!DOCTYPE html><html ng-app><head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>controller-inheritance</title> <meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible"> <style type="text/css"> .ng-cloak { display: none; } </style></head><body> <div ng-controller="MainCtrl"> <p>Good {{timeOfDay}}, {{name}}!</p> <div ng-controller="ChildCtrl"> <p>Good {{timeOfDay}}, {{name}}!</p> <p ng-controller="BabyCtrl">Good {{timeOfDay}}, {{name}}!</p> </div> </div> <script src="../angular-1.0.1.js" type="text/javascript"></script> <script type="text/javascript"> function MainCtrl($scope) { $scope.timeOfDay = 'Main time'; $scope.name = 'Main name'; } function ChildCtrl($scope) { $scope.name = 'Child name'; } function BabyCtrl($scope) { $scope.timeOfDay = 'Baby time'; $scope.name = 'Baby name'; } </script></body></html>Notice how we nest 3 ngController directly into the template. For our view, this template structure will cause 4 scopes to be created:
The inherited work is the same in controller and model. So in our previous example, all models can be rewritten through the controller.
Note: Standard prototype inheritance between two controllers does not work as we thought, because as we mentioned earlier, the controller is not initialized directly through angular, but instead applies that scope object. (controllers are not instantiated directly by angular, but rather are applied to the scope object, here is the same as before, I still don't understand.)
5. Testing Controller
While there are many ways to test controllers, one of the best conventions, as shown below, requires injection of $rootScope and $controller. (The test needs to be coordinated with jasmine.js)
<!DOCTYPE html><html ng-app><head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>controller-test</title> <meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible"> <link rel="stylesheet" href="../jasmine.css"> <style type="text/css"> .ng-cloak { display: none; } </style></head><body><script src="../angular-1.0.1.js" type="text/javascript"></script><script src="../angular-scenario-1.0.1.js" type="text/javascript"></script><script src="../jasmine.js" type="text/javascript"></script><script src="../angular-mocks-1.0.1.js" type="text/javascript"></script><script type="text/javascript"> function MyController($scope) { $scope.spices = [ {"name":"pasilla", "spiciness":"mild"}, {"name":"jalapeno", "spiceiness":"hot hot hot!"}, {"name":"habanero", "spiceness":"LAVA HOT!!"} ]; $scope.spice = "habanero"; } describe("MyController function", function () { describe("MyController", function () { var scope; beforeEach(inject(function ($rootScope, $controller) { scope = $rootScope.$new(); var ctrl = $controller(MyController, {$scope:scope}); })); it('should create "cpices" model with 3 spices', function () { expect(scope.spices.length).toBe(3); }); it('should set the default value of spice', function () { expect(scope.spice).toBe("habanero"); }); }); }); }); (function () { var jasmineEnv = jasmine.getEnv(); jasmineEnv.updateInterval = 1000; var trivialReporter = new jasmine.TrivialReporter(); jasmineEnv.addReporter(trivialReporter); jasmineEnv.specFilter = function (spec) { return trivialReporter.specFilter(spec); }; var currentWindowOnload = window.onload; window.onload = function () { if (currentWindowOnload) { currentWindowOnload(); } execJasmine(); }; function execJasmine() { jasmineEnv.execute(); } })();</script></body></html>If we need to test the nested controller, we need to create the same scope inheritance relationship in the test as in the DOM.
<!DOCTYPE html><html ng-app><head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>controller-test</title> <meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible"> <link rel="stylesheet" href="../jasmine.css"> <style type="text/css"> .ng-cloak { display: none; } </style></head><body><script src="../angular-1.0.1.js" type="text/javascript"></script><script src="../angular-scenario-1.0.1.js" type="text/javascript"></script><script src="../jasmine.js" type="text/javascript"></script><script src="../angular-mocks-1.0.1.js" type="text/javascript"></script><script type="text/javascript"> function MainCtrl($scope) { $scope.timeOfDay = 'Main time'; $scope.name = 'Main name'; } function ChildCtrl($scope) { $scope.name = 'Child name'; } function BabyCtrl($scope) { $scope.timeOfDay = 'Baby time'; $scope.name = 'Baby name'; } describe("MyController", function () { var mainScope,childScope,babyScope; beforeEach(inject(function ($rootScope, $controller) { mainScope = $rootScope.$new(); var mainCtrl = $controller(MainCtrl, {$scope:mainScope}); childScope = mainScope.$new(); var childCtrl = $controller(ChildCtrl, {$scope:childScope}); babyScope = childScope.$new(); var babyCtrl = $controller(BabyCtrl, {$scope:babyScope}); })); it('should have over and selected', function () { expect(mainScope.timeOfDay).toBe("Main time"); expect(mainScope.name).toBe("Main name"); expect(childScope.timeOfDay).toBe("Main time"); expect(childScope.name).toBe("Child name"); expect(babyScope.timeOfDay).toBe("Baby time"); expect(babyScope.name).toBe("Baby name"); }); }); (function () { var jasmineEnv = jasmine.getEnv(); jasmineEnv.updateInterval = 1000; var trivialReporter = new jasmine.TrivialReporter(); jasmineEnv.addReporter(trivialReporter); jasmineEnv.specFilter = function (spec) { return trivialReporter.specFilter(spec); }; var currentWindowOnload = window.onload; window.onload = function () { if (currentWindowOnload) { currentWindowOnload(); } execJasmine(); }; function execJasmine() { jasmineEnv.execute(); } })();</script></body></html>The above is the information about AngularJs Understanding the Controller Component. We will continue to add relevant information in the future. Thank you for your support!