include ../_util-fns

+includeShared('{ts}', 'intro')

:marked
  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).

+includeShared('{ts}', 'html-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'my-first-app')(format=".")
+includeShared('{ts}', 'html-2')

+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
    Don’t 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}', 'ref-vars')
+makeExample('template-syntax/dart/lib/app_component.html', 'ref-phone')(format=".")
+includeShared('{ts}', 'ref-vars-value')
+includeShared('{ts}', 'ref-vars-form-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'ref-form')(format=".")
+includeShared('{ts}', 'ref-vars-form-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'ref-form-a')(format=".")
+includeShared('{ts}', 'ref-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 _safe navigation operator_.
.callout.is-helpful
  header Dart difference: ?. is a Dart operator
  :marked
    The safe navigation 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-safe-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'safe-2')(format=".")
+includeShared('{ts}', 'expression-operators-safe-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'safe-1')(format=".")
+includeShared('{ts}', 'expression-operators-safe-3')
// +includeShared('{ts}', 'expression-operators-safe-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-safe-5')
+makeExample('template-syntax/dart/lib/app_component.html', 'safe-4')(format=".")

//
  NOTE: Intentionally skip ugly null checking you wouldn't do in Dart.
  That means skipping the shared sections 'expression-operators-safe-6' & 7,
  plus the example 'safe-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-safe-8')
+makeExample('template-syntax/dart/lib/app_component.html', 'safe-6')(format=".")
+includeShared('{ts}', 'expression-operators-safe-9')

+includeShared('{ts}', 'summary')
