docs(template-syntax): publish Dart version, tweak TypeScript version

closes #875
This commit is contained in:
Kathy Walrath 2016-02-22 11:43:15 -08:00
parent 3bedd33814
commit e725136d98
5 changed files with 463 additions and 483 deletions

View File

@ -33,11 +33,7 @@ class AppComponent implements OnInit, AfterViewInit {
String heroName;
String help;
String actionName = 'Go for it';
// String badCurly = 'special'; // XXX: This isn't working.
// String badCurly = 'bad, curly'; // XXX: This isn't working.
// String badCurly = 'bad curly'; // XXX: This isn't working.
String badCurly = 'bad'; // XXX: This isn't working.
// List<String> badCurly = ['bad', 'curly']; // XXX: This isn't working.
String badCurly = 'bad curly';
String classes = 'special';
bool canSave = true;
bool isActive = false;

View File

@ -184,17 +184,15 @@ button</button>
<!-- #enddocregion property-binding-5 -->
<!-- #docregion property-binding-6 -->
<!--
BAD!
HeroDetailComponent.hero expects a Hero object,
not the string "currentHero"
<!-- BAD! HeroDetailComponent.hero expects a Hero object,
not the string "currentHero".
<hero-detail hero="currentHero"></hero-detail>
In checked mode, uncommenting the hero-detail above causes this:
EXCEPTION: type 'String' is not a subtype of type 'Hero' of 'value'. -->
<hero-detail hero="currentHero"></hero-detail> -->
<!-- #enddocregion property-binding-6 -->
<!-- In checked mode, uncommenting the hero-detail above causes this:
EXCEPTION: type 'String' is not a subtype of type 'Hero' of 'value'. -->
<!-- #docregion property-binding-7 -->
<hero-detail prefix="You are my" [hero]="currentHero"></hero-detail>
<!-- #enddocregion property-binding-7 -->
@ -260,8 +258,8 @@ Property bound: <img [src]="heroImageUrl">
<!-- #docregion class-binding-2 -->
<!-- reset/override all class names with a binding -->
<div class="bad curly special"
[class]="badCurly">Bad curly</div> <!-- Doesn't work, due to
github.com/angular/angular/issues/6901 -->
[class]="badCurly">Bad curly</div>
<!-- Doesn't work, due to github.com/angular/angular/issues/6901 -->
<!-- #enddocregion class-binding-2 -->
<!-- #docregion class-binding-3 -->
@ -493,16 +491,16 @@ bindon-ngModel
You picked ...
<!-- #docregion NgSwitch, NgSwitch-expanded -->
<span [ngSwitch]="toeChoice">
<!-- #enddocregion NgSwitch -->
<!-- #enddocregion NgSwitch -->
<!-- with *NgSwitch -->
<!-- #docregion NgSwitch -->
<!-- #docregion NgSwitch -->
<span *ngSwitchWhen="'Eenie'">Eenie</span>
<span *ngSwitchWhen="'Meanie'">Meanie</span>
<span *ngSwitchWhen="'Miney'">Miney</span>
<span *ngSwitchWhen="'Moe'">Moe</span>
<span *ngSwitchDefault>other</span>
<!-- #enddocregion NgSwitch -->
<!-- #enddocregion NgSwitch -->
<!-- with <template> -->
<template ngSwitchWhen="Eenie"><span>Eenie</span></template>
@ -511,7 +509,7 @@ bindon-ngModel
<template ngSwitchWhen="Moe"><span>Moe</span></template>
<template ngSwitchDefault><span>other</span></template>
<!-- #docregion NgSwitch -->
<!-- #docregion NgSwitch -->
</span>
<!-- #enddocregion NgSwitch, NgSwitch-expanded -->
</div>

View File

@ -1,412 +0,0 @@
include ../../../../_includes/_util-fns
+includeShared('{ts}', 'intro')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'html-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'my-first-app')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'html-2')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'interpolation-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'first-interpolation')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'interpolation-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'title+image')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'interpolation-3')
+makeExample('template-syntax/dart/lib/app_component.html', 'sum-1')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'interpolation-4')
+makeExample('template-syntax/dart/lib/app_component.html', 'sum-2')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'interpolation-5')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'template-expressions-1')
:marked
We write template expressions in a language that looks like Dart.
Many Dart expressions are legal template expressions, but not all.
Dart expressions that have or promote side effects are prohibited,
including: **[QUESTION: is this list correct? I removed mentions of chaining with , and ;.]**
* assignments (`=`, `+=`, `-=`, ...)
* creating instances using `new` or `const`
* increment and decrement (`++` and `--`)
Other notable differences from Dart syntax include:
**[QUESTION: I wasn't able to use Dart interpolation inside a String,
which I had just assumed would work. How should we talk about that?
What else isn't allowed?]**
* no support for the bitwise operators `|` and `&`
* new [template expression operators](#expression-operators), such as `|`
.callout.is-helpful
header Dart difference: Template expression operators
:marked
[PENDING: say something about stuff you might find in a24ts template expressions
but not in dart template expressions, and vice versa.]
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'template-expressions-context')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'template-expressions-guidelines')
:marked
Dependent values should not change during a single turn of the event loop.
If an idempotent expression returns a string or a number, it returns the same string or number
when called twice in a row. If the expression returns an object (including a `DateTime`, `Map`, or `List`),
it returns the same object *reference* when called twice in a row.
.callout.is-helpful
header Dart difference: Arrays are lists
:marked
Arrays in JavaScript correspond to lists in Dart
(instances of the `List` class).
This chapter uses _array_ and _list_ interchangeably.
For more information, see
[Lists](https://www.dartlang.org/docs/dart-up-and-running/ch02.html#lists)
in the [Dart language tour](https://www.dartlang.org/docs/dart-up-and-running/ch02.html).
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'template-statements-1')
:marked
Like template expressions, template *statements* use a language that looks like Dart.
The template statement parser is different than the template expression parser and
specifically supports both basic assignment (`=`) and chaining expressions with semicolons (`;`) and commas (`,`).
**[QUESTION: is that true — would `,` really work? is "chaining" really the word we want to use?]**
However, certain Dart syntax is not allowed:
* the `new` and `const` keywords **[QUESTION: I guessed about `const`. Is it true?]**
* increment and decrement operators, `++` and `--`
* operator assignment, such as `+=` and `-=`
* the bitwise operators `|` and `&`
* the [template expression operators](#expression-operators)
**[QUESTION: can you really not use `?.`?]**
.callout.is-helpful
header Dart difference: Template statement operators
:marked
[PENDING: say something about stuff you might find in a24ts statements
but not in dart statements, and vice versa.]
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'template-statements-3')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'binding-syntax-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'img+button')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'binding-syntax-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'hero-detail-1')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'binding-syntax-3')
+makeExample('template-syntax/dart/lib/app_component.html', 'disabled-button-1')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'binding-syntax-4')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'binding-syntax-attribute-vs-property')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'binding-syntax-5')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'binding-syntax-world-without-attributes')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'binding-syntax-targets')
<div width="90%">
table
tr
th Binding type
th Target
th Examples
tr
td Property
td.
Element&nbsp;property<br>
Component&nbsp;property<br>
Directive&nbsp;property
td
+makeExample('template-syntax/dart/lib/app_component.html', 'property-binding-syntax-1')(format=".")
tr
td Event
td.
Element&nbsp;event<br>
Component&nbsp;event<br>
Directive&nbsp;event
td
+makeExample('template-syntax/dart/lib/app_component.html', 'event-binding-syntax-1')(format=".")
tr
td Two-way
td.
Event and property
td
+makeExample('template-syntax/dart/lib/app_component.html', '2-way-binding-syntax-1')(format=".")
tr
td Attribute
td.
Attribute
(the&nbsp;exception)
td
+makeExample('template-syntax/dart/lib/app_component.html', 'attribute-binding-syntax-1')(format=".")
tr
td Class
td.
<code>class</code> property
td
+makeExample('template-syntax/dart/lib/app_component.html', 'class-binding-syntax-1')(format=".")
tr
td Style
td.
<code>style</code> property
td
+makeExample('template-syntax/dart/lib/app_component.html', 'style-binding-syntax-1')(format=".")
</div>
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'binding-syntax-end')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'property-binding-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'property-binding-1')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'property-binding-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'property-binding-2')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'property-binding-3')
+makeExample('template-syntax/dart/lib/app_component.html', 'property-binding-3')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'property-binding-4')
+makeExample('template-syntax/dart/lib/app_component.html', 'property-binding-4')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'property-binding-5')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'property-binding-6')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'property-binding-7')
+makeExample('template-syntax/dart/lib/app_component.html', 'property-binding-1')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'property-binding-8')
+makeExample('template-syntax/dart/lib/app_component.html', 'property-binding-5')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'property-binding-9')
+makeExample('template-syntax/dart/lib/app_component.html', 'property-binding-3')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'property-binding-10')
+makeExample('template-syntax/dart/lib/app_component.html', 'property-binding-4')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'property-binding-11')
+makeExample('template-syntax/dart/lib/app_component.html', 'property-binding-6')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'property-binding-12')
+makeExample('template-syntax/dart/lib/app_component.html', 'property-binding-7')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'property-binding-13')
+makeExample('template-syntax/dart/lib/app_component.html', 'property-binding-vs-interpolation')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'property-binding-14')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'other-bindings-1')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'other-bindings-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'attrib-binding-colspan')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'other-bindings-3')
+makeExample('template-syntax/dart/lib/app_component.html', 'attrib-binding-aria')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'other-bindings-class-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'class-binding-1')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'other-bindings-class-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'class-binding-2')(format=".")
//
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'other-bindings-class-3')
:marked
Finally, we can bind to a specific class name.
Angular adds the class when the template expression evaluates to `true`.
It removes the class when the expression evaluates to `false`.
+makeExample('template-syntax/dart/lib/app_component.html', 'class-binding-3')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'other-bindings-class-4')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'other-bindings-style-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'style-binding-1')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'other-bindings-style-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'style-binding-2')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'other-bindings-style-3')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'event-binding-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'event-binding-1')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'event-binding-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'event-binding-1')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'event-binding-3')
+makeExample('template-syntax/dart/lib/app_component.html', 'event-binding-2')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'event-binding-4')
+makeExample('template-syntax/dart/lib/app_component.html', 'event-binding-3')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'event-binding-5')
+makeExample('template-syntax/dart/lib/app_component.html', 'without-NgModel')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'event-binding-6')
+makeExample('template-syntax/dart/lib/hero_detail_component.dart',
'template-1', 'HeroDetailComponent.ts (template)')(format=".")
+makeExample('template-syntax/dart/lib/hero_detail_component.dart',
'deleteRequest', 'HeroDetailComponent.ts (delete logic)')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'event-binding-7')
+makeExample('template-syntax/dart/lib/app_component.html', 'event-binding-to-component')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'event-binding-8')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'ngModel-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgModel-1')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'ngModel-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgModel-2')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'ngModel-3')
+makeExample('template-syntax/dart/lib/app_component.html', 'without-NgModel')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'ngModel-4')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgModel-3')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'ngModel-5')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgModel-1')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'ngModel-6')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgModel-4')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'ngModel-7')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'event-binding-1')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-2')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngClass-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'class-binding-3a')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngClass-2')
+makeExample('template-syntax/dart/lib/app_component.dart', 'setClasses')(format=".")
// PENDING: Add "Dart difference" for returning maps in Dart? for omitting unnecessary `this.`s?
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngClass-3')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgClass-1')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngStyle-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgStyle-1')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngStyle-2')
+makeExample('template-syntax/dart/lib/app_component.dart', 'setStyles')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngStyle-3')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgStyle-2')(format=".")
//
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngIf-1')
<a id="ngIf"></a>
.l-main-section
:marked
### NgIf
We can add an element subtree (an element and its children) to the DOM by binding an `NgIf` directive to a `true` expression.
+makeExample('template-syntax/dart/lib/app_component.html', 'NgIf-1')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngIf-2')
//
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngIf-3')
:marked
Binding to a false expression removes the element subtree from the DOM.
+makeExample('template-syntax/dart/lib/app_component.html', 'NgIf-2')(format=".")
.callout.is-helpful
header Dart difference: No truthy values
:marked
In checked mode, Dart expects Boolean values
(those with type `bool`) to be either `true` or `false`.
Even in production mode, the only value Dart treats as `true` is
the value `true`; all other values are `false`.
TypeScript and JavaScript, on the other hand, treat
many values (including non-null objects) as true.
A TypeScript Angular 2 program, for example, often has code like
`*ngIf="currentHero"` where a Dart program has code like
`*ngIf="currentHero != null"`.
When converting TypeScript code to Dart code, watch out for
true/false problems. For example, forgetting the `!= null`
can lead to error messages such as
"[TODO: Put error message here]".
For more information, see
[Booleans](https://www.dartlang.org/docs/dart-up-and-running/ch02.html#booleans)
in the [Dart language tour](https://www.dartlang.org/docs/dart-up-and-running/ch02.html).
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngIf-4')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgIf-3')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngIf-5')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngSwitch-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgSwitch')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngSwitch-2')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngFor-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgFor-1')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngFor-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgFor-2')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngFor-3')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngFor-4')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngFor-5')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngFor-6')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgFor-3')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngFor-7')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngForTrackBy-1')
+makeExample('template-syntax/dart/lib/app_component.dart', 'trackByHeroes')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngForTrackBy-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgForTrackBy-2')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'directives-ngForTrackBy-3')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template-ngIf-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'Template-1')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template-ngIf-2a')
+makeExample('template-syntax/dart/lib/app_component.html', 'Template-2a')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template-ngIf-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'Template-2')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template-ngIf-3')
// Changed from RED to ORANGE, since this isn't so dire a situation in Dart.
.callout.is-important
header Remember the brackets!
:marked
Dont make the mistake of writing `ngIf="currentHero"`!
That syntax assigns the *string* value "currentHero" to `ngIf`,
which won't work because `ngIf` expects a bool. **[QUESTION: Did I get that right?]**
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template-ngSwitch-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgSwitch-expanded')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template-ngSwitch-2')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template-ngFor-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'Template-3a')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template-ngFor-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'Template-3')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template-ngFor-3')
+makeExample('template-syntax/dart/lib/app_component.html', 'Template-4')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'star-template-ngFor-4')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'local-vars-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'Template-4')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'local-vars-2')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'local-vars-refs')
+makeExample('template-syntax/dart/lib/app_component.html', 'var-phone')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'local-vars-value')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'local-vars-form-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'var-form')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'local-vars-form-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'var-form-a')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'local-vars-form-3')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'inputs-outputs-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'io-1')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'inputs-outputs-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'io-2')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'inputs-outputs-3')
+makeExample('template-syntax/dart/lib/hero_detail_component.dart', 'input-output-1')(format=".")
:marked
.l-sub-section
:marked
Alternatively, we can identify members in the `inputs` and `outputs` arrays
of the directive metadata, as in this example:
+makeExample('template-syntax/dart/lib/hero_detail_component.dart', 'input-output-2')(format=".")
<br>
:marked
We can specify an input/output property either with a decorator or in a metadata array.
Don't do both!
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'inputs-outputs-4')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'inputs-outputs-5')
+makeExample('template-syntax/dart/lib/app_component.html', 'my-click')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'inputs-outputs-6')
+makeExample('template-syntax/dart/lib/my_click_directive.dart', 'my-click-output-1')(format=".")
.l-sub-section
:marked
We can also alias property names in the `inputs` and `outputs` arrays.
We write a colon-delimited (`:`) string with
the directive property name on the *left* and the public alias on the *right*:
+makeExample('template-syntax/dart/lib/my_click_directive.dart', 'my-click-output-2')(format=".")
<a id="expression-operators"></a>
.l-main-section
:marked
## Template expression operators
The template expression language employs a subset of Dart syntax supplemented with a few special operators
for specific scenarios. We'll cover two of these operators: _pipe_ and _Elvis_.
.callout.is-helpful
header Dart difference: ?. is a Dart operator
:marked
The Elvis operator (`?.`) is part of the Dart language.
It's considered a template expression operator because
Angular 2 supports `?.` even in TypeScript and JavaScript apps.
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'expression-operators-pipe-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'pipes-1')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'expression-operators-pipe-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'pipes-2')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'expression-operators-pipe-3')
+makeExample('template-syntax/dart/lib/app_component.html', 'pipes-3')(format=".")
//
NOTE: Intentionally omit discussion of the json pipe.
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'expression-operators-pipe-4')
+makeExample('template-syntax/dart/lib/app_component.html', 'pipes-json')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'expression-operators-elvis-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'elvis-2')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'expression-operators-elvis-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'elvis-1')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'expression-operators-elvis-3')
// +includeShared('../../../ts/latest/guide/template-syntax.jade', 'expression-operators-elvis-4')
:marked
Dart throws an exception, and so does Angular:
code-example(format="" language="html").
EXCEPTION: The null object does not have a getter 'firstName'.
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'expression-operators-elvis-5')
+makeExample('template-syntax/dart/lib/app_component.html', 'elvis-4')(format=".")
//
NOTE: Intentionally skip ugly null checking you wouldn't do in Dart.
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'expression-operators-elvis-6')
+make---dashed-so-does-not-show-as-fragment-error---Example('template-syntax/dart/lib/app_component.html', 'elvis-5')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'expression-operators-elvis-7')
:marked
This approach has merit but can be cumbersome, especially if the property path is long.
Imagine guarding against a null somewhere in a long property path such as `a.b.c.d`.
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'expression-operators-elvis-8')
+makeExample('template-syntax/dart/lib/app_component.html', 'elvis-6')(format=".")
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'expression-operators-elvis-9')
+includeShared('../../../ts/latest/guide/template-syntax.jade', 'summary')

View File

@ -1,12 +1,410 @@
include ../../../../_includes/_util-fns
+includeShared('{ts}', 'intro')
:marked
We're working on the Dart version of this chapter.
In the meantime, please see these resources:
The complete source code for the example app in this chapter is
[in GitHub](https://github.com/angular/angular.io/tree/master/public/docs/_examples/template-syntax/dart).
* [Template Syntax](/docs/ts/latest/guide/template-syntax.html):
The TypeScript version of this chapter
+includeShared('{ts}', 'html-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'my-first-app')(format=".")
+includeShared('{ts}', 'html-2')
* [Dart source code](https://github.com/angular/angular.io/tree/master/public/docs/_examples/template-syntax/dart):
A preliminary version of the example code that will appear in this chapter
+includeShared('{ts}', 'interpolation-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'first-interpolation')(format=".")
+includeShared('{ts}', 'interpolation-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'title+image')(format=".")
+includeShared('{ts}', 'interpolation-3')
+makeExample('template-syntax/dart/lib/app_component.html', 'sum-1')(format=".")
+includeShared('{ts}', 'interpolation-4')
+makeExample('template-syntax/dart/lib/app_component.html', 'sum-2')(format=".")
+includeShared('{ts}', 'interpolation-5')
+includeShared('{ts}', 'template-expressions-1')
:marked
We write template expressions in a language that looks like Dart.
Many Dart expressions are legal template expressions, but not all.
Dart expressions that have or promote side effects are prohibited,
including:
* assignments (`=`, `+=`, `-=`, ...)
* creating instances using `new` or `const`
* increment and decrement (`++` and `--`)
Other notable differences from Dart syntax include:
* no support for Dart string interpolation; for example,
instead of `"'The title is $title'"`, you must use
`"'The title is ' + title"`
* no support for the bitwise operators `|` and `&`
* new [template expression operators](#expression-operators), such as `|`
+includeShared('{ts}', 'template-expressions-context')
+includeShared('{ts}', 'template-expressions-guidelines')
:marked
Dependent values should not change during a single turn of the event loop.
If an idempotent expression returns a string or a number, it returns the same string or number
when called twice in a row. If the expression returns an object (including a `DateTime`, `Map`, or `List`),
it returns the same object *reference* when called twice in a row.
.callout.is-helpful
header Dart difference: Arrays are lists
:marked
Arrays in JavaScript correspond to lists in Dart
(instances of the `List` class).
This chapter uses _array_ and _list_ interchangeably.
For more information, see
[Lists](https://www.dartlang.org/docs/dart-up-and-running/ch02.html#lists)
in the [Dart language tour](https://www.dartlang.org/docs/dart-up-and-running/ch02.html).
+includeShared('{ts}', 'template-statements-1')
:marked
Like template expressions, template *statements* use a language that looks like Dart.
The template statement parser is different than the template expression parser and
specifically supports both basic assignment (`=`) and chaining expressions with semicolons (`;`).
However, certain Dart syntax is not allowed:
* the `new` and `const` keywords
* increment and decrement operators, `++` and `--`
* operator assignment, such as `+=` and `-=`
* the operators `|` and `&` (neither for bitwise operations
nor for the Angular [pipe operator](#the-pipe-operator-))
+includeShared('{ts}', 'template-statements-3')
+includeShared('{ts}', 'binding-syntax-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'img+button')(format=".")
+includeShared('{ts}', 'binding-syntax-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'hero-detail-1')(format=".")
+includeShared('{ts}', 'binding-syntax-3')
+makeExample('template-syntax/dart/lib/app_component.html', 'disabled-button-1')(format=".")
+includeShared('{ts}', 'binding-syntax-4')
+includeShared('{ts}', 'binding-syntax-attribute-vs-property')
+includeShared('{ts}', 'binding-syntax-5')
+includeShared('{ts}', 'binding-syntax-world-without-attributes')
+includeShared('{ts}', 'binding-syntax-targets')
<div width="90%">
table
tr
th Binding type
th Target
th Examples
tr
td Property
td.
Element&nbsp;property<br>
Component&nbsp;property<br>
Directive&nbsp;property
td
+makeExample('template-syntax/dart/lib/app_component.html', 'property-binding-syntax-1')(format=".")
tr
td Event
td.
Element&nbsp;event<br>
Component&nbsp;event<br>
Directive&nbsp;event
td
+makeExample('template-syntax/dart/lib/app_component.html', 'event-binding-syntax-1')(format=".")
tr
td Two-way
td.
Event and property
td
+makeExample('template-syntax/dart/lib/app_component.html', '2-way-binding-syntax-1')(format=".")
tr
td Attribute
td.
Attribute
(the&nbsp;exception)
td
+makeExample('template-syntax/dart/lib/app_component.html', 'attribute-binding-syntax-1')(format=".")
tr
td Class
td.
<code>class</code> property
td
+makeExample('template-syntax/dart/lib/app_component.html', 'class-binding-syntax-1')(format=".")
tr
td Style
td.
<code>style</code> property
td
+makeExample('template-syntax/dart/lib/app_component.html', 'style-binding-syntax-1')(format=".")
</div>
+includeShared('{ts}', 'binding-syntax-end')
+includeShared('{ts}', 'property-binding-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'property-binding-1')(format=".")
+includeShared('{ts}', 'property-binding-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'property-binding-2')(format=".")
+includeShared('{ts}', 'property-binding-3')
+makeExample('template-syntax/dart/lib/app_component.html', 'property-binding-3')(format=".")
+includeShared('{ts}', 'property-binding-4')
+makeExample('template-syntax/dart/lib/app_component.html', 'property-binding-4')(format=".")
+includeShared('{ts}', 'property-binding-5')
+includeShared('{ts}', 'property-binding-6')
+includeShared('{ts}', 'property-binding-7')
+makeExample('template-syntax/dart/lib/app_component.html', 'property-binding-1')(format=".")
+includeShared('{ts}', 'property-binding-8')
+makeExample('template-syntax/dart/lib/app_component.html', 'property-binding-5')(format=".")
+includeShared('{ts}', 'property-binding-9')
+makeExample('template-syntax/dart/lib/app_component.html', 'property-binding-3')(format=".")
+includeShared('{ts}', 'property-binding-10')
+makeExample('template-syntax/dart/lib/app_component.html', 'property-binding-4')(format=".")
+includeShared('{ts}', 'property-binding-11')
+makeExample('template-syntax/dart/lib/app_component.html', 'property-binding-6')(format=".")
.callout.is-helpful
header Dart difference: Type exceptions
:marked
In checked mode, uncommenting the `<hero-detail>` element above causes a type exception,
because `String` isn't a subtype of `Hero`.
For information on checked mode, see [Important concepts](https://www.dartlang.org/docs/dart-up-and-running/ch02.html#important-concepts)
in the Dart language tour.
+includeShared('{ts}', 'property-binding-12')
+makeExample('template-syntax/dart/lib/app_component.html', 'property-binding-7')(format=".")
+includeShared('{ts}', 'property-binding-13')
+makeExample('template-syntax/dart/lib/app_component.html', 'property-binding-vs-interpolation')(format=".")
+includeShared('{ts}', 'property-binding-14')
+includeShared('{ts}', 'other-bindings-1')
+includeShared('{ts}', 'other-bindings-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'attrib-binding-colspan')(format=".")
+includeShared('{ts}', 'other-bindings-3')
+makeExample('template-syntax/dart/lib/app_component.html', 'attrib-binding-aria')(format=".")
+includeShared('{ts}', 'other-bindings-class-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'class-binding-1')(format=".")
+includeShared('{ts}', 'other-bindings-class-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'class-binding-2')(format=".")
//
+includeShared('{ts}', 'other-bindings-class-3')
:marked
Finally, we can bind to a specific class name.
Angular adds the class when the template expression evaluates to `true`.
It removes the class when the expression evaluates to `false`.
+makeExample('template-syntax/dart/lib/app_component.html', 'class-binding-3')(format=".")
+includeShared('{ts}', 'other-bindings-class-4')
+includeShared('{ts}', 'other-bindings-style-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'style-binding-1')(format=".")
+includeShared('{ts}', 'other-bindings-style-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'style-binding-2')(format=".")
+includeShared('{ts}', 'other-bindings-style-3')
+includeShared('{ts}', 'event-binding-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'event-binding-1')(format=".")
+includeShared('{ts}', 'event-binding-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'event-binding-1')(format=".")
+includeShared('{ts}', 'event-binding-3')
+makeExample('template-syntax/dart/lib/app_component.html', 'event-binding-2')(format=".")
+includeShared('{ts}', 'event-binding-4')
+makeExample('template-syntax/dart/lib/app_component.html', 'event-binding-3')(format=".")
+includeShared('{ts}', 'event-binding-5')
+makeExample('template-syntax/dart/lib/app_component.html', 'without-NgModel')(format=".")
+includeShared('{ts}', 'event-binding-6')
+makeExample('template-syntax/dart/lib/hero_detail_component.dart',
'template-1', 'HeroDetailComponent.ts (template)')(format=".")
+makeExample('template-syntax/dart/lib/hero_detail_component.dart',
'deleteRequest', 'HeroDetailComponent.ts (delete logic)')(format=".")
+includeShared('{ts}', 'event-binding-7')
+makeExample('template-syntax/dart/lib/app_component.html', 'event-binding-to-component')(format=".")
+includeShared('{ts}', 'event-binding-8')
+includeShared('{ts}', 'ngModel-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgModel-1')(format=".")
+includeShared('{ts}', 'ngModel-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgModel-2')(format=".")
+includeShared('{ts}', 'ngModel-3')
+makeExample('template-syntax/dart/lib/app_component.html', 'without-NgModel')(format=".")
+includeShared('{ts}', 'ngModel-4')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgModel-3')(format=".")
+includeShared('{ts}', 'ngModel-5')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgModel-1')(format=".")
+includeShared('{ts}', 'ngModel-6')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgModel-4')(format=".")
+includeShared('{ts}', 'ngModel-7')
+includeShared('{ts}', 'directives-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'event-binding-1')(format=".")
+includeShared('{ts}', 'directives-2')
+includeShared('{ts}', 'directives-ngClass-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'class-binding-3a')(format=".")
+includeShared('{ts}', 'directives-ngClass-2')
+makeExample('template-syntax/dart/lib/app_component.dart', 'setClasses')(format=".")
// PENDING: Add "Dart difference" for returning maps in Dart? for omitting unnecessary `this.`s?
+includeShared('{ts}', 'directives-ngClass-3')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgClass-1')(format=".")
+includeShared('{ts}', 'directives-ngStyle-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgStyle-1')(format=".")
+includeShared('{ts}', 'directives-ngStyle-2')
+makeExample('template-syntax/dart/lib/app_component.dart', 'setStyles')(format=".")
+includeShared('{ts}', 'directives-ngStyle-3')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgStyle-2')(format=".")
//
+includeShared('{ts}', 'directives-ngIf-1')
<a id="ngIf"></a>
.l-main-section
:marked
### NgIf
We can add an element subtree (an element and its children) to the DOM by binding an `NgIf` directive to a `true` expression.
+makeExample('template-syntax/dart/lib/app_component.html', 'NgIf-1')(format=".")
+includeShared('{ts}', 'directives-ngIf-2')
//
+includeShared('{ts}', 'directives-ngIf-3')
:marked
Binding to a false expression removes the element subtree from the DOM.
+makeExample('template-syntax/dart/lib/app_component.html', 'NgIf-2')(format=".")
.callout.is-helpful
header Dart difference: No truthy values
:marked
In checked mode, Dart expects Boolean values
(those with type `bool`) to be either `true` or `false`.
Even in production mode, the only value Dart treats as `true` is
the value `true`; all other values are `false`.
TypeScript and JavaScript, on the other hand, treat
many values (including non-null objects) as true.
A TypeScript Angular 2 program, for example, often has code like
`*ngIf="currentHero"` where a Dart program has code like
`*ngIf="currentHero != null"`.
When converting TypeScript code to Dart code, watch out for
true/false problems. For example, forgetting the `!= null`
can lead to exceptions in checked mode, such as
"EXCEPTION: type 'Hero' is not a subtype of type 'bool' of 'boolean expression'".
For more information, see
[Booleans](https://www.dartlang.org/docs/dart-up-and-running/ch02.html#booleans)
in the [Dart language tour](https://www.dartlang.org/docs/dart-up-and-running/ch02.html).
+includeShared('{ts}', 'directives-ngIf-4')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgIf-3')(format=".")
+includeShared('{ts}', 'directives-ngIf-5')
+includeShared('{ts}', 'directives-ngSwitch-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgSwitch')(format=".")
+includeShared('{ts}', 'directives-ngSwitch-2')
+includeShared('{ts}', 'directives-ngFor-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgFor-1')(format=".")
+includeShared('{ts}', 'directives-ngFor-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgFor-2')(format=".")
+includeShared('{ts}', 'directives-ngFor-3')
+includeShared('{ts}', 'directives-ngFor-4')
+includeShared('{ts}', 'directives-ngFor-5')
+includeShared('{ts}', 'directives-ngFor-6')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgFor-3')(format=".")
+includeShared('{ts}', 'directives-ngFor-7')
+includeShared('{ts}', 'directives-ngForTrackBy-1')
+makeExample('template-syntax/dart/lib/app_component.dart', 'trackByHeroes')(format=".")
+includeShared('{ts}', 'directives-ngForTrackBy-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgForTrackBy-2')(format=".")
+includeShared('{ts}', 'directives-ngForTrackBy-3')
+includeShared('{ts}', 'star-template')
+includeShared('{ts}', 'star-template-ngIf-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'Template-1')(format=".")
+includeShared('{ts}', 'star-template-ngIf-2a')
+makeExample('template-syntax/dart/lib/app_component.html', 'Template-2a')(format=".")
+includeShared('{ts}', 'star-template-ngIf-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'Template-2')(format=".")
+includeShared('{ts}', 'star-template-ngIf-3')
// Changed from RED to ORANGE, since this isn't so dire a situation in Dart.
.callout.is-important
header Remember the brackets!
:marked
Dont make the mistake of writing `ngIf="currentHero"`!
That syntax assigns the *string* value "currentHero" to `ngIf`,
which won't work because `ngIf` expects a bool.
+includeShared('{ts}', 'star-template-ngSwitch-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'NgSwitch-expanded')(format=".")
+includeShared('{ts}', 'star-template-ngSwitch-2')
+includeShared('{ts}', 'star-template-ngFor-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'Template-3a')(format=".")
+includeShared('{ts}', 'star-template-ngFor-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'Template-3')(format=".")
+includeShared('{ts}', 'star-template-ngFor-3')
+makeExample('template-syntax/dart/lib/app_component.html', 'Template-4')(format=".")
+includeShared('{ts}', 'star-template-ngFor-4')
+includeShared('{ts}', 'local-vars-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'Template-4')(format=".")
+includeShared('{ts}', 'local-vars-2')
+includeShared('{ts}', 'local-vars-refs')
+makeExample('template-syntax/dart/lib/app_component.html', 'var-phone')(format=".")
+includeShared('{ts}', 'local-vars-value')
+includeShared('{ts}', 'local-vars-form-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'var-form')(format=".")
+includeShared('{ts}', 'local-vars-form-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'var-form-a')(format=".")
+includeShared('{ts}', 'local-vars-form-3')
+includeShared('{ts}', 'inputs-outputs-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'io-1')(format=".")
+includeShared('{ts}', 'inputs-outputs-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'io-2')(format=".")
+includeShared('{ts}', 'inputs-outputs-3')
+makeExample('template-syntax/dart/lib/hero_detail_component.dart', 'input-output-1')(format=".")
:marked
.l-sub-section
:marked
Alternatively, we can identify members in the `inputs` and `outputs` arrays
of the directive metadata, as in this example:
+makeExample('template-syntax/dart/lib/hero_detail_component.dart', 'input-output-2')(format=".")
<br>
:marked
We can specify an input/output property either with a decorator or in a metadata array.
Don't do both!
+includeShared('{ts}', 'inputs-outputs-4')
+includeShared('{ts}', 'inputs-outputs-5')
+makeExample('template-syntax/dart/lib/app_component.html', 'my-click')(format=".")
+includeShared('{ts}', 'inputs-outputs-6')
+makeExample('template-syntax/dart/lib/my_click_directive.dart', 'my-click-output-1')(format=".")
.l-sub-section
:marked
We can also alias property names in the `inputs` and `outputs` arrays.
We write a colon-delimited (`:`) string with
the directive property name on the *left* and the public alias on the *right*:
+makeExample('template-syntax/dart/lib/my_click_directive.dart', 'my-click-output-2')(format=".")
<a id="expression-operators"></a>
.l-main-section
:marked
## Template expression operators
The template expression language employs a subset of Dart syntax supplemented with a few special operators
for specific scenarios. We'll cover two of these operators: _pipe_ and _Elvis_.
.callout.is-helpful
header Dart difference: ?. is a Dart operator
:marked
The Elvis operator (`?.`) is part of the Dart language.
It's considered a template expression operator because
Angular 2 supports `?.` even in TypeScript and JavaScript apps.
+includeShared('{ts}', 'expression-operators-pipe-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'pipes-1')(format=".")
+includeShared('{ts}', 'expression-operators-pipe-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'pipes-2')(format=".")
+includeShared('{ts}', 'expression-operators-pipe-3')
+makeExample('template-syntax/dart/lib/app_component.html', 'pipes-3')(format=".")
//
NOTE: Intentionally omit discussion of the json pipe.
+includeShared('{ts}', 'expression-operators-pipe-4')
+makeExample('template-syntax/dart/lib/app_component.html', 'pipes-json')(format=".")
+includeShared('{ts}', 'expression-operators-elvis-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'elvis-2')(format=".")
+includeShared('{ts}', 'expression-operators-elvis-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'elvis-1')(format=".")
+includeShared('{ts}', 'expression-operators-elvis-3')
// +includeShared('{ts}', 'expression-operators-elvis-4')
:marked
Dart throws an exception, and so does Angular:
code-example(format="" language="html").
EXCEPTION: The null object does not have a getter 'firstName'.
+includeShared('{ts}', 'expression-operators-elvis-5')
+makeExample('template-syntax/dart/lib/app_component.html', 'elvis-4')(format=".")
//
NOTE: Intentionally skip ugly null checking you wouldn't do in Dart.
That means skipping the shared sections 'expression-operators-elvis-6' & 7,
plus the example 'elvis-5'.
:marked
This approach has merit but can be cumbersome, especially if the property path is long.
Imagine guarding against a null somewhere in a long property path such as `a.b.c.d`.
+includeShared('{ts}', 'expression-operators-elvis-8')
+makeExample('template-syntax/dart/lib/app_component.html', 'elvis-6')(format=".")
+includeShared('{ts}', 'expression-operators-elvis-9')
+includeShared('{ts}', 'summary')

View File

@ -574,20 +574,20 @@ table
The expression could call something like `getFoo()`. Only we know what `getFoo()` does.
If `getFoo()` changes something and we happen to be binding to that something, we risk an unpleasant experience. Angular may or may not display the changed value. Angular may detect the change and throw a warning error. Our general advice: stick to data properties and to methods that return values and do no more.
### Return the proper type
The template expression should evaluate to the type of value expected by the target property.
Return a string if the target property expects a string.
The template expression should evaluate to the type of value expected by the target property.
Return a string if the target property expects a string.
Return a number if the target property expects a number.
Return an object if the target property expects an object.
The `hero` property of the `HeroDetail` component expects a `Hero` object, which is exactly what were sending in the property binding:
The `hero` property of the `HeroDetail` component expects a `Hero` object, which is exactly what were sending in the property binding:
// #enddocregion property-binding-10
+makeExample('template-syntax/ts/app/app.component.html', 'property-binding-4')(format=".")
// #docregion property-binding-11
:marked
### Remember the brackets
The brackets tell Angular to evaluate the template expression.
The brackets tell Angular to evaluate the template expression.
If we forget the brackets, Angular treats the string as a constant and *initializes the target property* with that string.
It does *not* evaluate the string!
@ -598,15 +598,15 @@ table
a(id="one-time-initialization")
:marked
### One-time string initialization
We *should omit the brackets* when
* the target property accepts a string value
* the string is a fixed value that we can bake into the template
* this initial value never changes
We routinely initialize attributes this way in standard HTML and it works
We *should* omit the brackets when all of the following are true:
* The target property accepts a string value.
* The string is a fixed value that we can bake into the template.
* This initial value never changes.
We routinely initialize attributes this way in standard HTML, and it works
just as well for directive and component property initialization.
In the following example, we initialize the `prefix` property of the `HeroDetailComponent` to a fixed string,
not a template expression. Angular sets it and forgets it.
The following example initializes the `prefix` property of the `HeroDetailComponent` to a fixed string,
not a template expression. Angular sets it and forgets it.
// #enddocregion property-binding-12
+makeExample('template-syntax/ts/app/app.component.html', 'property-binding-7')(format=".")
// #docregion property-binding-13
@ -832,9 +832,9 @@ code-example(format="", language="html").
Parent directives listen for the event by binding to this property and accessing the payload through the `$event` object.
Consider a `HeroDetailComponent` that presents hero information and responds to user actions.
Although the `HeroDetailComponent` has a delete button it doesn't know how to delete the hero itself.
The best it can do is raise an event reporting the user's delete request.
Although the `HeroDetailComponent` has a delete button it doesn't know how to delete the hero itself.
The best it can do is raise an event reporting the user's delete request.
Here are the pertinent excerpts from that `HeroDetailComponent`:
// #enddocregion event-binding-6
+makeExample('template-syntax/ts/app/hero-detail.component.ts',
@ -845,9 +845,9 @@ code-example(format="", language="html").
// #docregion event-binding-7
:marked
The component defines a `deleteRequest` property that returns an `EventEmitter`.
When the user clicks *delete*, the component invokes the `delete()` method
When the user clicks *delete*, the component invokes the `delete()` method
which tells the `EventEmitter` to emit a `Hero` object.
Now imagine a hosting parent component that binds to the `HeroDetailComponent`'s `deleteRequest` event.
// #enddocregion event-binding-7
@ -1112,17 +1112,17 @@ figure.image-display
We bind the parent `NgSwitch` directive to an expression returning a *switch value*.
The value is a string in this example, but it can be a value of any type.
In this example, the parent `NgSwitch` directive controls a set of child `<span>` elements.
In this example, the parent `NgSwitch` directive controls a set of child `<span>` elements.
A `<span>` is either pegged to a *match value* expression or marked as the default.
**At any particular moment, at most one of these *spans* is in the DOM.**
If the *span*s *match value* equals the switch value, Angular adds the `<span>` to the DOM.
If none of the *spans* is a match, Angular adds the default *span* to the DOM.
If the *span*s *match value* equals the switch value, Angular adds the `<span>` to the DOM.
If none of the *spans* is a match, Angular adds the default *span* to the DOM.
Angular removes and destroys all other *spans*.
.l-sub-section
:marked
We could substitute any element for the *span* in this example.
We could substitute any element for the *span* in this example.
That element could be a `<div>` with a vast subtree of its own elements.
Only the matching `<div>` and its subtree would appear in the DOM;
the others would be removed.
@ -1131,11 +1131,11 @@ figure.image-display
1. `ngSwitch`: bound to an expression that returns the switch value
1. `ngSwitchWhen`: bound to an expression returning a match value
1. `ngSwitchDefault`: a marker attribute on the default element
.alert.is-critical
:marked
**Do *not*** put the asterisk (`*`) in front of `ngSwitch`. Use the property binding instead.
**Do** put the asterisk (`*`) in front of `ngSwitchWhen` and `ngSwitchDefault`.
For more information, see [\* and &lt;template>](#star-template).
// #enddocregion directives-ngSwitch-2
@ -1215,34 +1215,34 @@ figure.image-display
#### NgForTrackBy
The `ngFor` directive has the potential to perform poorly, especially with large lists.
A small change to one item, an item removed, or an item added can trigger a cascade of DOM manipulations.
For example, we could refresh the list of heroes by re-querying the server.
For example, we could refresh the list of heroes by re-querying the server.
The refreshed list probably contains most, if not all, of the previously displayed heroes.
*We* know this because the `id` of each hero hasn't changed.
But Angular sees only a fresh list of new object references.
But Angular sees only a fresh list of new object references.
It has no choice but to tear down the old list, discard those DOM elements, and re-build a new list with new DOM elements.
Angular can avoid this churn if we give it a *tracking* function that tells it what we know:
that two objects with the same `hero.id` are the same *hero*. Here is such a function:
// #enddocregion directives-ngForTrackBy-1
+makeExample('template-syntax/ts/app/app.component.ts', 'trackByHeroes')(format=".")
// #docregion directives-ngForTrackBy-2
:marked
Now set the `NgForTrackBy` directive to that *tracking* function.
Now set the `NgForTrackBy` directive to that *tracking* function.
Angular offers a variety of equivalent syntax choices including these two:
// #enddocregion directives-ngForTrackBy-2
+makeExample('template-syntax/ts/app/app.component.html', 'NgForTrackBy-2')(format=".")
// #docregion directives-ngForTrackBy-3
:marked
The *tracking* function doesn't eliminate all DOM changes.
Angular may have to update the DOM element if the same-hero *properties* have changed.
Angular may have to update the DOM element if the same-hero *properties* have changed.
But if the properties haven't changed &mdash; and most of the time they will not have changed &mdash;
Angular can leave those DOM elements alone. The list UI will be smoother and more responsive.
Here is an illustration of the `NgForTrackBy` effect.
figure.image-display
img(src='/resources/images/devguide/template-syntax/ng-for-track-by-anim.gif' alt="NgForTrackBy")
img(src='/resources/images/devguide/template-syntax/ng-for-track-by-anim.gif' alt="NgForTrackBy")
// #enddocregion directives-ngForTrackBy-3
// #docregion star-template
@ -1256,11 +1256,11 @@ figure.image-display
The `*` is a bit of syntactic sugar that makes it easier to read and write directives that modify HTML layout
with the help of templates.
`NgFor`, `NgIf`, and `NgSwitch` all add and remove element subtrees that are wrapped in `<template>` tags.
We didn't see the `<template>` tags because the `*` prefix syntax allowed us to skip those tags and
focus directly on the HTML element that we are including, excluding, or repeating.
In this section we go under the hood and see how
In this section we go under the hood and see how
Angular strips away the `*` and expands the HTML into the `<template>` tags for us.
// #enddocregion star-template
@ -1272,11 +1272,11 @@ figure.image-display
+makeExample('template-syntax/ts/app/app.component.html', 'Template-1')(format=".")
// #docregion star-template-ngIf-2a
:marked
The `currentHero` is referenced twice, first as the true/false condition for `NgIf` and
The `currentHero` is referenced twice, first as the true/false condition for `NgIf` and
again as the actual hero passed into the `HeroDetailComponent`.
The first expansion step transports the `ngIf` (without the `*` prefix) and its contents
into an expression assigned to a `template` directive.
The first expansion step transports the `ngIf` (without the `*` prefix) and its contents
into an expression assigned to a `template` directive.
// #enddocregion star-template-ngIf-2a
+makeExample('template-syntax/ts/app/app.component.html', 'Template-2a')(format=".")
// #docregion star-template-ngIf-2
@ -1304,18 +1304,18 @@ figure.image-display
// #docregion star-template-ngSwitch-1
:marked
### Expanding `*ngSwitch`
A similar transformation applies to `*ngSwitch`. We can de-sugar the syntax ourselves.
A similar transformation applies to `*ngSwitch`. We can de-sugar the syntax ourselves.
Here's an example, first with `*ngSwitchWhen` and `*ngSwitchDefault` and then again with `<template>` tags:
// #enddocregion star-template-ngSwitch-1
+makeExample('template-syntax/ts/app/app.component.html', 'NgSwitch-expanded')
// #enddocregion star-template-ngSwitch-1
+makeExample('template-syntax/ts/app/app.component.html', 'NgSwitch-expanded')(format=".")
// #docregion star-template-ngSwitch-2
:marked
The `*ngSwitchWhen` and `*ngSwitchDefault` expand in exactly the same manner as `*ngIf`,
wrapping their former elements in `<template>` tags.
Now we can see why the `ngSwitch` itself is not prefixed with an asterisk (*).
Now we can see why the `ngSwitch` itself is not prefixed with an asterisk (*).
It does not define content. It's job is to control a collection of templates.
In this case, it governs two sets of `NgSwitchWhen` and `NgSwitchDefault` directives.
We should expect it to display the values of the selected template twice,
once for the (*) prefixed version and once for the expanded template version.