diff --git a/aio/content/examples/interpolation/src/app/app.component.spec.ts b/aio/content/examples/interpolation/src/app/app.component.spec.ts
new file mode 100644
index 0000000000..852c902d87
--- /dev/null
+++ b/aio/content/examples/interpolation/src/app/app.component.spec.ts
@@ -0,0 +1,27 @@
+import { TestBed, async } from '@angular/core/testing';
+import { AppComponent } from './app.component';
+describe('AppComponent', () => {
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [
+ AppComponent
+ ],
+ }).compileComponents();
+ }));
+ it('should create the app', async(() => {
+ const fixture = TestBed.createComponent(AppComponent);
+ const app = fixture.debugElement.componentInstance;
+ expect(app).toBeTruthy();
+ }));
+ it(`should have as title 'Featured product:'`, async(() => {
+ const fixture = TestBed.createComponent(AppComponent);
+ const app = fixture.debugElement.componentInstance;
+ expect(app.title).toEqual('Featured product:');
+ }));
+ it('should render title in a p tag', async(() => {
+ const fixture = TestBed.createComponent(AppComponent);
+ fixture.detectChanges();
+ const compiled = fixture.debugElement.nativeElement;
+ expect(compiled.querySelector('p').textContent).toContain('Featured product:');
+ }));
+});
diff --git a/aio/content/examples/interpolation/src/app/app.component.ts b/aio/content/examples/interpolation/src/app/app.component.ts
new file mode 100644
index 0000000000..06bb18afc0
--- /dev/null
+++ b/aio/content/examples/interpolation/src/app/app.component.ts
@@ -0,0 +1,25 @@
+import { Component } from '@angular/core';
+
+import { CUSTOMERS } from './customers';
+
+@Component({
+ selector: 'app-root',
+ templateUrl: './app.component.html',
+ styleUrls: ['./app.component.css']
+})
+export class AppComponent {
+ customers = CUSTOMERS;
+
+ currentCustomer = 'Maria';
+ title = 'Featured product:';
+ itemImageUrl = '../assets/pottedPlant.png';
+
+ recommended = 'You might also like:';
+ itemImageUrl2 = '../assets/lamp.png';
+
+
+
+ getVal(): number { return 2; }
+
+
+}
diff --git a/aio/content/examples/interpolation/src/app/app.module.ts b/aio/content/examples/interpolation/src/app/app.module.ts
new file mode 100644
index 0000000000..926975afe8
--- /dev/null
+++ b/aio/content/examples/interpolation/src/app/app.module.ts
@@ -0,0 +1,18 @@
+import { BrowserModule } from '@angular/platform-browser';
+import { NgModule } from '@angular/core';
+
+
+import { AppComponent } from './app.component';
+
+
+@NgModule({
+ declarations: [
+ AppComponent
+ ],
+ imports: [
+ BrowserModule
+ ],
+ providers: [],
+ bootstrap: [AppComponent]
+})
+export class AppModule { }
diff --git a/aio/content/examples/interpolation/src/app/customer.ts b/aio/content/examples/interpolation/src/app/customer.ts
new file mode 100644
index 0000000000..c191255efb
--- /dev/null
+++ b/aio/content/examples/interpolation/src/app/customer.ts
@@ -0,0 +1,3 @@
+export class Customer {
+ name: string;
+}
diff --git a/aio/content/examples/interpolation/src/app/customers.ts b/aio/content/examples/interpolation/src/app/customers.ts
new file mode 100644
index 0000000000..a1d25b93c9
--- /dev/null
+++ b/aio/content/examples/interpolation/src/app/customers.ts
@@ -0,0 +1,9 @@
+import { Customer } from './customer';
+
+export const CUSTOMERS: Customer[] = [
+ { name: 'Maria' },
+ { name: 'Oliver' },
+ { name: 'Walter' },
+ { name: 'Lakshmi' },
+ { name: 'Yasha' }
+];
diff --git a/aio/content/examples/interpolation/src/assets/lamp.png b/aio/content/examples/interpolation/src/assets/lamp.png
new file mode 100644
index 0000000000..5c97adfaea
Binary files /dev/null and b/aio/content/examples/interpolation/src/assets/lamp.png differ
diff --git a/aio/content/examples/interpolation/src/assets/potted-plant.png b/aio/content/examples/interpolation/src/assets/potted-plant.png
new file mode 100644
index 0000000000..fe8ddda8c6
Binary files /dev/null and b/aio/content/examples/interpolation/src/assets/potted-plant.png differ
diff --git a/aio/content/examples/interpolation/src/index.html b/aio/content/examples/interpolation/src/index.html
new file mode 100644
index 0000000000..92f30d0e84
--- /dev/null
+++ b/aio/content/examples/interpolation/src/index.html
@@ -0,0 +1,14 @@
+
+
+
+
+ Interpolation
+
+
+
+
+
+
+
+
+
diff --git a/aio/content/examples/interpolation/src/main.ts b/aio/content/examples/interpolation/src/main.ts
new file mode 100644
index 0000000000..91ec6da5f0
--- /dev/null
+++ b/aio/content/examples/interpolation/src/main.ts
@@ -0,0 +1,12 @@
+import { enableProdMode } from '@angular/core';
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app/app.module';
+import { environment } from './environments/environment';
+
+if (environment.production) {
+ enableProdMode();
+}
+
+platformBrowserDynamic().bootstrapModule(AppModule)
+ .catch(err => console.log(err));
diff --git a/aio/content/examples/interpolation/stackblitz.json b/aio/content/examples/interpolation/stackblitz.json
new file mode 100644
index 0000000000..f33d39c88f
--- /dev/null
+++ b/aio/content/examples/interpolation/stackblitz.json
@@ -0,0 +1,10 @@
+{
+ "description": "Interpolation",
+ "files": [
+ "!**/*.d.ts",
+ "!**/*.js",
+ "!**/*.[1,2].*"
+ ],
+ "file": "src/app/app.component.ts",
+ "tags": ["interpolation"]
+}
diff --git a/aio/content/examples/property-binding/src/app/app.component.ts b/aio/content/examples/property-binding/src/app/app.component.ts
new file mode 100644
index 0000000000..1c52d44ebe
--- /dev/null
+++ b/aio/content/examples/property-binding/src/app/app.component.ts
@@ -0,0 +1,30 @@
+import { Component } from '@angular/core';
+
+
+@Component({
+ selector: 'app-root',
+ templateUrl: './app.component.html',
+ styleUrls: ['./app.component.css']
+})
+export class AppComponent {
+ itemImageUrl = '../assets/lamp.png';
+ isUnchanged = true;
+ classes = 'special';
+ // #docregion parent-data-type
+ parentItem = 'bananas';
+ // #enddocregion parent-data-type
+
+ // #docregion pass-object
+ currentItem = [{
+ id: 21,
+ name: 'peaches'
+ }];
+ // #enddocregion pass-object
+
+ interpolationTitle = 'Interpolation';
+ propertyTitle = 'Property binding';
+
+ // #docregion malicious-content
+ evilTitle = 'Template Syntax';
+ // #enddocregion malicious-content
+}
diff --git a/aio/content/guide/template-syntax.md b/aio/content/guide/template-syntax.md
index 68cd40d9ed..758ba8d8e7 100644
--- a/aio/content/guide/template-syntax.md
+++ b/aio/content/guide/template-syntax.md
@@ -42,31 +42,46 @@ Begin with the first form of data binding—interpolation—to see how m
{@a interpolation}
-## Interpolation ( {{...}} )
+## Interpolation and Template Expressions
-You met the double-curly braces of interpolation, `{{` and `}}`, early in your Angular education.
+Interpolation allows you to incorporate calculated strings into the text
+between HTML element tags and within attribute assignments. Template
+expressions are what you use to calculate those strings.
-
+The interpolation demonstrates all of
+the syntax and code snippets described in this section.
+
+### Interpolation `{{...}}`
+
+Interpolation refers to embedding expressions into marked up text.
+By default, interpolation uses as its delimiter the double curly braces, `{{` and `}}`.
+
+In the following snippet, `{{ currentCustomer }}` is an example of interpolation.
+
+
-You use interpolation to weave calculated strings into the text between HTML element tags and within attribute assignments.
+The text between the braces is often the name of a component
+property. Angular replaces that name with the
+string value of the corresponding component property.
-
+
-The text between the braces is often the name of a component property. Angular replaces that name with the
-string value of the corresponding component property. In the example above, Angular evaluates the `title` and `heroImageUrl` properties
-and "fills in the blanks", first displaying a bold application title and then a heroic image.
+In the example above, Angular evaluates the `title` and `itemImageUrl` properties
+and fills in the blanks, first displaying some title text and then an image.
-More generally, the text between the braces is a **template expression** that Angular first **evaluates**
-and then **converts to a string**. The following interpolation illustrates the point by adding the two numbers:
+More generally, the text between the braces is a **template expression**
+that Angular first **evaluates** and then **converts to a string**.
+The following interpolation illustrates the point by adding two numbers:
-
+
-The expression can invoke methods of the host component such as `getVal()`, seen here:
+The expression can invoke methods of the host component such as `getVal()` in
+the following example:
-
+
Angular evaluates all expressions in double curly braces,
@@ -74,60 +89,67 @@ converts the expression results to strings, and links them with neighboring lite
it assigns this composite interpolated result to an **element or directive property**.
You appear to be inserting the result between element tags and assigning it to attributes.
-It's convenient to think so, and you rarely suffer for this mistake.
-Though this is not exactly true. Interpolation is a special syntax that Angular converts into a
-[property binding](guide/template-syntax#property-binding), as is explained [below](guide/template-syntax#property-binding-or-interpolation).
-But first, let's take a closer look at template expressions and statements.
+
+However, interpolation is a special syntax that Angular converts into a
+property binding.
+If you'd like to use something other than `{{` and `}}`, you can
+configure the interpolation delimiter via the
+[interpolation](api/core/Component#interpolation)
+option in the `Component` metadata.
-
+
-{@a template-expressions}
+### Template expressions
-## Template expressions
-
-A template **expression** produces a value.
+A template **expression** produces a value and appears within the double
+curly braces, `{{ }}`.
Angular executes the expression and assigns it to a property of a binding target;
-the target might be an HTML element, a component, or a directive.
+the target could be an HTML element, a component, or a directive.
The interpolation braces in `{{1 + 1}}` surround the template expression `1 + 1`.
-In the [property binding](guide/template-syntax#property-binding) section below,
+In the property binding,
a template expression appears in quotes to the right of the `=` symbol as in `[property]="expression"`.
-You write these template expressions in a language that looks like JavaScript.
-Many JavaScript expressions are legal template expressions, but not all.
+In terms of syntax, template expressions are similar to JavaScript.
+Many JavaScript expressions are legal template expressions, with a few exceptions.
-JavaScript expressions that have or promote side effects are prohibited,
+You can't use JavaScript expressions that have or promote side effects,
including:
-* assignments (`=`, `+=`, `-=`, ...)
-* new
-* chaining expressions with ; or ,
-* increment and decrement operators (`++` and `--`)
+* Assignments (`=`, `+=`, `-=`, `...`)
+* Operators such as `new`, `typeof`, `instanceof`, etc.
+* Chaining expressions with ; or ,
+* The increment and decrement operators `++` and `--`
+* Some of the ES2015+ operators
Other notable differences from JavaScript syntax include:
-* no support for the bitwise operators `|` and `&`
-* new [template expression operators](guide/template-syntax#expression-operators), such as `|`, `?.` and `!`.
-
-{@a expression-context}
+* No support for the bitwise operators such as `|` and `&`
+* New template expression operators, such as `|`, `?.` and `!`
+
### Expression context
The *expression context* is typically the _component_ instance.
-In the following snippets, the `title` within double-curly braces and the
-`isUnchanged` in quotes refer to properties of the `AppComponent`.
+In the following snippets, the `recommended` within double curly braces and the
+`itemImageUrl2` in quotes refer to properties of the `AppComponent`.
-
+
An expression may also refer to properties of the _template's_ context
-such as a [template input variable](guide/template-syntax#template-input-variable) (`let hero`)
-or a [template reference variable](guide/template-syntax#ref-vars) (`#heroInput`).
+such as a template input variable,
+
+`let customer`, or a template reference variable, `#customerInput`.
+
-
+
+
+
+
The context for terms in an expression is a blend of the _template variables_,
@@ -136,34 +158,32 @@ If you reference a name that belongs to more than one of these namespaces,
the template variable name takes precedence, followed by a name in the directive's _context_,
and, lastly, the component's member names.
-The previous example presents such a name collision. The component has a `hero`
-property and the `*ngFor` defines a `hero` template variable.
-The `hero` in `{{hero.name}}`
+The previous example presents such a name collision. The component has a `customer`
+property and the `*ngFor` defines a `customer` template variable.
+
+
+
+The `customer` in `{{customer.name}}`
refers to the template input variable, not the component's property.
Template expressions cannot refer to anything in
-the global namespace (except `undefined`). They can't refer to `window` or `document`. They
-can't call `console.log` or `Math.max`. They are restricted to referencing
+the global namespace, except `undefined`. They can't refer to
+`window` or `document`. Additionally, they
+can't call `console.log()` or `Math.max()` and they are restricted to referencing
members of the expression context.
-
-{@a no-side-effects}
-
-{@a expression-guidelines}
+
### Expression guidelines
-Template expressions can make or break an application.
-Please follow these guidelines:
+When using template expressions follow these guidelines:
* [No visible side effects](guide/template-syntax#no-visible-side-effects)
* [Quick execution](guide/template-syntax#quick-execution)
* [Simplicity](guide/template-syntax#simplicity)
-* [Idempotence](guide/template-syntax#idempotence)
-The only exceptions to these guidelines should be in specific circumstances that you thoroughly understand.
-#### No visible side effects
+### No visible side effects
A template expression should not change any application state other than the value of the
target property.
@@ -172,37 +192,43 @@ This rule is essential to Angular's "unidirectional data flow" policy.
You should never worry that reading a component value might change some other displayed value.
The view should be stable throughout a single rendering pass.
-#### Quick execution
+An [idempotent](https://en.wikipedia.org/wiki/Idempotence) expression is ideal because
+it is free of side effects and improves Angular's change detection performance.
+
+In Angular terms, an idempotent expression always returns
+*exactly the same thing* until
+one of its dependent values changes.
+
+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 an `array`, it returns the same object *reference* when called twice in a row.
+
+
+
+There is one exception to this behavior that applies to `*ngFor`. `*ngFor` has `trackBy` functionality that can deal with referential inequality of objects that when iterating over them.
+
+For more information, see the [*ngFor with `trackBy`](guide/template-syntax#ngfor-with-trackby) section of this guide.
+
+
+
+### Quick execution
Angular executes template expressions after every change detection cycle.
Change detection cycles are triggered by many asynchronous activities such as
-promise resolutions, http results, timer events, keypresses and mouse moves.
+promise resolutions, HTTP results, timer events, key presses and mouse moves.
Expressions should finish quickly or the user experience may drag, especially on slower devices.
Consider caching values when their computation is expensive.
-#### Simplicity
+### Simplicity
-Although it's possible to write quite complex template expressions, you should avoid them.
+Although it's possible to write complex template expressions, it's a better
+practice to avoid them.
-A property name or method call should be the norm.
-An occasional Boolean negation (`!`) is OK.
-Otherwise, confine application and business logic to the component itself,
-where it will be easier to develop and test.
-
-#### Idempotence
-
-An [idempotent](https://en.wikipedia.org/wiki/Idempotence) expression is ideal because
-it is free of side effects and improves Angular's change detection performance.
-
-In Angular terms, an idempotent expression always returns *exactly the same thing* until
-one of its dependent values changes.
-
-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 an `array`),
-it returns the same object *reference* when called twice in a row.
+A property name or method call should be the norm, but an occasional Boolean negation, `!`, is OK.
+Otherwise, confine application and business logic to the component,
+where it is easier to develop and test.
+
@@ -1673,8 +1699,8 @@ You can only bind to _another_ component or directive through its _Input_ and _O
Remember that all **components** are **directives**.
-The following discussion refers to _components_ for brevity and
-because this topic is mostly a concern for component authors.
+The following discussion refers to _components_ for brevity and
+because this topic is mostly a concern for component authors.
Discussion
@@ -1985,7 +2011,7 @@ You'll need this template operator when you turn on strict null checks. It's opt
{@a any-type-cast-function}
-## The `$any` type cast function (`$any( )`)
+## The `$any` type cast function (`$any( )`)
Sometimes a binding expression will be reported as a type error and it is not possible or difficult
to fully specify the type. To silence the error, you can use the `$any` cast function to cast
@@ -1994,7 +2020,7 @@ the expression to [the `any` type](http://www.typescriptlang.org/docs/handbook/b
-In this example, when the Angular compiler turns your template into TypeScript code,
+In this example, when the Angular compiler turns your template into TypeScript code,
it prevents TypeScript from reporting that `marker` is not a member of the `Hero`
interface.