| 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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
 | @ngdoc overview
@name  Expressions
@description
Expressions are JavaScript-like code snippets that are usually placed in bindings such as
`{{ expression }}`.
For example, these are valid expressions in Angular:
  * `1+2`
  * `a+b`
  * `user.name`
  * `items[index]`
## Angular Expressions vs. JavaScript Expressions
Angular expressions are like JavaScript expressions with the following differences:
  * **Context:** JavaScript expressions are evaluated against the global `window`.
    In Angular, expressions are evaluated against a {@link ng.$rootScope.Scope `scope`} object.
  * **Forgiving:** In JavaScript, trying to evaluate undefined properties generates `ReferenceError`
    or `TypeError`. In Angular, expression evaluation is forgiving to `undefined` and `null`.
  * **No Control Flow Statements:** you cannot use the following in an Angular expression:
    conditionals, loops, or exceptions.
  * **Filters:** You can use {@link guide/filter filters} within expressions to format data before
    displaying it.
If you want to run more complex JavaScript code, you should make it a controller method and call
the method from your view. If you want to `eval()` an Angular expression yourself, use the
{@link ng.$rootScope.Scope#$eval `$eval()`} method.
## Example
<example>
  <file name="index.html">
    1+2={{1+2}}
  </file>
  <file name="protractor.js" type="protractor">
    it('should calculate expression in binding', function() {
      expect(element(by.binding('1+2')).getText()).toEqual('1+2=3');
    });
  </file>
</example>
You can try evaluating different expressions here:
<example>
  <file name="index.html">
    <div ng-controller="Cntl2" class="expressions">
      Expression:
      <input type='text' ng-model="expr" size="80"/>
      <button ng-click="addExp(expr)">Evaluate</button>
      <ul>
       <li ng-repeat="expr in exprs track by $index">
         [ <a href="" ng-click="removeExp($index)">X</a> ]
         <tt>{{expr}}</tt> => <span ng-bind="$parent.$eval(expr)"></span>
        </li>
      </ul>
    </div>
  </file>
  <file name="script.js">
    function Cntl2($scope) {
      var exprs = $scope.exprs = [];
      $scope.expr = '3*10|currency';
      $scope.addExp = function(expr) {
        exprs.push(expr);
      };
      $scope.removeExp = function(index) {
        exprs.splice(index, 1);
      };
    }
  </file>
  <file name="protractor.js" type="protractor">
    it('should allow user expression testing', function() {
      element(by.css('.expressions button')).click();
      var lis = element(by.css('.expressions ul')).element.all(by.repeater('expr in exprs'));
      expect(lis.count()).toBe(1);
      expect(lis.get(0).getText()).toEqual('[ X ] 3*10|currency => $30.00');
    });
  </file>
</example>
# Context
Angular does not use JavaScript's `eval()` to evaluate expressions. Instead Angular's
{@link ng.$parse $parse} service processes these expressions.
Unlike JavaScript, where names default to global `window` properties, Angular expressions must use
{@link ng.$window `$window`} explicitly to refer to the global `window` object. For example, if you
want to call `alert()` in an expression you must use `$window.alert()`. This restriction is
intentional. It prevents accidental access to the global state – a common source of subtle bugs.
<example>
  <file name="index.html">
    <div class="example2" ng-controller="Cntl1">
      Name: <input ng-model="name" type="text"/>
      <button ng-click="greet()">Greet</button>
    </div>
  </file>
  <file name="script.js">
    function Cntl1($window, $scope){
      $scope.name = 'World';
      $scope.greet = function() {
        $window.alert('Hello ' + $scope.name);
      };
    }
  </file>
  <file name="protractor.js" type="protractor">
    it('should calculate expression in binding', function() {
      if (browser.params.browser == 'safari') {
        // Safari can't handle dialogs.
        return;
      }
      element(by.css('[ng-click="greet()"]')).click();
      var alertDialog = browser.switchTo().alert();
      expect(alertDialog.getText()).toEqual('Hello World');
      alertDialog.accept();
    });
  </file>
</example>
## Forgiving
Expression evaluation is forgiving to undefined and null. In JavaScript, evaluating `a.b.c` throws
an exception if `a` is not an object. While this makes sense for a general purpose language, the
expression evaluations are primarily used for data binding, which often look like this:
        {{a.b.c}}
It makes more sense to show nothing than to throw an exception if `a` is undefined (perhaps we are
waiting for the server response, and it will become defined soon). If expression evaluation wasn't
forgiving we'd have to write bindings that clutter the code, for example: `{{((a||{}).b||{}).c}}`
Similarly, invoking a function `a.b.c()` on `undefined` or `null` simply returns `undefined`.
## No Control Flow Statements
You cannot write a control flow statement in an expression. The reason behind this is core to the
Angular philosophy that application logic should be in controllers, not the views. If you need a
conditional, loop, or to throw from a view expression, delegate to a JavaScript method instead.
 |