2011-06-06 08:50:35 -07:00
|
|
|
|
@ngdoc overview
|
2014-02-15 16:09:27 +00:00
|
|
|
|
@name Expressions
|
2014-09-04 16:49:16 +01:00
|
|
|
|
@sortOrder 270
|
2011-06-06 08:50:35 -07:00
|
|
|
|
@description
|
|
|
|
|
|
|
2017-01-24 17:23:54 +00:00
|
|
|
|
# AngularJS Expressions
|
2014-03-25 15:53:27 -07:00
|
|
|
|
|
2017-01-24 17:23:54 +00:00
|
|
|
|
AngularJS expressions are JavaScript-like code snippets that are mainly placed in
|
2015-12-05 19:42:57 +01:00
|
|
|
|
interpolation bindings such as `<span title="{{ attrBinding }}">{{ textBinding }}</span>`,
|
|
|
|
|
|
but also used directly in directive attributes such as `ng-click="functionExpression()"`.
|
2011-06-06 08:50:35 -07:00
|
|
|
|
|
2017-01-24 17:23:54 +00:00
|
|
|
|
For example, these are valid expressions in AngularJS:
|
2011-06-06 08:50:35 -07:00
|
|
|
|
|
2012-02-28 14:29:58 -08:00
|
|
|
|
* `1+2`
|
2014-03-02 22:29:11 -08:00
|
|
|
|
* `a+b`
|
2012-02-28 14:29:58 -08:00
|
|
|
|
* `user.name`
|
2014-03-02 22:29:11 -08:00
|
|
|
|
* `items[index]`
|
2011-06-06 08:50:35 -07:00
|
|
|
|
|
|
|
|
|
|
|
2017-01-24 17:23:54 +00:00
|
|
|
|
## AngularJS Expressions vs. JavaScript Expressions
|
2011-06-06 08:50:35 -07:00
|
|
|
|
|
2017-01-24 17:23:54 +00:00
|
|
|
|
AngularJS expressions are like JavaScript expressions with the following differences:
|
2012-02-28 14:29:58 -08:00
|
|
|
|
|
2014-03-02 22:29:11 -08:00
|
|
|
|
* **Context:** JavaScript expressions are evaluated against the global `window`.
|
2017-01-24 17:23:54 +00:00
|
|
|
|
In AngularJS, expressions are evaluated against a {@link ng.$rootScope.Scope `scope`} object.
|
2012-02-28 14:29:58 -08:00
|
|
|
|
|
2014-03-02 22:29:11 -08:00
|
|
|
|
* **Forgiving:** In JavaScript, trying to evaluate undefined properties generates `ReferenceError`
|
2017-01-24 17:23:54 +00:00
|
|
|
|
or `TypeError`. In AngularJS, expression evaluation is forgiving to `undefined` and `null`.
|
2012-02-28 14:29:58 -08:00
|
|
|
|
|
2016-04-21 16:15:17 +02:00
|
|
|
|
* **Filters:** You can use {@link guide/filter filters} within expressions to format data before
|
|
|
|
|
|
displaying it.
|
|
|
|
|
|
|
2017-01-24 17:23:54 +00:00
|
|
|
|
* **No Control Flow Statements:** You cannot use the following in an AngularJS expression:
|
2014-03-02 22:29:11 -08:00
|
|
|
|
conditionals, loops, or exceptions.
|
2015-05-29 14:56:19 -04:00
|
|
|
|
|
2017-01-24 17:23:54 +00:00
|
|
|
|
* **No Function Declarations:** You cannot declare functions in an AngularJS expression,
|
2014-12-17 21:55:31 -08:00
|
|
|
|
even inside `ng-init` directive.
|
2015-05-29 14:56:19 -04:00
|
|
|
|
|
|
|
|
|
|
* **No RegExp Creation With Literal Notation:** You cannot create regular expressions
|
2017-08-30 13:31:38 +03:00
|
|
|
|
in an AngularJS expression. An exception to this rule is {@link ngPattern `ng-pattern`} which accepts valid
|
|
|
|
|
|
RegExp.
|
2015-05-29 14:56:19 -04:00
|
|
|
|
|
2017-01-24 17:23:54 +00:00
|
|
|
|
* **No Object Creation With New Operator:** You cannot use `new` operator in an AngularJS expression.
|
2015-12-02 15:01:14 +03:00
|
|
|
|
|
2016-04-21 16:15:17 +02:00
|
|
|
|
* **No Bitwise, Comma, And Void Operators:** You cannot use
|
2016-07-04 15:36:41 +02:00
|
|
|
|
[Bitwise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators),
|
2017-01-24 17:23:54 +00:00
|
|
|
|
`,` or `void` operators in an AngularJS expression.
|
2012-02-28 14:29:58 -08:00
|
|
|
|
|
2014-03-02 22:29:11 -08:00
|
|
|
|
|
|
|
|
|
|
If you want to run more complex JavaScript code, you should make it a controller method and call
|
2017-01-24 17:23:54 +00:00
|
|
|
|
the method from your view. If you want to `eval()` an AngularJS expression yourself, use the
|
2014-03-02 22:29:11 -08:00
|
|
|
|
{@link ng.$rootScope.Scope#$eval `$eval()`} method.
|
2011-06-06 08:50:35 -07:00
|
|
|
|
|
|
|
|
|
|
## Example
|
2016-07-27 18:30:35 +01:00
|
|
|
|
<example name="expression-simple">
|
2014-02-15 20:19:10 -05:00
|
|
|
|
<file name="index.html">
|
2014-06-09 22:20:47 -07:00
|
|
|
|
<span>
|
|
|
|
|
|
1+2={{1+2}}
|
|
|
|
|
|
</span>
|
2014-02-15 20:19:10 -05:00
|
|
|
|
</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>
|
2011-06-06 08:50:35 -07:00
|
|
|
|
|
|
|
|
|
|
You can try evaluating different expressions here:
|
|
|
|
|
|
|
2016-07-27 18:30:35 +01:00
|
|
|
|
<example module="expressionExample" name="expression-eval">
|
2014-02-15 20:19:10 -05:00
|
|
|
|
<file name="index.html">
|
2014-07-08 01:12:10 -07:00
|
|
|
|
<div ng-controller="ExampleController" class="expressions">
|
2014-02-15 20:19:10 -05:00
|
|
|
|
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> ]
|
2015-07-26 16:39:51 +08:00
|
|
|
|
<code>{{expr}}</code> => <span ng-bind="$parent.$eval(expr)"></span>
|
2014-02-15 20:19:10 -05:00
|
|
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</file>
|
|
|
|
|
|
|
|
|
|
|
|
<file name="script.js">
|
2014-07-08 01:12:10 -07:00
|
|
|
|
angular.module('expressionExample', [])
|
|
|
|
|
|
.controller('ExampleController', ['$scope', function($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);
|
|
|
|
|
|
};
|
|
|
|
|
|
}]);
|
2014-02-15 20:19:10 -05:00
|
|
|
|
</file>
|
|
|
|
|
|
|
|
|
|
|
|
<file name="protractor.js" type="protractor">
|
|
|
|
|
|
it('should allow user expression testing', function() {
|
|
|
|
|
|
element(by.css('.expressions button')).click();
|
2014-07-02 14:09:10 -07:00
|
|
|
|
var lis = element(by.css('.expressions ul')).all(by.repeater('expr in exprs'));
|
2014-02-15 20:19:10 -05:00
|
|
|
|
expect(lis.count()).toBe(1);
|
|
|
|
|
|
expect(lis.get(0).getText()).toEqual('[ X ] 3*10|currency => $30.00');
|
|
|
|
|
|
});
|
|
|
|
|
|
</file>
|
|
|
|
|
|
</example>
|
2011-06-06 08:50:35 -07:00
|
|
|
|
|
|
|
|
|
|
|
2014-03-25 15:53:27 -07:00
|
|
|
|
## Context
|
2014-03-02 22:29:11 -08:00
|
|
|
|
|
2017-01-24 17:23:54 +00:00
|
|
|
|
AngularJS does not use JavaScript's `eval()` to evaluate expressions. Instead AngularJS's
|
2014-03-02 22:29:11 -08:00
|
|
|
|
{@link ng.$parse $parse} service processes these expressions.
|
2011-06-06 08:50:35 -07:00
|
|
|
|
|
2017-01-24 17:23:54 +00:00
|
|
|
|
AngularJS expressions do not have direct access to global variables like `window`, `document` or `location`.
|
2014-06-03 12:07:51 +01:00
|
|
|
|
This restriction is intentional. It prevents accidental access to the global state – a common source of subtle bugs.
|
|
|
|
|
|
|
2016-09-06 14:33:23 +01:00
|
|
|
|
Instead use services like `$window` and `$location` in functions on controllers, which are then called from expressions.
|
|
|
|
|
|
Such services provide mockable access to globals.
|
2011-06-06 08:50:35 -07:00
|
|
|
|
|
2015-12-06 17:03:15 +01:00
|
|
|
|
It is possible to access the context object using the identifier `this` and the locals object using the
|
|
|
|
|
|
identifier `$locals`.
|
|
|
|
|
|
|
2016-07-27 18:30:35 +01:00
|
|
|
|
<example module="expressionExample" name="expression-locals">
|
2014-02-15 20:19:10 -05:00
|
|
|
|
<file name="index.html">
|
2014-07-08 01:12:10 -07:00
|
|
|
|
<div class="example2" ng-controller="ExampleController">
|
2014-02-15 20:19:10 -05:00
|
|
|
|
Name: <input ng-model="name" type="text"/>
|
|
|
|
|
|
<button ng-click="greet()">Greet</button>
|
2014-06-03 12:07:51 +01:00
|
|
|
|
<button ng-click="window.alert('Should not see me')">Won't greet</button>
|
2014-02-15 20:19:10 -05:00
|
|
|
|
</div>
|
|
|
|
|
|
</file>
|
|
|
|
|
|
|
|
|
|
|
|
<file name="script.js">
|
2014-07-08 01:12:10 -07:00
|
|
|
|
angular.module('expressionExample', [])
|
|
|
|
|
|
.controller('ExampleController', ['$window', '$scope', function($window, $scope) {
|
|
|
|
|
|
$scope.name = 'World';
|
|
|
|
|
|
|
|
|
|
|
|
$scope.greet = function() {
|
|
|
|
|
|
$window.alert('Hello ' + $scope.name);
|
|
|
|
|
|
};
|
|
|
|
|
|
}]);
|
2014-02-15 20:19:10 -05:00
|
|
|
|
</file>
|
|
|
|
|
|
|
|
|
|
|
|
<file name="protractor.js" type="protractor">
|
|
|
|
|
|
it('should calculate expression in binding', function() {
|
2016-07-20 15:45:04 +02:00
|
|
|
|
if (browser.params.browser === 'safari') {
|
2014-02-15 20:19:10 -05:00
|
|
|
|
// Safari can't handle dialogs.
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
element(by.css('[ng-click="greet()"]')).click();
|
|
|
|
|
|
|
2015-07-27 10:52:11 +01:00
|
|
|
|
// We need to give the browser time to display the alert
|
2015-07-28 14:41:01 +01:00
|
|
|
|
browser.wait(protractor.ExpectedConditions.alertIsPresent(), 1000);
|
2015-07-27 10:52:11 +01:00
|
|
|
|
|
2014-02-15 20:19:10 -05:00
|
|
|
|
var alertDialog = browser.switchTo().alert();
|
|
|
|
|
|
|
|
|
|
|
|
expect(alertDialog.getText()).toEqual('Hello World');
|
|
|
|
|
|
|
|
|
|
|
|
alertDialog.accept();
|
|
|
|
|
|
});
|
|
|
|
|
|
</file>
|
|
|
|
|
|
</example>
|
2011-06-06 08:50:35 -07:00
|
|
|
|
|
|
|
|
|
|
## 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}}`
|
|
|
|
|
|
|
2014-03-02 22:29:11 -08:00
|
|
|
|
Similarly, invoking a function `a.b.c()` on `undefined` or `null` simply returns `undefined`.
|
2011-06-06 08:50:35 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## No Control Flow Statements
|
|
|
|
|
|
|
2014-05-21 14:46:05 +01:00
|
|
|
|
Apart from the ternary operator (`a ? b : c`), you cannot write a control flow statement in an
|
2017-01-24 17:23:54 +00:00
|
|
|
|
expression. The reason behind this is core to the AngularJS philosophy that application logic should
|
2014-05-21 14:46:05 +01:00
|
|
|
|
be in controllers, not the views. If you need a real conditional, loop, or to throw from a view
|
|
|
|
|
|
expression, delegate to a JavaScript method instead.
|
2011-06-06 08:50:35 -07:00
|
|
|
|
|
2014-12-14 20:00:45 +02:00
|
|
|
|
## No function declarations or RegExp creation with literal notation
|
2014-11-12 20:58:59 +01:00
|
|
|
|
|
2014-12-14 20:00:45 +02:00
|
|
|
|
You can't declare functions or create regular expressions from within AngularJS expressions. This is
|
2015-05-29 14:56:19 -04:00
|
|
|
|
to avoid complex model transformation logic inside templates. Such logic is better placed in a
|
2014-12-14 20:00:45 +02:00
|
|
|
|
controller or in a dedicated filter where it can be tested properly.
|
2014-11-12 20:58:59 +01:00
|
|
|
|
|
2014-03-25 15:53:27 -07:00
|
|
|
|
## `$event`
|
|
|
|
|
|
|
|
|
|
|
|
Directives like {@link ng.directive:ngClick `ngClick`} and {@link ng.directive:ngFocus `ngFocus`}
|
2014-09-15 17:36:58 -04:00
|
|
|
|
expose a `$event` object within the scope of that expression. The object is an instance of a [jQuery
|
|
|
|
|
|
Event Object](http://api.jquery.com/category/events/event-object/) when jQuery is present or a
|
|
|
|
|
|
similar jqLite object.
|
2014-03-25 15:53:27 -07:00
|
|
|
|
|
2016-07-27 18:30:35 +01:00
|
|
|
|
<example module="eventExampleApp" name="expression-events">
|
2014-03-25 15:53:27 -07:00
|
|
|
|
<file name="index.html">
|
|
|
|
|
|
<div ng-controller="EventController">
|
|
|
|
|
|
<button ng-click="clickMe($event)">Event</button>
|
|
|
|
|
|
<p><code>$event</code>: <pre> {{$event | json}}</pre></p>
|
|
|
|
|
|
<p><code>clickEvent</code>: <pre>{{clickEvent | json}}</pre></p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</file>
|
|
|
|
|
|
|
|
|
|
|
|
<file name="script.js">
|
|
|
|
|
|
angular.module('eventExampleApp', []).
|
|
|
|
|
|
controller('EventController', ['$scope', function($scope) {
|
|
|
|
|
|
/*
|
|
|
|
|
|
* expose the event object to the scope
|
|
|
|
|
|
*/
|
|
|
|
|
|
$scope.clickMe = function(clickEvent) {
|
|
|
|
|
|
$scope.clickEvent = simpleKeys(clickEvent);
|
|
|
|
|
|
console.log(clickEvent);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* return a copy of an object with only non-object keys
|
|
|
|
|
|
* we need this to avoid circular references
|
|
|
|
|
|
*/
|
2016-07-20 15:45:04 +02:00
|
|
|
|
function simpleKeys(original) {
|
|
|
|
|
|
return Object.keys(original).reduce(function(obj, key) {
|
2014-03-25 15:53:27 -07:00
|
|
|
|
obj[key] = typeof original[key] === 'object' ? '{ ... }' : original[key];
|
|
|
|
|
|
return obj;
|
|
|
|
|
|
}, {});
|
|
|
|
|
|
}
|
|
|
|
|
|
}]);
|
|
|
|
|
|
</file>
|
|
|
|
|
|
</example>
|
|
|
|
|
|
|
|
|
|
|
|
Note in the example above how we can pass in `$event` to `clickMe`, but how it does not show up
|
|
|
|
|
|
in `{{$event}}`. This is because `$event` is outside the scope of that binding.
|
2014-06-04 13:49:23 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## One-time binding
|
|
|
|
|
|
|
|
|
|
|
|
An expression that starts with `::` is considered a one-time expression. One-time expressions
|
|
|
|
|
|
will stop recalculating once they are stable, which happens after the first digest if the expression
|
|
|
|
|
|
result is a non-undefined value (see value stabilization algorithm below).
|
|
|
|
|
|
|
2017-02-01 11:28:56 -08:00
|
|
|
|
<example module="oneTimeBindingExampleApp" name="expression-one-time">
|
2014-06-04 13:49:23 -07:00
|
|
|
|
<file name="index.html">
|
|
|
|
|
|
<div ng-controller="EventController">
|
|
|
|
|
|
<button ng-click="clickMe($event)">Click Me</button>
|
|
|
|
|
|
<p id="one-time-binding-example">One time binding: {{::name}}</p>
|
|
|
|
|
|
<p id="normal-binding-example">Normal binding: {{name}}</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</file>
|
|
|
|
|
|
<file name="script.js">
|
2017-02-01 11:28:56 -08:00
|
|
|
|
angular.module('oneTimeBindingExampleApp', []).
|
2014-06-04 13:49:23 -07:00
|
|
|
|
controller('EventController', ['$scope', function($scope) {
|
|
|
|
|
|
var counter = 0;
|
|
|
|
|
|
var names = ['Igor', 'Misko', 'Chirayu', 'Lucas'];
|
|
|
|
|
|
/*
|
|
|
|
|
|
* expose the event object to the scope
|
|
|
|
|
|
*/
|
|
|
|
|
|
$scope.clickMe = function(clickEvent) {
|
|
|
|
|
|
$scope.name = names[counter % names.length];
|
|
|
|
|
|
counter++;
|
|
|
|
|
|
};
|
|
|
|
|
|
}]);
|
|
|
|
|
|
</file>
|
|
|
|
|
|
<file name="protractor.js" type="protractor">
|
|
|
|
|
|
it('should freeze binding after its value has stabilized', function() {
|
2017-02-01 11:28:56 -08:00
|
|
|
|
var oneTimeBinding = element(by.id('one-time-binding-example'));
|
2014-06-04 13:49:23 -07:00
|
|
|
|
var normalBinding = element(by.id('normal-binding-example'));
|
|
|
|
|
|
|
2017-02-01 11:28:56 -08:00
|
|
|
|
expect(oneTimeBinding.getText()).toEqual('One time binding:');
|
2014-06-04 13:49:23 -07:00
|
|
|
|
expect(normalBinding.getText()).toEqual('Normal binding:');
|
|
|
|
|
|
element(by.buttonText('Click Me')).click();
|
|
|
|
|
|
|
2017-02-01 11:28:56 -08:00
|
|
|
|
expect(oneTimeBinding.getText()).toEqual('One time binding: Igor');
|
2014-06-04 13:49:23 -07:00
|
|
|
|
expect(normalBinding.getText()).toEqual('Normal binding: Igor');
|
|
|
|
|
|
element(by.buttonText('Click Me')).click();
|
|
|
|
|
|
|
2017-02-01 11:28:56 -08:00
|
|
|
|
expect(oneTimeBinding.getText()).toEqual('One time binding: Igor');
|
2014-06-04 13:49:23 -07:00
|
|
|
|
expect(normalBinding.getText()).toEqual('Normal binding: Misko');
|
|
|
|
|
|
|
|
|
|
|
|
element(by.buttonText('Click Me')).click();
|
|
|
|
|
|
element(by.buttonText('Click Me')).click();
|
|
|
|
|
|
|
2017-02-01 11:28:56 -08:00
|
|
|
|
expect(oneTimeBinding.getText()).toEqual('One time binding: Igor');
|
2014-06-04 13:49:23 -07:00
|
|
|
|
expect(normalBinding.getText()).toEqual('Normal binding: Lucas');
|
|
|
|
|
|
});
|
|
|
|
|
|
</file>
|
|
|
|
|
|
</example>
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-12-05 19:42:57 +01:00
|
|
|
|
### Reasons for using one-time binding
|
2014-06-04 13:49:23 -07:00
|
|
|
|
|
|
|
|
|
|
The main purpose of one-time binding expression is to provide a way to create a binding
|
|
|
|
|
|
that gets deregistered and frees up resources once the binding is stabilized.
|
|
|
|
|
|
Reducing the number of expressions being watched makes the digest loop faster and allows more
|
|
|
|
|
|
information to be displayed at the same time.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### Value stabilization algorithm
|
|
|
|
|
|
|
|
|
|
|
|
One-time binding expressions will retain the value of the expression at the end of the
|
|
|
|
|
|
digest cycle as long as that value is not undefined. If the value of the expression is set
|
|
|
|
|
|
within the digest loop and later, within the same digest loop, it is set to undefined,
|
|
|
|
|
|
then the expression is not fulfilled and will remain watched.
|
|
|
|
|
|
|
2014-10-21 23:36:44 -03:00
|
|
|
|
1. Given an expression that starts with `::`, when a digest loop is entered and expression
|
|
|
|
|
|
is dirty-checked, store the value as V
|
|
|
|
|
|
2. If V is not undefined, mark the result of the expression as stable and schedule a task
|
2014-06-04 13:49:23 -07:00
|
|
|
|
to deregister the watch for this expression when we exit the digest loop
|
|
|
|
|
|
3. Process the digest loop as normal
|
2015-02-19 14:35:41 -07:00
|
|
|
|
4. When digest loop is done and all the values have settled, process the queue of watch
|
|
|
|
|
|
deregistration tasks. For each watch to be deregistered, check if it still evaluates
|
|
|
|
|
|
to a value that is not `undefined`. If that's the case, deregister the watch. Otherwise,
|
2014-06-04 13:49:23 -07:00
|
|
|
|
keep dirty-checking the watch in the future digest loops by following the same
|
|
|
|
|
|
algorithm starting from step 1
|
|
|
|
|
|
|
2015-05-29 14:56:19 -04:00
|
|
|
|
#### Special case for object literals
|
|
|
|
|
|
|
|
|
|
|
|
Unlike simple values, object-literals are watched until every key is defined.
|
|
|
|
|
|
See http://www.bennadel.com/blog/2760-one-time-data-bindings-for-object-literal-expressions-in-angularjs-1-3.htm
|
2014-06-04 13:49:23 -07:00
|
|
|
|
|
|
|
|
|
|
### How to benefit from one-time binding
|
|
|
|
|
|
|
2015-05-29 14:56:19 -04:00
|
|
|
|
If the expression will not change once set, it is a candidate for one-time binding.
|
2014-12-09 06:20:14 -08:00
|
|
|
|
Here are three example cases.
|
|
|
|
|
|
|
|
|
|
|
|
When interpolating text or attributes:
|
2014-06-04 13:49:23 -07:00
|
|
|
|
|
|
|
|
|
|
```html
|
2015-06-04 22:30:47 +02:00
|
|
|
|
<div name="attr: {{::color}}">text: {{::name | uppercase}}</div>
|
2014-06-04 13:49:23 -07:00
|
|
|
|
```
|
|
|
|
|
|
|
2015-06-04 22:30:47 +02:00
|
|
|
|
When using a directive with bidirectional binding and parameters that will not change:
|
2014-06-04 13:49:23 -07:00
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
|
someModule.directive('someDirective', function() {
|
|
|
|
|
|
return {
|
|
|
|
|
|
scope: {
|
|
|
|
|
|
name: '=',
|
|
|
|
|
|
color: '@'
|
|
|
|
|
|
},
|
|
|
|
|
|
template: '{{name}}: {{color}}'
|
|
|
|
|
|
};
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
```html
|
2014-11-12 11:22:06 +01:00
|
|
|
|
<div some-directive name="::myName" color="My color is {{::myColor}}"></div>
|
2014-06-04 13:49:23 -07:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-12-09 06:20:14 -08:00
|
|
|
|
When using a directive that takes an expression:
|
2014-06-04 13:49:23 -07:00
|
|
|
|
|
|
|
|
|
|
```html
|
|
|
|
|
|
<ul>
|
2015-06-04 22:30:47 +02:00
|
|
|
|
<li ng-repeat="item in ::items | orderBy:'name'">{{item.name}};</li>
|
2014-06-04 13:49:23 -07:00
|
|
|
|
</ul>
|
2015-07-26 16:39:51 +08:00
|
|
|
|
```
|