UNPKG

knowhow-server

Version:

A personal workflow engine that can manage and use any network connected host

163 lines (158 loc) 8.87 kB
<a href="http://github.com/angular/angular.js/edit/master/docs/content/guide/expression.ngdoc" class="improve-docs btn btn-primary"><i class="icon-edit"> </i> Improve this doc</a><h1><code ng:non-bindable=""></code> <div><span class="hint"></span> </div> </h1> <div><div class="developer-guide-page developer-guide-expressions-page"><p>Expressions are JavaScript-like code snippets that are usually placed in bindings such as <code>{{ expression }}</code>. Expressions are processed by the <a href="api/ng.$parse"><code>$parse</code></a> service. Expressions are often post processed using <a href="guide/filter">filters</a> to create a more user-friendly format.</p> <p>For example, these are all valid expressions in angular:</p> <ul> <li><code>1+2</code></li> <li><code>user.name</code></li> </ul> <h3 id="angular-expressions-vs-js-expressions">Angular Expressions vs. JS Expressions</h3> <p>It might be tempting to think of Angular view expressions as JavaScript expressions, but that is not entirely correct, since Angular does not use a JavaScript <code>eval()</code> to evaluate expressions. You can think of Angular expressions as JavaScript expressions with following differences:</p> <ul> <li><p><strong>Attribute Evaluation:</strong> evaluation of all properties are against the scope doing the evaluation, unlike in JavaScript where the expressions are evaluated against the global <code>window</code>.</p> </li> <li><p><strong>Forgiving:</strong> expression evaluation is forgiving to <code>undefined</code> and <code>null</code>, unlike in JavaScript, where trying to evaluate undefined properties can generate <code>ReferenceError</code> or <code>TypeError</code>.</p> </li> <li><p><strong>No Control Flow Statements:</strong> you cannot do any of the following in angular expression: conditionals, loops, or throw.</p> </li> </ul> <p>If, on the other hand, you do want to run arbitrary JavaScript code, you should make it a controller method and call the method. If you want to <code>eval()</code> an angular expression from JavaScript, use the <a href="api/ng.$rootScope.Scope#methods_$eval"><code><code>$eval()</code></code></a> method.</p> <h3 id="example">Example</h3> <h3 id="source">Source</h3> <div source-edit="" source-edit-deps="angular.js" source-edit-html="index.html-252" source-edit-css="" source-edit-js="" source-edit-json="" source-edit-unit="" source-edit-scenario="scenario.js-253" source-edit-protractor=""></div> <div class="tabbable"><div class="tab-pane" title="index.html"> <pre class="prettyprint linenums" ng-set-text="index.html-252" ng-html-wrap=" angular.js"></pre> <script type="text/ng-template" id="index.html-252"> 1+2={{1+2}} </script> </div> <div class="tab-pane" title="ngScenario e2e test"> <pre class="prettyprint linenums" ng-set-text="scenario.js-253"></pre> <script type="text/ng-template" id="scenario.js-253"> it('should calculate expression in binding', function() { expect(binding('1+2')).toEqual('3'); }); </script> </div> </div><h3 id="demo">Demo</h3> <div class="well doc-example-live animate-container" ng-embed-app="" ng-set-html="index.html-252" ng-eval-javascript=""></div> <p>You can try evaluating different expressions here:</p> <h3 id="source">Source</h3> <div source-edit="" source-edit-deps="angular.js script.js" source-edit-html="index.html-255" source-edit-css="" source-edit-js="script.js-254" source-edit-json="" source-edit-unit="" source-edit-scenario="scenario.js-256" source-edit-protractor=""></div> <div class="tabbable"><div class="tab-pane" title="index.html"> <pre class="prettyprint linenums" ng-set-text="index.html-255" ng-html-wrap=" angular.js script.js"></pre> <script type="text/ng-template" id="index.html-255"> <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> </script> </div> <div class="tab-pane" title="script.js"> <pre class="prettyprint linenums" ng-set-text="script.js-254"></pre> <script type="text/ng-template" id="script.js-254"> 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); }; } </script> </div> <div class="tab-pane" title="ngScenario e2e test"> <pre class="prettyprint linenums" ng-set-text="scenario.js-256"></pre> <script type="text/ng-template" id="scenario.js-256"> it('should allow user expression testing', function() { element('.expressions :button').click(); var li = using('.expressions ul').repeater('li'); expect(li.count()).toBe(1); expect(li.row(0)).toEqual(["3*10|currency", "$30.00"]); }); </script> </div> </div><h3 id="demo">Demo</h3> <div class="well doc-example-live animate-container" ng-embed-app="" ng-set-html="index.html-255" ng-eval-javascript="script.js-254"></div> <h2 id="property-evaluation">Property Evaluation</h2> <p>Evaluation of all properties takes place against a scope. Unlike JavaScript, where names default to global window properties, Angular expressions have to use <a href="api/ng.$window"><code><code>$window</code></code></a> to refer to the global <code>window</code> object. For example, if you want to call <code>alert()</code>, which is defined on <code>window</code>, in an expression you must use <code>$window.alert()</code>. This is done intentionally to prevent accidental access to the global state (a common source of subtle bugs).</p> <h3 id="property-evaluation_source">Source</h3> <div source-edit="" source-edit-deps="angular.js script.js" source-edit-html="index.html-258" source-edit-css="" source-edit-js="script.js-257" source-edit-json="" source-edit-unit="" source-edit-scenario="scenario.js-259" source-edit-protractor=""></div> <div class="tabbable"><div class="tab-pane" title="index.html"> <pre class="prettyprint linenums" ng-set-text="index.html-258" ng-html-wrap=" angular.js script.js"></pre> <script type="text/ng-template" id="index.html-258"> <div class="example2" ng-controller="Cntl1"> Name: <input ng-model="name" type="text"/> <button ng-click="greet()">Greet</button> </div> </script> </div> <div class="tab-pane" title="script.js"> <pre class="prettyprint linenums" ng-set-text="script.js-257"></pre> <script type="text/ng-template" id="script.js-257"> function Cntl1($window, $scope){ $scope.name = 'World'; $scope.greet = function() { ($window.mockWindow || $window).alert('Hello ' + $scope.name); } } </script> </div> <div class="tab-pane" title="ngScenario e2e test"> <pre class="prettyprint linenums" ng-set-text="scenario.js-259"></pre> <script type="text/ng-template" id="scenario.js-259"> it('should calculate expression in binding', function() { var alertText; this.addFutureAction('set mock', function($window, $document, done) { $window.mockWindow = { alert: function(text){ alertText = text; } }; done(); }); element(':button:contains(Greet)').click(); expect(this.addFuture('alert text', function(done) { done(null, alertText); })).toBe('Hello World'); }); </script> </div> </div><h3 id="property-evaluation_demo">Demo</h3> <div class="well doc-example-live animate-container" ng-embed-app="" ng-set-html="index.html-258" ng-eval-javascript="script.js-257"></div> <h3 id="property-evaluation_forgiving">Forgiving</h3> <p>Expression evaluation is forgiving to undefined and null. In JavaScript, evaluating <code>a.b.c</code> throws an exception if <code>a</code> 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:</p> <pre><code> {{a.b.c}}</code></pre> <p>It makes more sense to show nothing than to throw an exception if <code>a</code> is undefined (perhaps we are waiting for the server response, and it will become defined soon). If expression evaluation wasn&#39;t forgiving we&#39;d have to write bindings that clutter the code, for example: <code>{{((a||{}).b||{}).c}}</code></p> <p>Similarly, invoking a function <code>a.b.c()</code> on undefined or null simply returns undefined.</p> <h3 id="property-evaluation_no-control-flow-statements">No Control Flow Statements</h3> <p>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 in the view. If you need a conditional, loop, or to throw from a view expression, delegate to a JavaScript method instead.</p> </div></div>