aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/content/guide/expression.ngdoc (renamed from docs/content/guide/dev_guide.expressions.ngdoc)130
-rw-r--r--src/ng/parse.js33
2 files changed, 69 insertions, 94 deletions
diff --git a/docs/content/guide/dev_guide.expressions.ngdoc b/docs/content/guide/expression.ngdoc
index c54a9343..f92dbe48 100644
--- a/docs/content/guide/dev_guide.expressions.ngdoc
+++ b/docs/content/guide/expression.ngdoc
@@ -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:
-
-* **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.
+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 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,67 +144,13 @@ 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.
-
-
-## 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.
+conditional, loop, or to throw from a view expression, delegate to a JavaScript method instead.
-<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
@@ -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}
diff --git a/src/ng/parse.js b/src/ng/parse.js
index 294e2c8d..55b0c67c 100644
--- a/src/ng/parse.js
+++ b/src/ng/parse.js
@@ -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) {