From d558dc5f95eb283e839aecc6b9de85baa589cb1a Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Sat, 5 Dec 2015 19:42:57 +0100 Subject: [PATCH] docs: reorganize information about interpolation - Move interpolation info from Directive guide into new interpolation guide - Add information about boolean attributes to interpolation guide - remove wroong examples from prefixed boolean attribute docs, link to interpolation guide instead - mention additional examples for attributes that benefit from ngAttr - add docs for ngRequired directive --- docs/content/guide/directive.ngdoc | 57 ---------- docs/content/guide/expression.ngdoc | 7 +- docs/content/guide/interpolation.ngdoc | 142 +++++++++++++++++++++++++ src/ng/compile.js | 3 +- src/ng/directive/attrs.js | 63 ++++------- src/ng/directive/validators.js | 58 +++++++++- 6 files changed, 225 insertions(+), 105 deletions(-) create mode 100644 docs/content/guide/interpolation.ngdoc diff --git a/docs/content/guide/directive.ngdoc b/docs/content/guide/directive.ngdoc index a277e5f7ee5d..6e0d9d1a32bc 100644 --- a/docs/content/guide/directive.ngdoc +++ b/docs/content/guide/directive.ngdoc @@ -141,63 +141,6 @@ directives when possible. - -### Text and attribute bindings - -During the compilation process the {@link ng.$compile compiler} matches text and attributes -using the {@link ng.$interpolate $interpolate} service to see if they contain embedded -expressions. These expressions are registered as {@link ng.$rootScope.Scope#$watch watches} -and will update as part of normal {@link ng.$rootScope.Scope#$digest digest} cycle. An -example of interpolation is shown below: - -```html -Hello {{username}}! -``` - - -### `ngAttr` attribute bindings - -Web browsers are sometimes picky about what values they consider valid for attributes. - -For example, considering this template: - -```html - - - -``` - -We would expect Angular to be able to bind to this, but when we check the console we see -something like `Error: Invalid value for attribute cx="{{cx}}"`. Because of the SVG DOM API's -restrictions, you cannot simply write `cx="{{cx}}"`. - -With `ng-attr-cx` you can work around this problem. - -If an attribute with a binding is prefixed with the `ngAttr` prefix (denormalized as `ng-attr-`) -then during the binding it will be applied to the corresponding unprefixed attribute. This allows -you to bind to attributes that would otherwise be eagerly processed by browsers -(e.g. an SVG element's `circle[cx]` attributes). When using `ngAttr`, the `allOrNothing` flag of -{@link ng.$interpolate $interpolate} is used, so if any expression in the interpolated string -results in `undefined`, the attribute is removed and not added to the element. - -For example, we could fix the example above by instead writing: - -```html - - - -``` - -If one wants to modify a camelcased attribute (SVG elements have valid camelcased attributes), such as `viewBox` on the `svg` element, one can use underscores to denote that the attribute to bind to is naturally camelcased. - -For example, to bind to `viewBox`, we can write: - -```html - - -``` - - ## Creating Directives First let's talk about the {@link ng.$compileProvider#directive API for registering directives}. Much like diff --git a/docs/content/guide/expression.ngdoc b/docs/content/guide/expression.ngdoc index b0e9816740ee..8e62fcf036fd 100644 --- a/docs/content/guide/expression.ngdoc +++ b/docs/content/guide/expression.ngdoc @@ -5,8 +5,9 @@ # Angular Expressions -Angular expressions are JavaScript-like code snippets that are usually placed in bindings such as -`{{ expression }}`. +Angular expressions are JavaScript-like code snippets that are mainly placed in +interpolation bindings such as `{{ textBinding }}`, +but also used directly in directive attributes such as `ng-click="functionExpression()"`. For example, these are valid expressions in Angular: @@ -282,7 +283,7 @@ result is a non-undefined value (see value stabilization algorithm below). -### Why this feature +### Reasons for using one-time binding 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. diff --git a/docs/content/guide/interpolation.ngdoc b/docs/content/guide/interpolation.ngdoc new file mode 100644 index 000000000000..2b53da63124d --- /dev/null +++ b/docs/content/guide/interpolation.ngdoc @@ -0,0 +1,142 @@ +@ngdoc overview +@name Interpolation +@sortOrder 275 +@description + +# Interpolation and data-binding + +Interpolation markup with embedded @link {guide/expressions expressions} is used by Angular to +provide data-binding to text nodes and attribute values. + +An example of interpolation is shown below: + +```html +Hello {{username}}! +``` + +### How text and attribute bindings work + +During the compilation process the {@link ng.$compile compiler} uses the {@link ng.$interpolate $interpolate} +service to see if text nodes and element attributes contain interpolation markup with embedded expressions. + +If that is the case, the compiler adds an interpolateDirective to the node and +registers {@link ng.$rootScope.Scope#$watch watches} on the computed interpolation function, +which will update the corresponding text nodes or attribute values as part of the +normal {@link ng.$rootScope.Scope#$digest digest} cycle. + +Note that the interpolateDirective has a priority of 100 and sets up the watch in the preLink function. + +### Binding to boolean attributes + +Attributes such as `disabled` are called `boolean` attributes, because their presence means `true` and +their absence means `false`. We cannot use normal attribute bindings with them, because the HTML +specification does not require browsers to preserve the values of boolean attributes. This means that +if we put an Angular interpolation expression into such an attribute then the binding information +would be lost, because the browser ignores the attribute value. + +In the following example, the interpolation information would be ignored and the browser would simply +interpret the attribute as present, meaning that the button would always be disabled. + + ```html + Disabled: + +``` + +For this reason, Angular provides special `ng`-prefixed directives for the following boolean attributes: +{@link ngDisabled `disabled`}, [@link ngRequired `required`}, [@link ngSelected `selected`}, +{@link ngChecked `checked`}, {@link ngReadonly `readOnly`} , and [@link ngOpen `open`}. + +These directives take an expression inside the attribute, and set the corresponding boolean attribute +to true when the expression evaluates to truthy. + + ```html + Disabled: + +``` + +### `ngAttr` for binding to arbitrary attributes + +Web browsers are sometimes picky about what values they consider valid for attributes. + +For example, considering this template: + +```html + + + +``` + +We would expect Angular to be able to bind to this, but when we check the console we see +something like `Error: Invalid value for attribute cx="{{cx}}"`. Because of the SVG DOM API's +restrictions, you cannot simply write `cx="{{cx}}"`. + +With `ng-attr-cx` you can work around this problem. + +If an attribute with a binding is prefixed with the `ngAttr` prefix (denormalized as `ng-attr-`) +then during the binding it will be applied to the corresponding unprefixed attribute. This allows +you to bind to attributes that would otherwise be eagerly processed by browsers +(e.g. an SVG element's `circle[cx]` attributes). When using `ngAttr`, the `allOrNothing` flag of +{@link ng.$interpolate $interpolate} is used, so if any expression in the interpolated string +results in `undefined`, the attribute is removed and not added to the element. + +For example, we could fix the example above by instead writing: + +```html + + + +``` + +If one wants to modify a camelcased attribute (SVG elements have valid camelcased attributes), +such as `viewBox` on the `svg` element, one can use underscores to denote that the attribute to bind +to is naturally camelcased. + +For example, to bind to `viewBox`, we can write: + +```html + + +``` + +The following attributes are also known to cause problems when used with normal bindings: + +- **size** in `