blob: b8a33c8659372121536d3a8c9dc1872ca3ef4f74 [file]
<a href='http://github.com/angular/angular.js/edit/master/docs/content/guide/expression.ngdoc' class='improve-docs btn btn-primary'><i class="glyphicon glyphicon-edit">&nbsp;</i>Improve this doc</a>
<h1 id="angular-expressions">Angular Expressions</h1>
<p>Angular expressions are JavaScript-like code snippets that are usually placed in bindings such as
<code>{{ expression }}</code>.</p>
<p>For example, these are valid expressions in Angular:</p>
<ul>
<li><code>1+2</code></li>
<li><code>a+b</code></li>
<li><code>user.name</code></li>
<li><code>items[index]</code></li>
</ul>
<h2 id="angular-expressions-vs-javascript-expressions">Angular Expressions vs. JavaScript Expressions</h2>
<p>Angular expressions are like JavaScript expressions with the following differences:</p>
<ul>
<li><p><strong>Context:</strong> JavaScript expressions are evaluated against the global <code>window</code>.
In Angular, expressions are evaluated against a <a href="api/ng/type/$rootScope.Scope"><code>scope</code></a> object.</p>
</li>
<li><p><strong>Forgiving:</strong> In JavaScript, trying to evaluate undefined properties generates <code>ReferenceError</code>
or <code>TypeError</code>. In Angular, expression evaluation is forgiving to <code>undefined</code> and <code>null</code>.</p>
</li>
<li><p><strong>No Control Flow Statements:</strong> you cannot use the following in an Angular expression:
conditionals, loops, or exceptions.</p>
</li>
<li><p><strong>Filters:</strong> You can use <a href="guide/filter">filters</a> within expressions to format data before
displaying it.</p>
</li>
</ul>
<p>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 <code>eval()</code> an Angular expression yourself, use the
<a href="api/ng/type/$rootScope.Scope#$eval"><code>$eval()</code></a> method.</p>
<h2 id="example">Example</h2>
<p>
<div>
<a ng-href="http://plnkr.co/edit/ngdoc:example-example92@{{docsVersion}}?p=preview" class="btn pull-right" target="_blank">
<i class="glyphicon glyphicon-edit">&nbsp;</i>
Edit in Plunker</a>
<div class="runnable-example"
path="examples/example-example92">
<div class="runnable-example-file"
name="index.html"
language="html"
type="html">
<pre><code>1+2={{1+2}}</code></pre>
</div>
<div class="runnable-example-file"
name="protractor.js"
type="protractor"
language="js">
<pre><code>it(&#39;should calculate expression in binding&#39;, function() {&#10; expect(element(by.binding(&#39;1+2&#39;)).getText()).toEqual(&#39;1+2=3&#39;);&#10;});</code></pre>
</div>
<iframe class="runnable-example-frame" src="examples/example-example92/index.html" name="example-example92"></iframe>
</div>
</div>
</p>
<p>You can try evaluating different expressions here:</p>
<p>
<div>
<a ng-href="http://plnkr.co/edit/ngdoc:example-example93@{{docsVersion}}?p=preview" class="btn pull-right" target="_blank">
<i class="glyphicon glyphicon-edit">&nbsp;</i>
Edit in Plunker</a>
<div class="runnable-example"
path="examples/example-example93">
<div class="runnable-example-file"
name="index.html"
language="html"
type="html">
<pre><code>&lt;div ng-controller=&quot;Cntl2&quot; class=&quot;expressions&quot;&gt;&#10; Expression:&#10; &lt;input type=&#39;text&#39; ng-model=&quot;expr&quot; size=&quot;80&quot;/&gt;&#10; &lt;button ng-click=&quot;addExp(expr)&quot;&gt;Evaluate&lt;/button&gt;&#10; &lt;ul&gt;&#10; &lt;li ng-repeat=&quot;expr in exprs track by $index&quot;&gt;&#10; [ &lt;a href=&quot;&quot; ng-click=&quot;removeExp($index)&quot;&gt;X&lt;/a&gt; ]&#10; &lt;tt&gt;{{expr}}&lt;/tt&gt; =&gt; &lt;span ng-bind=&quot;$parent.$eval(expr)&quot;&gt;&lt;/span&gt;&#10; &lt;/li&gt;&#10; &lt;/ul&gt;&#10;&lt;/div&gt;</code></pre>
</div>
<div class="runnable-example-file"
name="script.js"
language="js"
type="js">
<pre><code>function Cntl2($scope) {&#10; var exprs = $scope.exprs = [];&#10; $scope.expr = &#39;3*10|currency&#39;;&#10; $scope.addExp = function(expr) {&#10; exprs.push(expr);&#10; };&#10;&#10; $scope.removeExp = function(index) {&#10; exprs.splice(index, 1);&#10; };&#10;}</code></pre>
</div>
<div class="runnable-example-file"
name="protractor.js"
type="protractor"
language="js">
<pre><code>it(&#39;should allow user expression testing&#39;, function() {&#10; element(by.css(&#39;.expressions button&#39;)).click();&#10; var lis = element(by.css(&#39;.expressions ul&#39;)).element.all(by.repeater(&#39;expr in exprs&#39;));&#10; expect(lis.count()).toBe(1);&#10; expect(lis.get(0).getText()).toEqual(&#39;[ X ] 3*10|currency =&gt; $30.00&#39;);&#10;});</code></pre>
</div>
<iframe class="runnable-example-frame" src="examples/example-example93/index.html" name="example-example93"></iframe>
</div>
</div>
</p>
<h2 id="context">Context</h2>
<p>Angular does not use JavaScript&#39;s <code>eval()</code> to evaluate expressions. Instead Angular&#39;s
<a href="api/ng/service/$parse">$parse</a> service processes these expressions.</p>
<p>Unlike JavaScript, where names default to global <code>window</code> properties, Angular expressions must use
<a href="api/ng/service/$window"><code>$window</code></a> explicitly to refer to the global <code>window</code> object. For example, if you
want to call <code>alert()</code> in an expression you must use <code>$window.alert()</code>. This restriction is
intentional. It prevents accidental access to the global state – a common source of subtle bugs.</p>
<p>
<div>
<a ng-href="http://plnkr.co/edit/ngdoc:example-example94@{{docsVersion}}?p=preview" class="btn pull-right" target="_blank">
<i class="glyphicon glyphicon-edit">&nbsp;</i>
Edit in Plunker</a>
<div class="runnable-example"
path="examples/example-example94">
<div class="runnable-example-file"
name="index.html"
language="html"
type="html">
<pre><code>&lt;div class=&quot;example2&quot; ng-controller=&quot;Cntl1&quot;&gt;&#10; Name: &lt;input ng-model=&quot;name&quot; type=&quot;text&quot;/&gt;&#10; &lt;button ng-click=&quot;greet()&quot;&gt;Greet&lt;/button&gt;&#10;&lt;/div&gt;</code></pre>
</div>
<div class="runnable-example-file"
name="script.js"
language="js"
type="js">
<pre><code>function Cntl1($window, $scope){&#10; $scope.name = &#39;World&#39;;&#10;&#10; $scope.greet = function() {&#10; $window.alert(&#39;Hello &#39; + $scope.name);&#10; };&#10;}</code></pre>
</div>
<div class="runnable-example-file"
name="protractor.js"
type="protractor"
language="js">
<pre><code>it(&#39;should calculate expression in binding&#39;, function() {&#10; if (browser.params.browser == &#39;safari&#39;) {&#10; // Safari can&#39;t handle dialogs.&#10; return;&#10; }&#10; element(by.css(&#39;[ng-click=&quot;greet()&quot;]&#39;)).click();&#10;&#10; var alertDialog = browser.switchTo().alert();&#10;&#10; expect(alertDialog.getText()).toEqual(&#39;Hello World&#39;);&#10;&#10; alertDialog.accept();&#10;});</code></pre>
</div>
<iframe class="runnable-example-frame" src="examples/example-example94/index.html" name="example-example94"></iframe>
</div>
</div>
</p>
<h2 id="forgiving">Forgiving</h2>
<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 <code>undefined</code> or <code>null</code> simply returns <code>undefined</code>.</p>
<h2 id="no-control-flow-statements">No Control Flow Statements</h2>
<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 the views. If you need a
conditional, loop, or to throw from a view expression, delegate to a JavaScript method instead.</p>
<h2 id="-event-"><code>$event</code></h2>
<p>Directives like <a href="api/ng/directive/ngClick"><code>ngClick</code></a> and <a href="api/ng/directive/ngFocus"><code>ngFocus</code></a>
expose a <code>$event</code> object within the scope of that expression.</p>
<p>
<div>
<a ng-href="http://plnkr.co/edit/ngdoc:example-example95@{{docsVersion}}?p=preview" class="btn pull-right" target="_blank">
<i class="glyphicon glyphicon-edit">&nbsp;</i>
Edit in Plunker</a>
<div class="runnable-example"
path="examples/example-example95"
module="eventExampleApp">
<div class="runnable-example-file"
name="index.html"
language="html"
type="html">
<pre><code>&lt;div ng-controller=&quot;EventController&quot;&gt;&#10; &lt;button ng-click=&quot;clickMe($event)&quot;&gt;Event&lt;/button&gt;&#10; &lt;p&gt;&lt;code&gt;$event&lt;/code&gt;: &lt;pre&gt; {{$event | json}}&lt;/pre&gt;&lt;/p&gt;&#10; &lt;p&gt;&lt;code&gt;clickEvent&lt;/code&gt;: &lt;pre&gt;{{clickEvent | json}}&lt;/pre&gt;&lt;/p&gt;&#10;&lt;/div&gt;</code></pre>
</div>
<div class="runnable-example-file"
name="script.js"
language="js"
type="js">
<pre><code>angular.module(&#39;eventExampleApp&#39;, []).&#10; controller(&#39;EventController&#39;, [&#39;$scope&#39;, function($scope) {&#10; /*&#10; * expose the event object to the scope&#10; */&#10; $scope.clickMe = function(clickEvent) {&#10; $scope.clickEvent = simpleKeys(clickEvent);&#10; console.log(clickEvent);&#10; };&#10;&#10; /*&#10; * return a copy of an object with only non-object keys&#10; * we need this to avoid circular references&#10; */&#10; function simpleKeys (original) {&#10; return Object.keys(original).reduce(function (obj, key) {&#10; obj[key] = typeof original[key] === &#39;object&#39; ? &#39;{ ... }&#39; : original[key];&#10; return obj;&#10; }, {});&#10; }&#10; }]);</code></pre>
</div>
<iframe class="runnable-example-frame" src="examples/example-example95/index.html" name="example-example95"></iframe>
</div>
</div>
</p>
<p>Note in the example above how we can pass in <code>$event</code> to <code>clickMe</code>, but how it does not show up
in <code>{{$event}}</code>. This is because <code>$event</code> is outside the scope of that binding.</p>