Angularjs Understanding the Controller Component_angularjs

Source: Internet
Author: User
Tags inheritance naming convention uppercase letter angular scope


In angular, controller is a JavaScript function (Type/class) that is used to extend angular scope except for root scope (http://www.jb51.net/article/ 91749.htm) is an example. When we or angular create a new child scope through the Scope. $new API (http://docs.angularjs.org/api/ng. $rootScope. scope# $new), An option is passed into the controller as a parameter to the method (not seen here, except that the first parameter of the controller is a newly created scope with binding parent scope). This will tell angular of the need for joint controller and new scope, and to extend its behavior.



Controller can be used as:



1. Set the initial state of the scope object.
2. Increase the behavior into scope.



One, Setting up the initial state of a scope object (set the initial status of the scope object)



Typically, 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 (presumably as a parameter) and establishes the initial scope state. This means that angular never creates an instance of the controller type (that is, the new operator is not used for the constructor of controller). The constructor is always applied to the existing scope object.



We established the initial state of scope by creating the Model property. For example:



function GreetingCtrl ($scope) {$scope. Greeting = "hola!";}



"GreetingCtrl" This controller created a "greeting", can be applied to the template version of the model.



Ii. adding Behavior to a Scope object (Increase behavior in scope object)



The behavior on the angular scope object is in the form of a scope method property for use by templates and views. This behavior (behavior) can modify the application model.



As discussed in the model chapter of the guideline (http://www.jb51.net/article/91777.htm), any object (or original type) is assigned to scope and becomes the model property. Any function attached to the scope is available for template view, either through angular expression calls, or through the NG event handler directive invocation (such as Ngclick).



Three, Using controllers correctly



Generally speaking, controller should not try to do too many things. It should contain only the business logic needed for a single view (and a little bit of a bend, always thinking that controller is a forwarding ...). )。



The common way to keep controller simple is to extract the work that is not part of controller into the service, and use the service in controller through dependency injection. These things are discussed in the Dependency Injection Services section of the wizard.



Do not do the following things in controller:


    1. Any type of DOM operation-Controller should contain only business logic. Dom operations, the performance logic of the application, are notoriously difficult to test. Putting any representation logic into controller greatly affects the testability of the application logic. Angular data binding (http://docs.angularjs.org/guide/dev_guide.templates.databinding) provided to automate (update) the DOM. If we want to perform our custom DOM operation, we can extract the representation logic into directive (http://www.jb51.net/article/91739.htm).
    2. Input formatting (input format)-Replaces with angular form controls (http://www.jb51.net/article/91744.htm).
    3. Output filtering (formatted filter)-use angular filters instead.
    4. Perform stateless or stateful, controller shared code-using angular services instead.
    5. Instantiate or manage the life cycle of other components, such as creating a service instance.


Iv. associating controllers with angular Scope Objects



We can explicitly pass the scope. $NEW Associate controller and scope objects, or implicitly through Ngcontroller directive (http://docs.angularjs.org/api/ Ng.directive:ngController) or $route service (http://docs.angularjs.org/api/ng. $route).



1. Example of Controller constructors and methods



To illustrate how the controller component works in angular, let's use the following components to create a small application:


    1. A template with two buttons and a simple message.
    2. A model consisting of a string attribute named "Spice".
    3. A controller with two methods that set the Spice property.


The message in our template contains a binding to spice model, and the default setting is "very". Depending on the clicked button, the value of the spice model is set to "chili" or "jalapeño", and the message is automatically updated by the 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 class="ng-cloak">
 <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>


The things to note in the example above:


    1. Ngcontroller directive is used as our template (implicitly) to create scope, which is called the Spicyctrl parameter.
    2. Spicyctrl is just an ordinary JavaScript function. As a (random) naming convention, the name begins with an uppercase letter and ends with "Ctrl" or "Controller."
    3. Assigning values to a property can create or update $scope model.
    4. The Controller method can be created by directly assigning to the $scope implementation. (Chilispicy method)
    5. The two methods of controller are available in template (valid in the element that contains the Ng-controller property and in its child elements).
    6. Note: Previous versions of Angular (1.0RC ago) allow us to use this instead of the $scope definition $scope method, but this is no longer applicable. In a method defined on scope, this is equivalent to $scope (angular this to scope), but not in our controller constructor.
    7. Note: Previous versions of Angular (1.0RC ago) automatically add controller prototype methods to scope, but not now. All methods need to be manually added to scope. (The impression that there was a guide before, useful this.) Not yet updated-_-!)


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-aruments</title>
 <meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
 <style type="text/css">
 .ng-cloak {
  display: none;
 }
 </style>
</head>
<body class="ng-cloak">
 <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.spice = "very";
  $scope.spicy = function(spice) {
  $scope.spice = spice;
  };
 }
 </script>
</body>
</html>


Notice that Spicyctrl controller now only defines a method that has a parameter "spice", called "spicy". Template can refer to the controller method and pass it a constant string or model value.



Controller inheritance is inherited in angular based on scope. 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 class="ng-cloak">
 <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时间';
  $scope.name = 'Main名称';
 }

 function ChildCtrl($scope) {
  $scope.name = 'Child名称';
 }

 function BabyCtrl($scope) {
  $scope.timeOfDay = 'Baby时间';
  $scope.name = 'Baby名称';
 }
 </script>
</body>
</html>


Notice how we nested 3 ngcontroller directive into the stencil. For our view, this template structure will cause 4 scopes to be created:


    1. Root scope.
    2. Mainctrl scope, containing TimeOfDay and name model.
    3. Childctrl scope, covering the Mainctrl scope of the name model, inherited the TimeOfDay model.
    4. The Babyctrl scope covers the timeofday of Mainctrl scope and the name of Childctrl scope.


Inherited work, in controller and model is the same. So in our previous example, all model can be rewritten through controller.



Note: Standard prototype inheritance between two controller does not work as we would like to, because as we mentioned earlier, controller is not directly initialized through angular, but instead, the scope object is apply. (controllers are not instantiated directly by angular, but rather are applied to the scope object, as before, I still don't understand.) )



V. Testing Controller



Although there are many ways to test controller, one of the best conventions, as shown below, needs to be injected into $rootscope and $controller. (The test needs to cooperate 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 class="ng-cloak">

<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="../jasmine-html.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 nested controller, we need to create the same scope inheritance relationship in 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 class="ng-cloak">

<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="../jasmine-html.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时间';
 $scope.name = 'Main名称';
 }

 function ChildCtrl($scope) {
 $scope.name = 'Child名称';
 }

 function BabyCtrl($scope) {
 $scope.timeOfDay = 'Baby时间';
 $scope.name = 'Baby名称';
 }

 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时间");
  expect(mainScope.name).toBe("Main名称");
  expect(childScope.timeOfDay).toBe("Main时间");
  expect(childScope.name).toBe("Child名称");
  expect(babyScope.timeOfDay).toBe("Baby时间");
  expect(babyScope.name).toBe("Baby名称");
 });
 });

 (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 about ANGULARJS understanding the Controller component data collation, follow-up continue to supplement the relevant information, thank you for your support!


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.