mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-16 23:30:23 +00:00
docs(expression): rewrite
This commit is contained in:
parent
dd38ce6585
commit
41d26db32c
2 changed files with 68 additions and 93 deletions
|
|
@ -1,38 +1,41 @@
|
|||
@ngdoc overview
|
||||
@name Developer Guide: Understanding Angular Expressions
|
||||
@name Developer Guide: Expressions
|
||||
@description
|
||||
|
||||
Expressions are {@link dev_guide.templates.databinding bindings} that you write in HTML and embed
|
||||
in templates in order to create views in angular. Angular expressions are similar but not
|
||||
equivalent to JavaScript expressions.
|
||||
Expressions are JavaScript-like code snippets that are usually placed in bindings such as `{{
|
||||
expression }}`. Expressions are process by the {@link api/angular.module.ng.$parse $parse}
|
||||
service.
|
||||
|
||||
For example, these are all valid expressions in angular:
|
||||
|
||||
* `1+2={{1+2}}`
|
||||
* `3*10|currency`
|
||||
* `Hello {{name}}!`
|
||||
* `Hello {{'World'}}!`
|
||||
* `1+2`
|
||||
* `3*10 | currency`
|
||||
* `user.name`
|
||||
|
||||
|
||||
## Angular Expressions vs. JS Expressions
|
||||
|
||||
It might be tempting to think of angular view expressions as JavaScript expressions, but that is
|
||||
not entirely correct. Angular does not use a simple JavaScript eval of the expression text. You can
|
||||
think of angular expressions as JavaScript expressions with these differences:
|
||||
not entirely correct, since angular does not use a JavaScript `eval()` to evaluate expressions.
|
||||
You can think of angular expressions as JavaScript expressions with following differences
|
||||
differences:
|
||||
|
||||
* **Attribute Evaluation:** evaluation of all attributes are against the current scope, not to the
|
||||
global window as in JavaScript.
|
||||
* **Forgiving:** expression evaluation is forgiving to undefined and null, unlike in JavaScript.
|
||||
* **No Control Flow Statements:** you cannot do the following from an angular expression:
|
||||
conditionals, loops, or throw.
|
||||
* **Type Augmentation:** the scope expression evaluator augments built-in types.
|
||||
* **Filters:** you can add filters to an expression, for example to convert raw data into a
|
||||
human-readable format.
|
||||
* **The $:** angular reserves this prefix to differentiate its API names from others.
|
||||
* **Attribute Evaluation:** evaluation of all properties are against the scope, doing the
|
||||
evaluation, unlike in JavaScript where the expressions are evaluated against the global
|
||||
`window`.
|
||||
|
||||
* **Forgiving:** expression evaluation is forgiving to undefined and null, unlike in JavaScript,
|
||||
where such evaluations generate `NullPointerExceptions`.
|
||||
|
||||
* **No Control Flow Statements:** you cannot do any of the following in angular expression:
|
||||
conditionals, loops, or throw.
|
||||
|
||||
* **Filters:** you can pass result of expression evaluations through filter chains. For example
|
||||
to convert date object into a local specific human-readable format.
|
||||
|
||||
If, on the other hand, you do want to run arbitrary JavaScript code, you should make it a
|
||||
controller method and call that. If you want to `eval()` an angular expression from JavaScript, use
|
||||
the `Scope:$eval()` method.
|
||||
controller method and call the method. If you want to `eval()` an angular expression from
|
||||
JavaScript, use the {@link api/angular.module.ng.$rootScope.Scope#$eval `$eval()`} method.
|
||||
|
||||
## Example
|
||||
<doc:example>
|
||||
|
|
@ -86,13 +89,13 @@ You can try evaluating different expressions here:
|
|||
</doc:example>
|
||||
|
||||
|
||||
# Attribute Evaluation
|
||||
# Property Evaluation
|
||||
|
||||
Evaluation of all attributes takes place against the current scope. Unlike JavaScript, where names
|
||||
default to global window properties, angular expressions have to use `$window` to refer to the
|
||||
global object. For example, if you want to call `alert()`, which is defined on `window`, an
|
||||
expression must use `$window.alert()`. This is done intentionally to prevent accidental access to
|
||||
the global state (a common source of subtle bugs).
|
||||
Evaluation of all properties takes place against a scope. Unlike JavaScript, where names default
|
||||
to global window properties, angular expressions have to use {@link api/angular.module.ng.$window
|
||||
`$window`} to refer to the global `window` object. For example, if you want to call `alert()`, which is
|
||||
defined on `window`, in an expression must use `$window.alert()`. This is done intentionally to
|
||||
prevent accidental access to the global state (a common source of subtle bugs).
|
||||
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
|
|
@ -141,68 +144,14 @@ forgiving we'd have to write bindings that clutter the code, for example: `{{((a
|
|||
|
||||
Similarly, invoking a function `a.b.c()` on undefined or null simply returns undefined.
|
||||
|
||||
Assignments work the same way in reverse:
|
||||
|
||||
a.b.c = 10
|
||||
|
||||
...creates the intermediary objects even if a is 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 in the view. If you need a
|
||||
conditional (including ternary operators), loop, or to throw from a view expression, delegate to a
|
||||
JavaScript method instead.
|
||||
conditional, loop, or to throw from a view expression, delegate to a JavaScript method instead.
|
||||
|
||||
|
||||
## Type Augmentation
|
||||
|
||||
Built-in types have methods like `[].push()`, but the richness of these methods is limited.
|
||||
Consider the example below, which allows you to do a simple search over a canned set of contacts.
|
||||
The example would be much more complicated if we did not have the `Array:$filter()`. There is no
|
||||
built-in method on `Array` called {@link api/angular.module.ng.$filter.filter $filter} and angular doesn't add
|
||||
it to `Array.prototype` because that could collide with other JavaScript frameworks.
|
||||
|
||||
For this reason the scope expression evaluator augments the built-in types to make them act like
|
||||
they have extra methods. The actual method for `$filter()` is `angular.module.ng.$filter.filter()`. You can
|
||||
call it from JavaScript.
|
||||
|
||||
Extensions: You can further extend the expression vocabulary by adding new methods to
|
||||
`angular.module.ng.$filter` or `angular.String`, etc.
|
||||
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<div ng-init="friends = [
|
||||
{name:'John', phone:'555-1212'},
|
||||
{name:'Mary', phone:'555-9876'},
|
||||
{name:'Mike', phone:'555-4321'},
|
||||
{name:'Adam', phone:'555-5678'},
|
||||
{name:'Julie', phone:'555-8765'}]"></div>
|
||||
Search: <input ng-model="searchText"/>
|
||||
<table class="example3">
|
||||
<thead>
|
||||
<tr><th>Name</th><th>Phone</th><tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="friend in friends | filter:searchText">
|
||||
<td>{{friend.name}}</td>
|
||||
<td>{{friend.phone}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should filter the list', function() {
|
||||
var tr = using('table.example3 tbody').repeater('tr');
|
||||
expect(tr.count()).toBe(5);
|
||||
input('searchText').enter('a');
|
||||
expect(tr.count()).toBe(2);
|
||||
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
|
||||
## Filters
|
||||
|
||||
When presenting data to the user, you might need to convert the data from its raw format to a
|
||||
|
|
@ -212,14 +161,15 @@ of filters like this:
|
|||
|
||||
name | uppercase
|
||||
|
||||
The expression evaluator simply passes the value of name to angular.module.ng.$filter.uppercase.
|
||||
The expression evaluator simply passes the value of name to {@link
|
||||
api/angular.module.ng.$filter.uppercase `uppercase`} filter.
|
||||
|
||||
Chain filters using this syntax:
|
||||
|
||||
value | filter1 | filter2
|
||||
|
||||
You can also pass colon-delimited arguments to filters, for example, to display the number 123 with
|
||||
2 decimal points:
|
||||
You can also pass colon-delimited arguments to filters, for example, to display the number 123
|
||||
with 2 decimal points:
|
||||
|
||||
123 | number:2
|
||||
|
||||
|
|
@ -235,11 +185,3 @@ property and then we would have a collision. This problem exists because angular
|
|||
objects with additional behavior. By prefixing its additions with $ we are reserving our namespace
|
||||
so that angular developers and developers who use angular can develop in harmony without collisions.
|
||||
|
||||
|
||||
## Related Topics
|
||||
|
||||
* {@link dev_guide.templates.filters Understanding Angular Filters}
|
||||
|
||||
## Related API
|
||||
|
||||
* {@link api/angular.module.ng.$compile Angular Compiler API}
|
||||
|
|
@ -807,6 +807,39 @@ function getterFn(path, csp) {
|
|||
|
||||
///////////////////////////////////
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name angular.module.ng.$parse
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
*
|
||||
* Converts Angular {@link guid/expression expression} into a function.
|
||||
*
|
||||
* <pre>
|
||||
* var getter = $parse('user.name');
|
||||
* var setter = getter.assign;
|
||||
* var context = {user:{name:'angular'}};
|
||||
* var locals = {user:{name:'local'}};
|
||||
*
|
||||
* expect(getter(context)).toEqual('angular');
|
||||
* setter(context, 'newValue');
|
||||
* expect(context.user.name).toEqual('newValue');
|
||||
* expect(getter(context, locals)).toEqual('local');
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @param {string} expression String expression to compile.
|
||||
* @returns {function(context, locals)} a function which represents the compiled expression:
|
||||
*
|
||||
* * `context`: an object against which any expressions embedded in the strings are evaluated
|
||||
* against (Topically a scope object).
|
||||
* * `locals`: local variables context object, useful for overriding values in `context`.
|
||||
*
|
||||
* The return function also has an `assign` property, if the expression is assignable, which
|
||||
* allows one to set values to expressions.
|
||||
*
|
||||
*/
|
||||
function $ParseProvider() {
|
||||
var cache = {};
|
||||
this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue