文章目录
  1. 1. Hello World
  2. 2. AngularJS Convenience Function
  3. 3. AngularJS Modules
  4. 4. Controller
    1. 4.1. More Directives
    2. 4.2. ng-repeat
  5. 5. Karma
    1. 5.1. Unit Test for Controller

Hello World

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html>
  <body ng-app>
    <input type="text"
           ng-model="name"
           placeholder="Enter your name">
    <h1>Hello <span ng-bind="name"></span></h1>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.js">
    </script>
  </body>
</html>

AngularJS Convenience Function

  • angular.forEach Iterator over objects and arrays, to help you write code in a functional manner.
  • angular.fromJson and angular.toJson Convenience methods to convert from a string to a JSON object and back from a JSON object to a string.
  • angular.copy Performs a deep copy of a given object and returns the newly created copy.
  • angular.equals Determines if two objects, regular expressions, arrays, or values are equal. Does deep comparison in the case of objects or arrays.
  • angular.isObject, angular.isArray, and angular.isFunction Convenience methods to quickly check if a given variable is an object, array, or function.
  • angular.isString, angular.isNumber, and angular.isDate Convenience methods to check if a given variable is a string, number, or date object.

AngularJS Modules

Modules are AngularJS’s way of packaging relevant code under a single name.

The module can also depend on other modules as dependencies, which are defined when the module is instantiated.

Module to load as the main entry point for the application by passing the module name to the ng-app directive.

1
2
3
4
5
// define a module
angular.module('notesApp', ['notesApp.ui', 'thirdCompany.fusioncharts']);

// get a module
angular.module('notesApp', []);

This example defines a module (note the empty array as the second argument), and then lets AngularJS bootstrap the module through the ng-app directive.

1
2
3
4
5
6
7
8
9
10
<!-- File: chapter2/module-example.html -->
<html ng-app="notesApp">
  <head><title>Hello AngularJS</title></head>
  <body>
    Hello 2nd time AngularJS
    <script type="text/javascript">
      angular.module('notesApp', []);
    </script>
  </body>
</html>

Controller

An AngularJS controller is almost always directly linked to a view or HTML. It acts as the gateway between our model, which is the data that drives our application, and the view, which is what the user sees and interacts with.

  • Fetching the right data from the server for the current UI
  • Deciding which parts of that data to show to the user
  • Presentation logic, such as how to display elements, which parts of the UI to show, how to style them, etc.
  • User interactions, such as what happens when a user clicks something or how a text input should be validated

The array holds all the dependencies for the controller as string variables, and the last argument in the array is the actual controller function. In this case, because we have no dependencies, the function is the only argument in the array.

We also introduce a new directive, ng-controller. This is used to tell AngularJS to go instantiate an instance of the controller with the given name, and attach it to the DOM element.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<body ng-controller="MainCtrl as ctrl">
   AngularJS.
  <button ng-click="ctrl.changeMessage()">
    Change Message
  </button>
  <div ng-repeat="note in ctrl.notes">
    <span class="label"> </span>
    <span class="status" ng-bind="note.done"></span>
  </div>

  <script type="text/javascript">
    angular.module('notesApp', [])
    .controller('MainCtrl', [function() {
      var self = this;
      self.message= 'Hello ';
      self.changeMessage = function() {
        self.message = 'Goodbye';
      };
      self.notes = [
        {id: 1, label: 'First Note', done: false},
        {id: 2, label: 'Second Note', done: false},
        {id: 3, label: 'Done Note', done: true},
        {id: 4, label: 'Last Note', done: false}
      ];

  }]);
  </script>
</body>

Use class="ng-cloak" to hide \{\{\}\} in angularjs when bootstrap.

1
2
3
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],.ng-cloak, .x-ng-cloak {
  display: none !important;
}

Each time it hits an ng-controller or an ng-repeat directive, it creates what we call a scope in AngularJS. A scope is the context for that element. The scope dictates what each DOM element has access to in terms of functions, variables, and the like.

Also note that while the ng-repeat instances each get their own scope, they still have access to the parent scope.

More Directives

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<style>
.done { background-color: green;}
.pending {background-color: red;}
</style>

<body ng-controller="MainCtrl as ctrl">
  <div ng-repeat="note in ctrl.notes"
       ng-class="ctrl.getNoteClass(note.done)">
    <span class="label"> </span>
    <span class="assignee"
          ng-show="note.assignee"
          ng-bind="note.assignee">
    </span>
  </div>
</body>

<script type="text/javascript">
angular.module('notesApp', []).controller('MainCtrl', [
  function() {
    var self = this;
    self.notes = [
      {label: 'First Note', done: false, assignee: 'Shyam'},
      {label: 'Second Note', done: false},
      {label: 'Done Note', done: true},
      {label: 'Last Note', done: false, assignee: 'Brad'}
    ];
    self.getNoteClass = function(status) {
      return {
        done: status,
        pending: !status
      };
  };
}]);

</script>

AngularJS treats true, nonempty strings, nonzero numbers, and nonnull JS objects as truthy.

The ng-class directive can take strings or objects as values. If it is a string, it simply applies the CSS classes directly. If it is an object, AngularJS takes a look at each key of the object, and depending on whether the value for that key is true or false, applies or removes the CSS class.

ng-repeat

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<div ng-repeat="(author, note) in ctrl.notes">
  <span class="label"> </span>
  <span class="author" ng-bind="author"></span>
</div>
<script type="text/javascript">
  angular.module('notesApp', [])
    .controller('MainCtrl', [function() {
      var self = this;
      self.notes = {
      shyam: {
        id: 1,
        label: 'First Note',
        done: false
      },
      Misko: {
        id: 3,
        label: 'Finished Third Note',
        done: true
      },
      brad: {
        id: 2,
        label: 'Second Note',
        done: false
      }
    };
  }]);
</script>

Helper variables in ng-repeat

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<div ng-repeat="note in ctrl.notes">
  <div>First Element: {\{$first}}</div>
  <div>Middle Element: {\{$middle}}</div>
  <div>Last Element: {\{$last}}</div>
  <div>Index of Element: {\{$index}}</div>
  <div>At Even Position: {\{$even}}</div>
  <div>At Odd Position: {\{$odd}}</div>
  <span class="label"> {\{note.label}}</span>
  <span class="status" ng-bind="note.done"></span>
</div>

<script type="text/javascript">
var self = this;
self.notes = [
  {id: 1, label: 'First Note', done: false},
  {id: 2, label: 'Second Note', done: false},
  {id: 3, label: 'Done Note', done: true},
  {id: 4, label: 'Last Note', done: false}
];
</script>

To optimize performance, ng-repeat caches or reuses DOM elements if the objects are exactly the same, according to the hash of the object

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- DOM Elements are reused every time someone clicks -->
<button ng-click="ctrl.changeNotes()">Change Notes</button>
<div ng-repeat="note in ctrl.notes2 track by note.id">
  \{\{note.$$hashKey}}
  <span class="label"> </span>
  <span class="author" ng-bind="note.done"></span>
</div>

<!-- ng-repeat Across Multiple HTML Elements  -->
<table>
  <tr ng-repeat-start="note in ctrl.notes">
    <td></td>
  </tr>
  <tr ng-repeat-end>
    <td>Done: </td>
  </tr>
</table>

Karma

1
2
3
4
5
sudo npm install karma-cli -g
npm install karma
npm install karma-jasmine karma-chrome-launcher

karma init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// File: chapter3/karma.conf.js
// Karma configuration
module.exports = function(config) {
  config.set({
    // base path that will be used to resolve files and exclude
    basePath: '',
    // testing framework to use (jasmine/mocha/qunit/...)
    frameworks: ['jasmine'],
    
    // list of files / patterns to load in the browser
    files: [
      'angular.min.js',
      'angular-mocks.js',
      'controller.js',
      'simpleSpec.js',
      'controllerSpec.js'
    ],
      
    // list of files / patterns to exclude
    exclude: [],
    // web server port
    port: 8080,
    
    // level of logging
    // possible values: LOG_DISABLE || LOG_ERROR ||
    // LOG_WARN || LOG_INFO || LOG_DEBUG
    logLevel: config.LOG_INFO,
    
    // enable / disable watching file and executing tests
    // whenever any file changes
    autoWatch: true,
    // Start these browsers, currently available:
    // - Chrome
    // - ChromeCanary
    // - Firefox
    // - Opera
    // - Safari (only Mac)
    // - PhantomJS
    // - IE (only Windows)
    browsers: ['Chrome'],
    // Continuous Integration mode
    // if true, it captures browsers, runs tests, and exits
    singleRun: false
  });
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
describe('My Function', function() {
  var t;
  // Similar to setup
  beforeEach(function() {
    t = true;
  });
  afterEach(function() {
    t = null;
  });
  it('should perform action 1', function() {
    expect(t).toBeTruthy();
  });
  it('should perform action 2', function() {
    var expectedValue = true;
    expect(t).toEqual(expectedValue);
  });
});
  • toEqual, does a deep equality check between the two objects, like array.
  • toBe, expects both items passed to the expect and the matcher to be the exact same object reference.
  • toBeTruthy and toBeFalsy
  • toBeDefined, toBeUndefined and toBeNull
  • toContain, array passed to the expect contains the element passed to the matcher
  • toMatch, Used for regular expression checks when the first argument to the expect is a string that needs to match a specific regular expression pattern.

Unit Test for Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
angular.module('notesApp', [])
  .controller('ListCtrl', [function() {
    var self = this;
    self.items = [
      {id: 1, label: 'First', done: true},
      {id: 2, label: 'Second', done: false}
    ];
    self.getDoneClass = function(item) {
    return {
      finished: item.done,
      unfinished: !item.done
    };
  };
}]);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// File: chapter3/controllerSpec.js
describe('Controller: ListCtrl', function() {
  // Instantiate a new version of my module before each test
  beforeEach(module('notesApp'));
  var ctrl;
  
  // Before each unit test, instantiate a new instance
  // of the controller
  beforeEach(inject(function($controller) {
    ctrl = $controller('ListCtrl');
  }));
    
  it('should have items available on load', function() {
    expect(ctrl.items).toEqual([
      {id: 1, label: 'First', done: true},
      {id: 2, label: 'Second', done: false}
    ]);
  });
  it('should have highlight items based on state', function() {
    var item = {id: 1, label: 'First', done: true};
    var actualClass = ctrl.getDoneClass(item);
    expect(actualClass.finished).toBeTruthy();
    expect(actualClass.unfinished).toBeFalsy();
    item.done = false;
    actualClass = ctrl.getDoneClass(item);
    expect(actualClass.finished).toBeFalsy();
    expect(actualClass.unfinished).toBeTruthy();
  });
});
  
// karma start my.conf.js
// The examples and tests in this book were run using version 0.12.16
// of Karma, and version 1.2.19 of AngularJS (both the angular.js and
// angular-mocks.js files)
文章目录
  1. 1. Hello World
  2. 2. AngularJS Convenience Function
  3. 3. AngularJS Modules
  4. 4. Controller
    1. 4.1. More Directives
    2. 4.2. ng-repeat
  5. 5. Karma
    1. 5.1. Unit Test for Controller