From 41d26db32c1c013dd33faa03df85e38681a9ebb1 Mon Sep 17 00:00:00 2001 From: Misko Hevery Date: Tue, 28 Feb 2012 14:29:58 -0800 Subject: docs(expression): rewrite --- docs/content/guide/dev_guide.expressions.ngdoc | 245 ------------------------- 1 file changed, 245 deletions(-) delete mode 100644 docs/content/guide/dev_guide.expressions.ngdoc (limited to 'docs/content/guide/dev_guide.expressions.ngdoc') diff --git a/docs/content/guide/dev_guide.expressions.ngdoc b/docs/content/guide/dev_guide.expressions.ngdoc deleted file mode 100644 index c54a9343..00000000 --- a/docs/content/guide/dev_guide.expressions.ngdoc +++ /dev/null @@ -1,245 +0,0 @@ -@ngdoc overview -@name Developer Guide: Understanding Angular 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. - -For example, these are all valid expressions in angular: - -* `1+2={{1+2}}` -* `3*10|currency` -* `Hello {{name}}!` -* `Hello {{'World'}}!` - - -## 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. - -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. - -## Example - - - 1+2={{1+2}} - - - it('should calculate expression in binding', function() { - expect(binding('1+2')).toEqual('3'); - }); - - - -You can try evaluating different expressions here: - - - - -
- Expression: - - -
    -
  • - [ X ] - {{expr}} => -
  • -
-
-
- - 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"]); - }); - -
- - -# Attribute 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). - - - - -
- Name: - -
-
- - 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'); - }); - -
- -## 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}}` - -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. - - - -
- Search: - - - - - - - - - - -
NamePhone
{{friend.name}}{{friend.phone}}
-
- - 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); - - }); - -
- -## Filters - -When presenting data to the user, you might need to convert the data from its raw format to a -user-friendly format. For example, you might have a data object that needs to be formatted -according to the locale before displaying it to the user. You can pass expressions through a chain -of filters like this: - - name | uppercase - -The expression evaluator simply passes the value of name to angular.module.ng.$filter.uppercase. - -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: - - 123 | number:2 - -# The $ - -You might be wondering, what is the significance of the $ prefix? It is simply a prefix that -angular uses, to differentiate its API names from others. If angular didn't use $, then evaluating -`a.length()` would return undefined because neither a nor angular define such a property. - -Consider that in a future version of angular we might choose to add a length method, in which case -the behavior of the expression would change. Worse yet, you the developer could create a length -property and then we would have a collision. This problem exists because angular augments existing -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} -- cgit v1.2.3