2014-12-08 17:29:04 -05:00
|
|
|
# Templates
|
|
|
|
|
2015-02-15 22:06:53 -05:00
|
|
|
Templates are markup which is added to HTML to declaratively describe how the application model should be
|
2014-12-08 17:29:04 -05:00
|
|
|
projected to DOM as well as which DOM events should invoke which methods on the controller. Templates contain
|
|
|
|
syntax which is core to Angular and allows for data-binding, event-binding, template-instantiation.
|
|
|
|
|
2015-02-14 14:06:20 -05:00
|
|
|
The design of the template syntax has these properties:
|
2015-04-29 18:07:55 -04:00
|
|
|
|
2014-12-08 17:29:04 -05:00
|
|
|
|
2015-02-14 14:06:20 -05:00
|
|
|
* All data-binding expressions are easily identifiable. (i.e. there is never an ambiguity whether the value should be
|
2014-12-08 17:29:04 -05:00
|
|
|
interpreted as string literal or as an expression.)
|
2015-02-09 02:02:41 -05:00
|
|
|
* All events and their statements are easily identifiable.
|
2014-12-08 17:29:04 -05:00
|
|
|
* All places of DOM instantiation are easily identifiable.
|
2015-02-15 22:06:53 -05:00
|
|
|
* All places of variable declaration are easily identifiable.
|
2014-12-08 17:29:04 -05:00
|
|
|
|
2015-02-15 22:06:53 -05:00
|
|
|
The above properties guarantee that the templates are easy to parse by tools (such as IDEs) and reason about by people.
|
|
|
|
At no point is it necessary to understand which directives are active or what their semantics are in order to reason
|
2014-12-08 17:29:04 -05:00
|
|
|
about the template runtime characteristics.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Summary
|
|
|
|
|
|
|
|
Below is a summary of the kinds of syntaxes which Angular templating supports. The syntaxes are explained in more
|
2015-02-14 14:06:20 -05:00
|
|
|
detail in the following sections.
|
2014-12-08 17:29:04 -05:00
|
|
|
|
|
|
|
<table>
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th>Description</th><th>Short</th><th>Canonical</th>
|
|
|
|
</tr>
|
2015-02-17 17:22:03 -05:00
|
|
|
</thead>
|
2014-12-08 17:29:04 -05:00
|
|
|
<tbody>
|
|
|
|
<tr>
|
|
|
|
<th>Text Interpolation</th>
|
|
|
|
<td>
|
2015-02-17 17:22:03 -05:00
|
|
|
<pre>
|
|
|
|
```
|
2015-02-13 12:04:03 -05:00
|
|
|
<div>{{exp}}</div>
|
|
|
|
```
|
2015-02-17 17:22:03 -05:00
|
|
|
</pre>
|
2014-12-08 17:29:04 -05:00
|
|
|
|
|
|
|
Example:
|
2015-02-17 17:22:03 -05:00
|
|
|
<pre>
|
|
|
|
```
|
2014-12-08 17:29:04 -05:00
|
|
|
<div>
|
|
|
|
Hello {{name}}!
|
|
|
|
<br>
|
|
|
|
Goodbye {{name}}!
|
|
|
|
</div>
|
|
|
|
```
|
2015-02-17 17:22:03 -05:00
|
|
|
</pre>
|
2014-12-08 17:29:04 -05:00
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
`<div [text|index]=exp>`
|
|
|
|
|
|
|
|
Example:
|
2015-02-17 17:22:03 -05:00
|
|
|
<pre>
|
|
|
|
```
|
2014-12-08 17:29:04 -05:00
|
|
|
<div
|
|
|
|
[text|0]=" 'Hello' + stringify(name) + '!' "
|
|
|
|
[text|2]=" 'Goodbye' + stringify(name) + '!' ">
|
|
|
|
_<b>x</b>_
|
|
|
|
</div>
|
|
|
|
```
|
2015-02-17 17:22:03 -05:00
|
|
|
</pre>
|
2014-12-08 17:29:04 -05:00
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<th>Property Interpolation</th>
|
|
|
|
<td>
|
2015-02-17 17:22:03 -05:00
|
|
|
<pre>
|
|
|
|
```
|
2015-02-13 12:04:03 -05:00
|
|
|
<div name="{{exp}}">
|
|
|
|
```
|
2015-02-17 17:22:03 -05:00
|
|
|
</pre>
|
2014-12-08 17:29:04 -05:00
|
|
|
|
|
|
|
Example:
|
|
|
|
|
2015-02-17 17:22:03 -05:00
|
|
|
<pre>
|
|
|
|
```
|
2015-02-13 12:04:03 -05:00
|
|
|
<div class="{{selected}}">`
|
|
|
|
```
|
2015-02-17 17:22:03 -05:00
|
|
|
</pre>
|
2014-12-08 17:29:04 -05:00
|
|
|
</td>
|
|
|
|
<td>
|
2015-02-17 17:22:03 -05:00
|
|
|
<pre>
|
|
|
|
```
|
2015-02-13 12:04:03 -05:00
|
|
|
<div [name]="stringify(exp)">
|
|
|
|
```
|
2015-02-17 17:22:03 -05:00
|
|
|
</pre>
|
2014-12-08 17:29:04 -05:00
|
|
|
|
|
|
|
Example:
|
|
|
|
|
2015-02-17 17:22:03 -05:00
|
|
|
<pre>
|
|
|
|
```
|
2015-02-13 12:04:03 -05:00
|
|
|
<div [class]="stringify(selected)">
|
|
|
|
```
|
2015-02-17 17:22:03 -05:00
|
|
|
</pre>
|
2014-12-08 17:29:04 -05:00
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<th>Property binding</th>
|
|
|
|
<td>
|
|
|
|
`<div [prop]="exp">`
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
|
|
`<div [hidden]="true">`
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
`<div bind-prop="exp">`
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
|
|
`<div bind-hidden="true">`
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<th>Event binding (non-bubbling)</th>
|
|
|
|
<td>
|
|
|
|
`<div (event)="statement">`
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
|
|
`<div (click)="doX()">`
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
`<div on-event="statement">`
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
|
|
`<div on-click="doX()">`
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<th>Event binding (bubbling)</th>
|
|
|
|
<td>
|
|
|
|
`<div (^event)="statement">`
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
|
|
`<div (^mouseover)="hlite()">`
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
`<div on-bubble-event="statement">`
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
|
|
`<div on-bubble-mouseover="hlite()">`
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<th>Declare reference</th>
|
|
|
|
<td>
|
|
|
|
`<div #symbol>`
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
2015-02-17 17:22:03 -05:00
|
|
|
<pre>
|
2014-12-08 17:29:04 -05:00
|
|
|
```
|
|
|
|
<video #player>
|
|
|
|
<button (click)="player.play()">play</button>
|
|
|
|
```
|
2015-02-17 17:22:03 -05:00
|
|
|
</pre>
|
2014-12-08 17:29:04 -05:00
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
`<div def="symbol">`
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
2015-02-17 17:22:03 -05:00
|
|
|
<pre>
|
2014-12-08 17:29:04 -05:00
|
|
|
```
|
|
|
|
<video def="player">
|
|
|
|
<button on-click="player.play()">play</button>
|
|
|
|
```
|
2015-02-17 17:22:03 -05:00
|
|
|
</pre>
|
2014-12-08 17:29:04 -05:00
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<th>Inline Template</th>
|
|
|
|
<td>
|
|
|
|
`<div template="...">...</div>`
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
2015-02-17 17:22:03 -05:00
|
|
|
<pre>
|
2014-12-08 17:29:04 -05:00
|
|
|
```
|
|
|
|
<ul>
|
2015-03-19 09:31:41 -04:00
|
|
|
<li template="for: #item of items">
|
2014-12-08 17:29:04 -05:00
|
|
|
{{item}}
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
```
|
2015-02-17 17:22:03 -05:00
|
|
|
</pre>
|
2014-12-08 17:29:04 -05:00
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
`<template>...</template>`
|
|
|
|
|
|
|
|
Example:
|
2015-02-17 17:22:03 -05:00
|
|
|
<pre>
|
2014-12-08 17:29:04 -05:00
|
|
|
```
|
|
|
|
<ul>
|
2015-03-19 09:31:41 -04:00
|
|
|
<template def-for:"item"
|
|
|
|
bind-for-in="items">
|
2014-12-08 17:29:04 -05:00
|
|
|
<li>
|
|
|
|
{{item}}
|
|
|
|
</li>
|
|
|
|
</template>
|
|
|
|
</ul>
|
|
|
|
```
|
2015-02-17 17:22:03 -05:00
|
|
|
</pre>
|
2014-12-08 17:29:04 -05:00
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<th>Explicit Template</th>
|
|
|
|
<td>
|
|
|
|
`<template>...</template>`
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
2015-02-17 17:22:03 -05:00
|
|
|
<pre>
|
2014-12-08 17:29:04 -05:00
|
|
|
```
|
2015-03-19 09:31:41 -04:00
|
|
|
<template #for="item"
|
|
|
|
[for-in]="items">
|
2014-12-08 17:29:04 -05:00
|
|
|
_some_content_to_repeat_
|
|
|
|
</template>
|
|
|
|
```
|
2015-02-17 17:22:03 -05:00
|
|
|
</pre>
|
2014-12-08 17:29:04 -05:00
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
`<template>...</template>`
|
|
|
|
|
|
|
|
Example:
|
2015-02-17 17:22:03 -05:00
|
|
|
<pre>
|
2014-12-08 17:29:04 -05:00
|
|
|
```
|
2015-03-19 09:31:41 -04:00
|
|
|
<template def-for="item"
|
|
|
|
bind-for-in="items">
|
2014-12-08 17:29:04 -05:00
|
|
|
_some_content_to_repeat_
|
|
|
|
</template>
|
|
|
|
```
|
2015-02-17 17:22:03 -05:00
|
|
|
</pre>
|
2014-12-08 17:29:04 -05:00
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Property Binding
|
|
|
|
|
2015-02-14 14:06:20 -05:00
|
|
|
Binding application model data to the UI is the most common kind of bindings in an Angular application. The bindings
|
2014-12-08 17:29:04 -05:00
|
|
|
are always in the form of `property-name` which is assigned an `expression`. The generic form is:
|
|
|
|
|
|
|
|
<table>
|
|
|
|
<tr>
|
|
|
|
<th>Short form</th>
|
|
|
|
<td>`<some-element [some-property]="expression">`</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<th>Canonical form</th>
|
|
|
|
<td>`<some-element bind-some-property="expression">`</td>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
|
|
|
|
|
|
|
|
Where:
|
|
|
|
* `some-element` can be any existing DOM element.
|
|
|
|
* `some-property` (escaped with `[]` or `bind-`) is the name of the property on `some-element`. In this case the
|
|
|
|
dash-case is converted into camel-case `someProperty`.
|
|
|
|
* `expression` is a valid expression (as defined in section below).
|
|
|
|
|
|
|
|
Example:
|
|
|
|
```
|
|
|
|
<div [title]="user.firstName">
|
|
|
|
```
|
|
|
|
|
|
|
|
In the above example the `title` property of the `div` element will be updated whenever the `user.firstName` changes
|
|
|
|
its value.
|
|
|
|
|
|
|
|
Key points:
|
|
|
|
* The binding is to the element property not the element attribute.
|
2015-02-14 14:06:20 -05:00
|
|
|
* To prevent custom element from accidentally reading the literal `expression` on the title element, the attribute name
|
|
|
|
is escaped. In our case the `title` is escaped to `[title]` through the addition of square brackets `[]`.
|
2015-04-14 21:53:58 -04:00
|
|
|
* A binding value (in this case `user.firstName` will always be an expression, never a string literal).
|
2014-12-08 17:29:04 -05:00
|
|
|
|
|
|
|
NOTE: Unlike Angular v1, Angular v2 binds to properties of elements rather than attributes of elements. This is
|
2015-02-14 14:06:20 -05:00
|
|
|
done to better support custom elements, and to allow binding for values other than strings.
|
2014-12-08 17:29:04 -05:00
|
|
|
|
2015-02-14 14:06:20 -05:00
|
|
|
NOTE: Some editors/server side pre-processors may have trouble generating `[]` around the attribute name. For this
|
2014-12-08 17:29:04 -05:00
|
|
|
reason Angular also supports a canonical version which is prefixed using `bind-`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### String Interpolation
|
|
|
|
|
2015-02-14 14:06:20 -05:00
|
|
|
Property bindings are the only data bindings which Angular supports, but for convenience Angular supports an interpolation
|
2014-12-08 17:29:04 -05:00
|
|
|
syntax which is just a short hand for the data binding syntax.
|
|
|
|
|
|
|
|
```
|
|
|
|
<span>Hello {{name}}!</span>
|
|
|
|
```
|
|
|
|
|
|
|
|
is a short hand for:
|
|
|
|
|
|
|
|
```
|
|
|
|
<span [text|0]=" 'Hello ' + stringify(name) + '!' ">_</span>
|
|
|
|
```
|
|
|
|
|
2015-02-14 14:06:20 -05:00
|
|
|
The above says to bind the `'Hello ' + stringify(name) + '!'` expression to the zero-th child of the `span`'s `text`
|
2014-12-08 17:29:04 -05:00
|
|
|
property. The index is necessary in case there are more than one text nodes, or if the text node we wish to bind to
|
|
|
|
is not the first one.
|
|
|
|
|
|
|
|
Similarly the same rules apply to interpolation inside attributes.
|
|
|
|
|
|
|
|
```
|
|
|
|
<span title="Hello {{name}}!"></span>
|
|
|
|
```
|
|
|
|
|
|
|
|
is a short hand for:
|
|
|
|
|
|
|
|
```
|
|
|
|
<span [title]=" 'Hello ' + stringify(name) + '!' "></span>
|
|
|
|
```
|
|
|
|
|
|
|
|
NOTE: `stringify()` is a built in implicit function which converts its argument to a string representation, while
|
|
|
|
keeping `null` and `undefined` as empty strings.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-02-14 14:06:20 -05:00
|
|
|
## Local Variables
|
2014-12-08 17:29:04 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Inline Templates
|
|
|
|
|
|
|
|
Data binding allows updating the DOM's properties, but it does not allow for changing of the DOM structure. To change
|
2015-02-09 02:02:41 -05:00
|
|
|
DOM structure we need the ability to define child templates, and then instantiate these templates into Views. The
|
2015-02-14 14:06:20 -05:00
|
|
|
Views than can be inserted and removed as needed to change the DOM structure.
|
2014-12-08 17:29:04 -05:00
|
|
|
|
|
|
|
<table>
|
|
|
|
<tr>
|
|
|
|
<th>Short form</th>
|
|
|
|
<td>
|
|
|
|
```
|
|
|
|
parent template
|
|
|
|
<element>
|
|
|
|
<some-element template="instantiating-directive-microsyntax">child template</some-element>
|
|
|
|
</element>
|
|
|
|
```
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<th>Canonical form</th>
|
|
|
|
<td>
|
|
|
|
```
|
|
|
|
parent template
|
|
|
|
<element>
|
|
|
|
<template instantiating-directive-bindings>
|
|
|
|
<some-element>child template</some-element>
|
|
|
|
</template>
|
|
|
|
</element>
|
|
|
|
```
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
|
|
|
|
Where:
|
|
|
|
* `template` defines a child template and designates the anchor where Views (instances of the template) will be
|
|
|
|
inserted. The template can be defined implicitly with `template` attribute, which turns the current element into
|
|
|
|
a template, or explicitly with `<template>` element. Explicit declaration is longer, but it allows for having
|
|
|
|
templates which have more than one root DOM node.
|
2015-04-29 18:07:55 -04:00
|
|
|
* `viewport` is required for templates. The directive is responsible for deciding when
|
|
|
|
and in which order should child views be inserted into this location. Such a directive usually has one or
|
2015-02-15 22:06:53 -05:00
|
|
|
more bindings and can be represented as either `viewport-directive-bindings` or
|
|
|
|
`viewport-directive-microsyntax` on `template` element or attribute. See template microsyntax for more details.
|
2014-12-08 17:29:04 -05:00
|
|
|
|
|
|
|
|
|
|
|
Example of conditionally included template:
|
|
|
|
|
|
|
|
```
|
|
|
|
Hello {{user}}!
|
2015-02-14 14:06:20 -05:00
|
|
|
<div template="if: isAdministrator">
|
2014-12-08 17:29:04 -05:00
|
|
|
...administrator menu here...
|
|
|
|
</div>
|
|
|
|
```
|
|
|
|
|
2015-04-29 18:07:55 -04:00
|
|
|
In the above example the `if` directive determines whether the child view (an instance of the child template) should be
|
2015-02-14 14:06:20 -05:00
|
|
|
inserted into the root view. The `if` makes this decision based on if the `isAdministrator` binding is true.
|
2014-12-08 17:29:04 -05:00
|
|
|
|
2015-02-14 14:06:20 -05:00
|
|
|
The above example is in the short form, for better clarity let's rewrite it in the canonical form, which is functionally
|
2014-12-08 17:29:04 -05:00
|
|
|
identical.
|
|
|
|
|
|
|
|
```
|
|
|
|
Hello {{user}}!
|
2015-02-14 14:06:20 -05:00
|
|
|
<template [if]="isAdministrator">
|
2014-12-08 17:29:04 -05:00
|
|
|
<div>
|
|
|
|
...administrator menu here...
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Template Microsyntax
|
|
|
|
|
2015-02-09 02:02:41 -05:00
|
|
|
Often times it is necessary to encode a lot of different bindings into a template to control how the instantiation
|
2015-03-19 09:31:41 -04:00
|
|
|
of the templates occurs. One such example is `for`.
|
2014-12-08 17:29:04 -05:00
|
|
|
|
|
|
|
```
|
|
|
|
<form #foo=form>
|
|
|
|
</form>
|
|
|
|
<ul>
|
2015-03-19 09:31:41 -04:00
|
|
|
<template for #person [in]="people" #i="index">
|
2015-02-09 16:44:42 -05:00
|
|
|
<li>{{i}}. {{person}}<li>
|
2014-12-08 17:29:04 -05:00
|
|
|
</template>
|
|
|
|
</ul>
|
|
|
|
```
|
|
|
|
|
|
|
|
Where:
|
2015-03-19 09:31:41 -04:00
|
|
|
* `for` triggers the for directive.
|
|
|
|
* `[in]="people"` binds an iterable object to the `for` controller.
|
|
|
|
* `#person` exports the implicit `for` item.
|
2014-12-08 17:29:04 -05:00
|
|
|
* `#i=index` exports item index as `i`.
|
|
|
|
|
2015-02-15 22:06:53 -05:00
|
|
|
The above example is explicit but quite wordy. For this reason in most situations a short hand version of the
|
2015-02-09 02:02:41 -05:00
|
|
|
syntax is preferable.
|
2014-12-08 17:29:04 -05:00
|
|
|
|
|
|
|
```
|
|
|
|
<ul>
|
2015-04-26 00:36:51 -04:00
|
|
|
<li template="for; #person; of=people; #i=index;">{{i}}. {{person}}<li>
|
2014-12-08 17:29:04 -05:00
|
|
|
</ul>
|
|
|
|
```
|
|
|
|
|
2015-02-14 14:06:20 -05:00
|
|
|
Notice how each key value pair is translated to a `key=value;` statement in the `template` attribute. This makes the
|
2015-02-09 02:02:41 -05:00
|
|
|
repeat syntax a much shorter, but we can do better. Turns out that most punctuation is optional in the short version
|
2014-12-08 17:29:04 -05:00
|
|
|
which allows us to further shorten the text.
|
|
|
|
|
|
|
|
```
|
|
|
|
<ul>
|
2015-03-19 09:31:41 -04:00
|
|
|
<li template="for #person of people #i=index">{{i}}. {{person}}<li>
|
2014-12-08 17:29:04 -05:00
|
|
|
</ul>
|
|
|
|
```
|
|
|
|
|
2015-03-19 09:31:41 -04:00
|
|
|
We can also optionally use `var` instead of `#` and add `:` to `for` which creates the following recommended
|
|
|
|
microsyntax for `for`.
|
2014-12-08 17:29:04 -05:00
|
|
|
|
|
|
|
```
|
|
|
|
<ul>
|
2015-03-19 09:31:41 -04:00
|
|
|
<li template="for: var person of people; var i=index">{{i}}. {{person}}<li>
|
2014-12-08 17:29:04 -05:00
|
|
|
</ul>
|
|
|
|
```
|
|
|
|
|
2015-03-19 09:31:41 -04:00
|
|
|
Finally, we can move the `for` keyword to the left hand side and prefix it with `*` as so:
|
|
|
|
|
|
|
|
```
|
|
|
|
<ul>
|
2015-05-11 20:04:55 -04:00
|
|
|
<li *ng-for="var person of people; var i=index">{{i}}. {{person}}<li>
|
2015-03-19 09:31:41 -04:00
|
|
|
</ul>
|
|
|
|
```
|
|
|
|
|
|
|
|
|
2015-02-14 14:06:20 -05:00
|
|
|
The format is intentionally defined freely, so that developers of directives can build an expressive microsyntax for
|
|
|
|
their directives. The following code describes a more formal definition.
|
2014-12-08 17:29:04 -05:00
|
|
|
|
|
|
|
```
|
|
|
|
expression: ... // as defined in Expressions section
|
|
|
|
local: [a-zA-Z][a-zA-Z0-9]* // exported variable name available for binding
|
|
|
|
internal: [a-zA-Z][a-zA-Z0-9]* // internal variable name which the directive exports.
|
|
|
|
key: [a-z][-|_|a-z0-9]]* // key which maps to attribute name
|
|
|
|
keyExpression: key[:|=]?expression // binding which maps an expression to a property
|
|
|
|
varExport: [#|var]local(=internal)? // binding which exports a local variable from a directive
|
|
|
|
microsyntax: ([[key|keyExpression|varExport][;|,]?)*
|
|
|
|
```
|
|
|
|
|
|
|
|
Where
|
2015-02-14 14:06:20 -05:00
|
|
|
* `expression` is an Angular expression as defined in section: Expressions
|
2015-02-09 02:02:41 -05:00
|
|
|
* `local` is a local identifier for local variables.
|
2014-12-08 17:29:04 -05:00
|
|
|
* `internal` is an internal variable which the directive exports for binding.
|
|
|
|
* `key` is an attribute name usually only used to trigger a specific directive.
|
2015-02-14 14:06:20 -05:00
|
|
|
* `keyExpression` is an property name to which the expression will be bound to.
|
2015-02-15 22:06:53 -05:00
|
|
|
* `varExport` allows exporting of directive internal state as variables for further binding. If no `internal` name
|
2015-02-14 14:06:20 -05:00
|
|
|
is specified, the exporting is to an implicit variable.
|
|
|
|
* `microsyntax` allows you to build a simple microsyntax which can still clearly identify which expressions bind to
|
2015-02-09 02:02:41 -05:00
|
|
|
which properties as well as which variables are exported for binding.
|
2014-12-08 17:29:04 -05:00
|
|
|
|
|
|
|
|
|
|
|
NOTE: the `template` attribute must be present to make it clear to the user that a sub-template is being created. This
|
2015-04-26 00:36:51 -04:00
|
|
|
goes along with the philosophy that the developer should be able to reason about the template without understanding the
|
2014-12-08 17:29:04 -05:00
|
|
|
semantics of the instantiator directive.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Binding Events
|
|
|
|
|
|
|
|
Binding events allows wiring events from DOM (or other components) to the Angular controller.
|
|
|
|
|
|
|
|
<table>
|
|
|
|
<tr>
|
|
|
|
<th>Short form</th>
|
|
|
|
<td>`<some-element (some-event)="statement">`</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<th>Canonical form</th>
|
|
|
|
<td>`<some-element on-some-event="statement">`</td>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
|
|
|
|
Where:
|
2015-02-15 22:06:53 -05:00
|
|
|
* `some-element` Any element which can generate DOM events (or has an angular directive which generates the event).
|
2015-04-26 00:36:51 -04:00
|
|
|
* `some-event` (escaped with `()` or `on-`) is the name of the event `some-event`. In this case the
|
2014-12-08 17:29:04 -05:00
|
|
|
dash-case is converted into camel-case `someEvent`.
|
2015-04-29 18:07:55 -04:00
|
|
|
* `statement` is a valid statement (as defined in section below).
|
2015-04-16 12:03:15 -04:00
|
|
|
If the execution of the statement returns `false`, then `preventDefault`is applied on the DOM event.
|
2014-12-08 17:29:04 -05:00
|
|
|
|
2015-02-15 22:06:53 -05:00
|
|
|
By default, angular only listens to the element on the event, and ignores events which bubble. To listen to bubbled
|
2015-04-26 00:36:51 -04:00
|
|
|
events (as in the case of clicking on any child) use the bubble option (`(event)` or `on-bubble-event`) as shown
|
|
|
|
below.
|
2014-12-08 17:29:04 -05:00
|
|
|
|
|
|
|
<table>
|
|
|
|
<tr>
|
|
|
|
<th>Short form</th>
|
|
|
|
<td>`<some-element (^some-event)="statement">`</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<th>Canonical form</th>
|
|
|
|
<td>`<some-element on-bubble-some-event="statement">`</td>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
```
|
|
|
|
@Component(...)
|
|
|
|
class Example {
|
|
|
|
submit() {
|
|
|
|
// do something when button is clicked
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
<button (click)="submit()">Submit</button>
|
|
|
|
```
|
|
|
|
|
2015-02-15 22:06:53 -05:00
|
|
|
In the above example, when clicking on the submit button angular will invoke the `submit` method on the surrounding
|
2014-12-08 17:29:04 -05:00
|
|
|
component's controller.
|
|
|
|
|
|
|
|
|
|
|
|
NOTE: Unlike Angular v1, Angular v2 treats event bindings as core constructs not as directives. This means that there
|
|
|
|
is no need to create a event directive for each kind of event. This makes it possible for Angular v2 to easily
|
2015-02-15 22:06:53 -05:00
|
|
|
bind to custom events of Custom Elements, whose event names are not known ahead of time.
|
2014-12-08 17:29:04 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Expressions, Statements and Formatters
|
|
|
|
|
2015-02-09 02:02:41 -05:00
|
|
|
Angular templates contain expressions for binding to data and statements for binding to events. Expressions and statements
|
2014-12-08 17:29:04 -05:00
|
|
|
have different semantics.
|
|
|
|
|
|
|
|
|
|
|
|
### Expressions
|
|
|
|
|
2015-02-14 14:06:20 -05:00
|
|
|
Expressions can be used to bind to properties only. Expressions represent how data should be projected to the View.
|
2015-01-27 03:13:23 -05:00
|
|
|
Expressions should not have any side effects and should be idempotent. Examples of where expressions can be used in
|
2014-12-08 17:29:04 -05:00
|
|
|
Angular are:
|
|
|
|
```
|
|
|
|
<div title="{{expression}}">{{expression}}</div>
|
|
|
|
<div [title]="expression">...</div>
|
|
|
|
<div bind-title="expression">...</div>
|
2015-02-04 16:27:31 -05:00
|
|
|
<div template="if: expression">...</div>
|
2014-12-08 17:29:04 -05:00
|
|
|
```
|
|
|
|
|
2015-02-17 17:22:03 -05:00
|
|
|
Expressions are simplified version of expression in the language in which you are writing your application. (i.e.
|
|
|
|
expressions follow JS syntax and semantics in JS and Dart syntax and semantics in Dart). Unlike expressions in the
|
|
|
|
language, binding expressions behave differently in following ways:
|
2014-12-08 17:29:04 -05:00
|
|
|
|
2015-02-17 17:22:03 -05:00
|
|
|
* *Must be defined*: Unlike Angular v1, Angular v2 will throw an error on dereferencing fields which are not defined.
|
|
|
|
For example: `user.name` will throw an error if `user` is defined but it does not have `name` property. If the `name`
|
|
|
|
property is not known, it must be declared and set to some value such as empty string, `null` (or `undefined` in JS).
|
|
|
|
This is done to allow early detection of errors in the templates.
|
|
|
|
* *Safe dereference*: Expressions `user.name` where `user` is null will throw `NullPointerException` in the language.
|
2014-12-08 17:29:04 -05:00
|
|
|
In contrast Angular will silently ignore `null` on `user`. This is done because Views often have to wait for the data
|
2015-01-27 03:13:23 -05:00
|
|
|
to arrive from the backend and many fields will be `null` until the data arrives. Safe dereference is so common in the
|
2015-02-14 14:06:20 -05:00
|
|
|
Views that we have made it the default.
|
|
|
|
* *Single expression*: An expression must be a single statement. (i.e. no `;`)
|
2014-12-08 17:29:04 -05:00
|
|
|
* *No assignments*: Binding expressions can not contain assignments.
|
|
|
|
* *No keywords*: Binding expressions can not contain keywords such as: `var`, `if`, and so on.
|
2015-02-17 17:22:03 -05:00
|
|
|
* *Formatters*: Angular expressions can be piped through formatters to further transform the binding value.
|
2014-12-08 17:29:04 -05:00
|
|
|
(See: Formatters)
|
|
|
|
|
|
|
|
Examples of some expressions and their behavior:
|
|
|
|
|
|
|
|
Given:
|
|
|
|
```
|
|
|
|
class Greeter {
|
|
|
|
name:string;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
* `name` : Will result in the value of the `name` property on the `Greeter` class.
|
2015-02-17 17:22:03 -05:00
|
|
|
* `name.length`: Will result in either the length of the `name` string or `undefined` (`null` in Dart) if `name`
|
2014-12-08 17:29:04 -05:00
|
|
|
property is `null` or `undefined`. Example of: safe dereference.
|
2015-02-14 14:06:20 -05:00
|
|
|
* `foo`: Will throw an error because `foo` is not declared on the `Greeter` class. Example of: Must be defined
|
|
|
|
* `name=1`: Not allowed because of assignment.
|
2015-02-09 02:02:41 -05:00
|
|
|
* `name; name.length`: Not allowed because of multiple statements.
|
2014-12-08 17:29:04 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### Statements
|
|
|
|
|
|
|
|
Statements can be used to bind to events only. Statements represent actions to trigger as a response to an event.
|
2015-02-09 02:02:41 -05:00
|
|
|
Examples of where statements can be used in Angular are:
|
2014-12-08 17:29:04 -05:00
|
|
|
```
|
2015-02-09 02:02:41 -05:00
|
|
|
<div (click)="statements">...</div>
|
|
|
|
<div on-click="statements">...</div>
|
2014-12-08 17:29:04 -05:00
|
|
|
```
|
|
|
|
|
2015-02-09 02:02:41 -05:00
|
|
|
Statements are similar to statements in the language in which you are writing your application. (i.e.
|
|
|
|
statements follow JS syntax and semantics in JS and Dart syntax and semantics in Dart). Unlike statements in the
|
2015-02-14 14:06:20 -05:00
|
|
|
language, binding expressions behave differently in the following ways:
|
2014-12-08 17:29:04 -05:00
|
|
|
|
2015-01-27 03:13:23 -05:00
|
|
|
* *Unsafe dereference*: Expressions `user.verify()` where `user` is `null` will throw `NullPointerException` in the
|
2015-02-14 14:06:20 -05:00
|
|
|
language as well as in statements. (In contrast to Safe dereference in Angular expressions.) While Angular protects
|
2015-02-09 02:02:41 -05:00
|
|
|
you from null dereferencing in expressions due to lazy loading of data, no such protection is required for statements,
|
2014-12-08 17:29:04 -05:00
|
|
|
and doing so would make it harder to detect typos in statements.
|
2015-02-09 02:02:41 -05:00
|
|
|
* *Multiple statements OK*: Statements can be composed from more than one statement. (i.e. no `doA(); doB()`)
|
2015-01-27 03:13:23 -05:00
|
|
|
* *Assignments OK*: Event bindings can have side effects and hence assignments are allowed.
|
2014-12-08 17:29:04 -05:00
|
|
|
* *No keywords*: Statements can not contain keywords such as: `var`, `if`, and so on.
|
2015-02-09 02:02:41 -05:00
|
|
|
* *No Formatters*: Angular statements can not contain formatters. (Formatters are only useful for data binding)
|
2014-12-08 17:29:04 -05:00
|
|
|
|
|
|
|
## Further Reading
|
|
|
|
|
2015-02-09 02:02:41 -05:00
|
|
|
* [Template Syntax Constraints and Reasoning](https://docs.google.com/document/d/1HHy_zPLGqJj0bHMiWPzPCxn1pO5GlOYwmv-qGgl4f_s)
|