diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..7142337909 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,24 @@ +dist: trusty +sudo: required +language: node_js +node_js: + - "5" +os: + - linux +env: + global: + - DISPLAY=:99.0 + - CHROME_BIN=chromium-browser + matrix: + - SCRIPT="run-e2e-tests --fast" +before_install: + - npm install -g gulp --no-optional +before_script: + - sh -e /etc/init.d/xvfb start +install: + - npm install --no-optional + - npm install --prefix public/docs/_examples + - npm run webdriver:update --prefix public/docs/_examples + - gulp add-example-boilerplate +script: + - gulp $SCRIPT \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index 0b6a9bac5d..6ec64f97ff 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -60,7 +60,7 @@ var _devguideShredJadeOptions = { }; var _apiShredOptions = { - examplesDir: path.join(ANGULAR_PROJECT_PATH, 'modules/angular2/examples'), + examplesDir: path.join(ANGULAR_PROJECT_PATH, 'modules/@angular/examples'), fragmentsDir: path.join(DOCS_PATH, '_fragments/_api'), zipDir: path.join(RESOURCES_PATH, 'zips/api') }; @@ -103,9 +103,6 @@ var _exampleDartWebBoilerPlateFiles = ['styles.css']; * all means (ts|js|dart) */ gulp.task('run-e2e-tests', function() { - - var exePath = path.join(process.cwd(), "./node_modules/.bin/"); - var promise; if (argv.fast) { // fast; skip all setup @@ -115,7 +112,7 @@ gulp.task('run-e2e-tests', function() { var spawnInfo = spawnExt('npm', ['install'], { cwd: EXAMPLES_PATH}); promise = spawnInfo.promise.then(function() { copyExampleBoilerplate(); - spawnInfo = spawnExt('webdriver-manager', ['update'], {cwd: exePath}); + spawnInfo = spawnExt('npm', ['run', 'webdriver:update'], {cwd: EXAMPLES_PATH}); return spawnInfo.promise; }); } @@ -124,9 +121,12 @@ gulp.task('run-e2e-tests', function() { return findAndRunE2eTests(argv.filter); }).then(function(status) { reportStatus(status); + if (status.failed.length > 0){ + return Promise.reject('Some test suites failed'); + } }).catch(function(e) { gutil.log(e); - return e; + process.exit(1); }); }); @@ -213,9 +213,8 @@ function runProtractor(prepPromise, appDir, appRunSpawnInfo, protractorConfigFil .then(function (data) { // start protractor var pcFilename = path.resolve(protractorConfigFilename); // need to resolve because we are going to be running from a different dir - var exePath = path.join(process.cwd(), "./node_modules/.bin/"); - var spawnInfo = spawnExt('protractor', - [ pcFilename, '--params.appDir=' + appDir, '--params.outputFile=' + outputFile], { cwd: exePath }); + var spawnInfo = spawnExt('npm', [ 'run', 'protractor', '--', pcFilename, + '--params.appDir=' + appDir, '--params.outputFile=' + outputFile], { cwd: EXAMPLES_PATH }); return spawnInfo.promise }) .then( @@ -483,9 +482,14 @@ gulp.task('git-changed-examples', ['_shred-devguide-examples'], function(){ gulp.task('check-deploy', ['build-docs'], function() { return harpCompile().then(function() { - gutil.log('compile ok - running live server ...'); - execPromise('npm run live-server ./www'); - return askDeploy(); + gutil.log('compile ok'); + if(argv.dryRun) { + return false; + } else { + gutil.log('running live server ...'); + execPromise('npm run live-server ./www'); + return askDeploy(); + } }).then(function(shouldDeploy) { if (shouldDeploy) { gutil.log('deploying...'); @@ -847,7 +851,7 @@ function filterOutExcludedPatterns(fileNames, excludeMatchers) { } function apiSourceWatch(postBuildAction) { - var srcPattern = [path.join(ANGULAR_PROJECT_PATH, 'modules/angular2/src/**/*.*')]; + var srcPattern = [path.join(ANGULAR_PROJECT_PATH, 'modules/@angular/src/**/*.*')]; gulp.watch(srcPattern, {readDelay: 500}, function (event, done) { gutil.log('API source changed'); gutil.log('Event type: ' + event.event); // added, changed, or deleted @@ -858,7 +862,7 @@ function apiSourceWatch(postBuildAction) { } function apiExamplesWatch(postShredAction) { - var examplesPath = path.join(ANGULAR_PROJECT_PATH, 'modules/angular2/examples/**'); + var examplesPath = path.join(ANGULAR_PROJECT_PATH, 'modules/@angular/examples/**'); var includePattern = path.join(examplesPath, '**/*.*'); var excludePattern = '!' + path.join(examplesPath, '**/node_modules/**/*.*'); var cleanPath = [path.join(_apiShredOptions.fragmentsDir, '**/*.*'), '!**/*.ovr.*']; diff --git a/public/_includes/_util-fns.jade b/public/_includes/_util-fns.jade index 35e790e874..1e57e5e1ae 100644 --- a/public/_includes/_util-fns.jade +++ b/public/_includes/_util-fns.jade @@ -22,6 +22,7 @@ - var _an = 'an'; //- TS arrays vs. Dart lists +- var _Array = 'Array'; - var _array = 'array'; //- Deprecate now that we have the articles _a and _an - var _an_array = 'an array'; @@ -33,6 +34,9 @@ //- Location of sample code - var _liveLink = 'live link'; +//- Other +- var _truthy = 'truthy'; +- var _falsey = 'falsey'; //- Used to prefix identifiers that are private. In Dart this will be '_'. - var _priv = ''; @@ -40,8 +44,8 @@ //- Use to conditionally include the block that follows +ifDocsFor(...). //- Generally favor use of Jade named blocks instead. ifDocsFor is convenient //- for prose that should appear only in one language version. -mixin ifDocsFor(lang) - if _docsFor.toLowerCase() === lang.toLowerCase() +mixin ifDocsFor(langPattern) + if _docsFor.toLowerCase().match(langPattern.toLowerCase()) block //- Use to map inlined (prose) TS paths into, say, Dart paths via the diff --git a/public/docs/_examples/architecture/dart/example-config.json b/public/docs/_examples/architecture/dart/example-config.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/public/docs/_examples/displaying-data/dart/example-config.json b/public/docs/_examples/displaying-data/dart/example-config.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/public/docs/_examples/forms/dart/example-config.json b/public/docs/_examples/forms/dart/example-config.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/public/docs/_examples/package.json b/public/docs/_examples/package.json index 3a83c2bdf3..095493faf7 100644 --- a/public/docs/_examples/package.json +++ b/public/docs/_examples/package.json @@ -13,6 +13,7 @@ "tsc": "tsc", "tsc:w": "tsc -w", "typings": "typings", + "protractor": "protractor", "webdriver:update": "webdriver-manager update", "start:webpack": "webpack-dev-server --inline --progress --port 8080", "test:webpack": "karma start karma.webpack.conf.js", diff --git a/public/docs/_examples/router/e2e-spec.js b/public/docs/_examples/router/e2e-spec.js index 4e3018b5c2..73bf120d0c 100644 --- a/public/docs/_examples/router/e2e-spec.js +++ b/public/docs/_examples/router/e2e-spec.js @@ -59,7 +59,7 @@ describe('Router', function () { crisisCenterEdit(2, true); }); - it('should be able to edit and cancel details from the crisis center view', function () { + xit('should be able to edit and cancel details from the crisis center view', function () { crisisCenterEdit(3, false); }); diff --git a/public/docs/_examples/template-syntax/dart/example-config.json b/public/docs/_examples/template-syntax/dart/example-config.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/public/docs/_examples/template-syntax/dart/lib/app_component.dart b/public/docs/_examples/template-syntax/dart/lib/app_component.dart index be36d6c38d..6d9199c175 100644 --- a/public/docs/_examples/template-syntax/dart/lib/app_component.dart +++ b/public/docs/_examples/template-syntax/dart/lib/app_component.dart @@ -3,6 +3,7 @@ import 'dart:convert'; import 'dart:html'; import 'package:angular2/core.dart'; +import 'package:angular2/common.dart'; import 'hero.dart'; import 'hero_detail_component.dart'; @@ -40,7 +41,9 @@ class AppComponent implements OnInit, AfterViewInit { bool isSpecial = true; bool isUnchanged = true; bool isSelected = false; + final Color colorRed = Color.red; Color color = Color.red; + var colorEnum = Color; List heroes; Hero currentHero; @@ -56,7 +59,7 @@ class AppComponent implements OnInit, AfterViewInit { final Hero nullHero = null; Map product = {'name': 'frimfram', 'price': 42}; FormElement form; - String clickity = ''; + String clicked = ''; String clickMessage = ''; String clickMessage2 = ''; final String iconUrl = 'assets/images/ng-logo.png'; @@ -87,14 +90,14 @@ class AppComponent implements OnInit, AfterViewInit { int getVal() => val; - void onCancel(MouseEvent event) { - DivElement el = event.target; + void onCancel(UIEvent event) { + HtmlElement el = event?.target; var evtMsg = event != null ? 'Event target is ${el.innerHtml}.' : ''; alerter('Canceled. $evtMsg'); } - void onClickMe(MouseEvent event) { - DivElement el = event.target; + void onClickMe(UIEvent event) { + HtmlElement el = event?.target; var evtMsg = event != null ? 'Event target class is ${el.className}.' : ''; alerter('Click me. $evtMsg'); } @@ -103,9 +106,10 @@ class AppComponent implements OnInit, AfterViewInit { alerter('Deleted hero: ${hero?.firstName}'); } - bool onSave([MouseEvent event = null]) { + bool onSave([UIEvent event = null]) { + HtmlElement el = event?.target; var evtMsg = - event != null ? ' Event target is ${event.target.innerHtml}.' : ''; + event != null ? ' Event target is ${el.innerHtml}.' : ''; alerter('Saved. $evtMsg'); return false; } diff --git a/public/docs/_examples/template-syntax/dart/lib/app_component.html b/public/docs/_examples/template-syntax/dart/lib/app_component.html index 0400832633..c7542c3039 100644 --- a/public/docs/_examples/template-syntax/dart/lib/app_component.html +++ b/public/docs/_examples/template-syntax/dart/lib/app_component.html @@ -31,11 +31,11 @@
* prefix and <template>
-Template local variables
+Template reference variables
Inputs and outputs
Pipes
Safe navigation operator ?.
- +Enums

Interpolation

@@ -105,9 +105,9 @@ -
click me
+
click me
-{{clickity}} +{{clicked}}

@@ -184,15 +184,14 @@ button - + - - - +
+ + + +
@@ -202,7 +201,7 @@ Interpolated:
Property bound:
The interpolated title is {{title}}
-
+
top @@ -258,9 +257,7 @@ Property bound:
Bad curly
-

Note: "Bad curly" should be smaller but isn't, due to - issue #6901.

+ [className]="badCurly">Bad curly
@@ -374,15 +371,15 @@ bindon-ngModel
+ [ngModel]="currentHero.firstName" + (ngModelChange)="currentHero.firstName=$event"> (ngModelChange) = "...firstName=$event"
+ [ngModel]="currentHero.firstName" + (ngModelChange)="setUpperCaseFirstName($event)"> (ngModelChange) = "setUpperCaseFirstName($event)"
@@ -443,7 +440,7 @@ bindon-ngModel -
Hello, {{nullHero.firstName}}
@@ -487,33 +484,33 @@ bindon-ngModel
-
Pick a toe
-
- You picked ... - - +
Pick a toe
+
+ You picked ... + + - - - Eenie - Meanie - Miney - Moe - other - + + + Eenie + Meanie + Miney + Moe + other + - - - - - - + + + + + + - - -
+
+ +
top @@ -620,7 +617,7 @@ bindon-ngModel

expand to <template>

@@ -644,15 +641,15 @@ bindon-ngModel top - -

Template local variables

+ +

Template reference variables

@@ -672,7 +669,7 @@ bindon-ngModel
+ [(ngModel)]="currentHero.firstName">
@@ -682,7 +679,7 @@ bindon-ngModel

- + top @@ -708,13 +705,15 @@ bindon-ngModel

Pipes

- -
{{ title | uppercase }}
+
Title through uppercase pipe: {{title | uppercase}}
- -
{{ title | uppercase | lowercase }}
+ +
+ Title through a pipe chain: + {{title | uppercase | lowercase}} +
@@ -723,16 +722,14 @@ bindon-ngModel - - +
{{currentHero}}
Birthdate: {{(currentHero?.birthdate | date:'longDate') | uppercase}}
- {{product['price'] | currency:'$'}} + {{product['price'] | currency:'USD':false}}
top @@ -742,7 +739,7 @@ bindon-ngModel
- The title is {{ title }} + The title is {{title}}
@@ -759,11 +756,10 @@ bindon-ngModel - @@ -784,19 +780,16 @@ The null hero's name is {{nullHero.firstName}} top - + -

Enums in binding

- -

The current color number is {{color}}

-

- -top - - -

My First Angular Application

- +

+ + The name of the Color.red enum is {{colorRed}}.
+ The current color is {{color}} and its index is {{color.index}}.
+ + +

top diff --git a/public/docs/_examples/template-syntax/ts/app/app.component.html b/public/docs/_examples/template-syntax/ts/app/app.component.html index 37d5614cb2..ed43a2ff33 100644 --- a/public/docs/_examples/template-syntax/ts/app/app.component.html +++ b/public/docs/_examples/template-syntax/ts/app/app.component.html @@ -52,13 +52,13 @@ - -

The sum of 1 + 1 is {{1 + 1}}

+ +

The sum of 1 + 1 is {{1 + 1}}

- -

The sum of 1 + 1 is not {{1 + 1 + getVal()}}

+ +

The sum of 1 + 1 is not {{1 + 1 + getVal()}}

top @@ -66,8 +66,8 @@

New Mental Model

- - + +
Mental Model
@@ -184,13 +184,14 @@ button - - + +
+ + + +
@@ -199,8 +200,8 @@ button Interpolated:
Property bound: -
The interpolated title is {{title}}
-
+
The interpolated title is {{title}}
+
top @@ -278,13 +279,13 @@ Property bound:

Style Binding

- - + + - - + + top @@ -393,7 +394,7 @@ bindon-ngModel
This div is saveable and special
-After setClasses(), the classes are "{{classDiv.className}}" + After setClasses(), the classes are "{{classDiv.className}}"
@@ -409,8 +410,8 @@ After setClasses(), the classes are "{{classDiv.className}}"

NgStyle Binding

-
- This div is x-large +
+ This div is x-large.
@@ -418,12 +419,12 @@ After setClasses(), the classes are "{{classDiv.className}}"

setStyles returns {{setStyles() | json}}

- This div is italic, normal weight, and extra large (24px) + This div is italic, normal weight, and extra large (24px).

After setStyles(), the DOM confirms that the styles are - "{{getStyles(styleDiv)}}" + {{getStyles(styleDiv)}} .

@@ -439,7 +440,7 @@ After setClasses(), the classes are "{{classDiv.className}}" -
Hello, {{nullHero.firstName}}
@@ -603,22 +604,22 @@ After setClasses(), the classes are "{{classDiv.className}}"

* prefix and <template>

*ngIf expansion

-

*ngIf

- - - +

*ngIf

+ + + -

expand to template = "..."

- - - +

expand to template = "..."

+ + + -

expand to <template>

- - - +

expand to <template>

+ + +

*ngFor expansion

*ngFor

@@ -658,7 +659,7 @@ After setClasses(), the classes are "{{classDiv.className}}" - +

Example Form

@@ -704,13 +705,15 @@ After setClasses(), the classes are "{{classDiv.className}}"

Pipes

- -
{{ title | uppercase }}
+
Title through uppercase pipe: {{title | uppercase}}
- -
{{ title | uppercase | lowercase }}
+ +
+ Title through a pipe chain: + {{title | uppercase | lowercase}} +
@@ -720,16 +723,8 @@ After setClasses(), the classes are "{{classDiv.className}}"
{{currentHero | json}}
- - -
Birthdate: {{(currentHero?.birthdate | date:'longDate') | uppercase}}
@@ -743,29 +738,29 @@ After setClasses(), the classes are "{{classDiv.className}}"

Safe navigation operator ?.

- -The title is {{ title }} - + + The title is {{title}} +
- -The current hero's name is {{currentHero?.firstName}} - + + The current hero's name is {{currentHero?.firstName}} +
- -The current hero's name is {{currentHero.firstName}} - + + The current hero's name is {{currentHero.firstName}} +
@@ -780,27 +775,25 @@ The null hero's name is {{nullHero && nullHero.firstName}}
- - -The null hero's name is {{nullHero?.firstName}} - + + + The null hero's name is {{nullHero?.firstName}} +
top - +

Enums in binding

-

The name of the Color.Red enum is {{Color[Color.Red]}}

-

The current color number is {{color}}

-

- -top - - -

My First Angular Application

- +

+ + The name of the Color.Red enum is {{Color[Color.Red]}}.
+ The current color is {{Color[color]}} and its number is {{color}}.
+ + +

top diff --git a/public/docs/_examples/template-syntax/ts/app/app.component.ts b/public/docs/_examples/template-syntax/ts/app/app.component.ts index 1333f9c24d..33ddaa9bf1 100644 --- a/public/docs/_examples/template-syntax/ts/app/app.component.ts +++ b/public/docs/_examples/template-syntax/ts/app/app.component.ts @@ -77,6 +77,9 @@ export class AppComponent implements AfterViewInit, OnInit { heroImageUrl = 'images/hero.png'; //iconUrl = 'https://angular.io/resources/images/logos/standard/shield-large.png'; + clicked = ''; + clickMessage = ''; + clickMessage2 = ''; iconUrl = 'images/ng-logo.png'; isActive = false; isSpecial = true; diff --git a/public/docs/_examples/upgrade-adapter/ts/app/1-to-2-projection/main.controller.ts b/public/docs/_examples/upgrade-adapter/ts/app/1-to-2-projection/main.controller.ts index a47d561b1b..c6041ac788 100644 --- a/public/docs/_examples/upgrade-adapter/ts/app/1-to-2-projection/main.controller.ts +++ b/public/docs/_examples/upgrade-adapter/ts/app/1-to-2-projection/main.controller.ts @@ -1,4 +1,4 @@ -import { Hero } from '../Hero'; +import { Hero } from '../hero'; export class MainController { hero = new Hero(1, 'Windstorm', 'Specific powers of controlling winds'); diff --git a/public/docs/_examples/upgrade-adapter/ts/app/2-to-1-transclusion/container.component.ts b/public/docs/_examples/upgrade-adapter/ts/app/2-to-1-transclusion/container.component.ts index fabb595405..a468898e5f 100644 --- a/public/docs/_examples/upgrade-adapter/ts/app/2-to-1-transclusion/container.component.ts +++ b/public/docs/_examples/upgrade-adapter/ts/app/2-to-1-transclusion/container.component.ts @@ -1,7 +1,7 @@ // #docregion import { Component } from '@angular/core'; import { upgradeAdapter } from './upgrade_adapter'; -import { Hero } from '../Hero'; +import { Hero } from '../hero'; const HeroDetail = upgradeAdapter.upgradeNg1Component('heroDetail'); diff --git a/public/docs/_examples/upgrade-adapter/ts/app/downgrade-io/main.controller.ts b/public/docs/_examples/upgrade-adapter/ts/app/downgrade-io/main.controller.ts index 2bf72de681..2ce02c8792 100644 --- a/public/docs/_examples/upgrade-adapter/ts/app/downgrade-io/main.controller.ts +++ b/public/docs/_examples/upgrade-adapter/ts/app/downgrade-io/main.controller.ts @@ -1,4 +1,4 @@ -import { Hero } from '../Hero'; +import { Hero } from '../hero'; export class MainController { hero = new Hero(1, 'Windstorm'); diff --git a/public/docs/_examples/upgrade-adapter/ts/app/upgrade-io/container.component.ts b/public/docs/_examples/upgrade-adapter/ts/app/upgrade-io/container.component.ts index c13857c7c5..692e3f206f 100644 --- a/public/docs/_examples/upgrade-adapter/ts/app/upgrade-io/container.component.ts +++ b/public/docs/_examples/upgrade-adapter/ts/app/upgrade-io/container.component.ts @@ -1,7 +1,7 @@ // #docregion import { Component } from '@angular/core'; import { upgradeAdapter } from './upgrade_adapter'; -import { Hero } from '../Hero'; +import { Hero } from '../hero'; const HeroDetail = upgradeAdapter.upgradeNg1Component('heroDetail'); diff --git a/public/docs/_examples/user-input/dart/example-config.json b/public/docs/_examples/user-input/dart/example-config.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/public/docs/_layout.jade b/public/docs/_layout.jade index b5fbb2370a..e277180fa0 100644 --- a/public/docs/_layout.jade +++ b/public/docs/_layout.jade @@ -25,7 +25,7 @@ html(lang="en" ng-app="angularIOApp" itemscope itemtype="http://schema.org/Frame else article(class="l-content-small grid-fluid docs-content") div(class="c10") - .showcase.shadow-1 + .showcase .showcase-content != yield if (current.path[3] == 'guide' || current.path[3] == 'tutorial') && current.path[4] diff --git a/public/docs/dart/latest/_util-fns.jade b/public/docs/dart/latest/_util-fns.jade index ab5ba781a7..05448f0216 100644 --- a/public/docs/dart/latest/_util-fns.jade +++ b/public/docs/dart/latest/_util-fns.jade @@ -3,6 +3,7 @@ include ../../../_includes/_util-fns //- See the _util-fns file included above for a description of the use of these variables. - var _docsFor = 'dart'; - var _decorator = 'annotation'; +- var _Array = 'List'; - var _array = 'list'; - var _an_array = 'a list'; //- Deprecate now that we have the articles - var _a = 'an'; @@ -12,6 +13,8 @@ include ../../../_includes/_util-fns - var _Promise = 'Future'; - var _Observable = 'Stream'; - var _liveLink = 'sample repo'; +- var _truthy = 'true'; +- var _falsey = 'false'; mixin liveExampleLink(linkText, exampleUrlPartName) - var text = linkText || '在线例子'; @@ -37,7 +40,7 @@ mixin liveExampleLink2(linkText, exampleUrlPartName) - // Adjust the folder path, e.g., ts -> dart - folder = folder.replace(/(^|\/)ts($|\/)/, '$1dart$2').replace(/(^|\/)app($|\/)/, inWebFolder ? '$1web$2' : '$1lib$2'); - // Special case not handled above: e.g., index.html -> web/index.html -- if(baseNameNoExt.match(/^(index|styles)(\.\d)?$/)) folder = (folder ? folder + '/' : '') + 'web'; +- if(baseNameNoExt.match(/^(index|styles)(\.\d)?$/) && !folder.match(/web$/)) folder = (folder ? folder + '/' : '') + 'web'; - // In file name, replace special characters with underscore - baseNameNoExt = baseNameNoExt.replace(/[\-\.]/g, '_'); - // Adjust the file extension diff --git a/public/docs/dart/latest/guide/template-syntax.jade b/public/docs/dart/latest/guide/template-syntax.jade index 893e53e825..8ba4989112 100644 --- a/public/docs/dart/latest/guide/template-syntax.jade +++ b/public/docs/dart/latest/guide/template-syntax.jade @@ -1,407 +1,128 @@ -include ../_util-fns +extends ../../../ts/latest/guide/template-syntax.jade -+includeShared('{ts}', 'intro') +block includes + include ../_util-fns + - var _JavaScript = 'Dart'; + - var __chaining_op = ';'; + - var __new_op = 'new or const'; + - var mapApiRef = 'https://api.dartlang.org/stable/1.16.0/dart-core/Map-class.html'; + - var __objectAsMap = 'Map' -: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 +block notable-differences :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). + * 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-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') - -
-table - tr - th Binding type - th Target - th Examples - tr - td Property - td. - Element property
- Component property
- Directive property - td - +makeExample('template-syntax/dart/lib/app_component.html', 'property-binding-syntax-1')(format=".") - tr - td Event - td. - Element event
- Component event
- Directive 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 exception) - td - +makeExample('template-syntax/dart/lib/app_component.html', 'attribute-binding-syntax-1')(format=".") - tr - td Class - td. - class property - td - +makeExample('template-syntax/dart/lib/app_component.html', 'class-binding-syntax-1')(format=".") - tr - td Style - td. - style property - td - +makeExample('template-syntax/dart/lib/app_component.html', 'style-binding-syntax-1')(format=".") -
- -+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 +block template-expressions-cannot :marked - In checked mode, uncommenting the `` 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') + Perhaps more surprising, template expressions can’t refer to static + properties, nor to top-level variables or functions, such as `window` or + `document` from `dart:html`. They can’t directly call `print` or functions + imported from `dart:math`. They are restricted to referencing members of + the expression context. -+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') - -.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 +block statement-context :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"`. + Template statements can’t refer to static properties on the class, nor to + top-level variables or functions, such as `window` or `document` from + `dart:html`. They can’t directly call `print` or functions imported from + `dart:math`. - 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') +block dart-type-exceptions + .callout.is-helpful + header Dart difference: Type exceptions + :marked + In checked mode, if the template expression result type and the target + property type are not assignment compatible, then a type exception will + be thrown. + 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}', '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! +block dart-type-exception-example + .callout.is-helpful + header Dart difference: Type exception example + :marked + In checked mode, the code above will result in a type exception: + `String` isn't a subtype of `Hero`. + +block dart-class-binding-bug + .callout.is-helpful + header Angular Issue #6901 + :marked + Issue [#6901][6901] prevents us from using `[class]`. As is illustrated + above, in the meantime we can achieve the same effect by binding to + `className`. + + [6901]: http://github.com/angular/angular/issues/6901 + +block style-property-name-dart-diff + .callout.is-helpful + header Dart difference: Style property names + :marked + While [camelCase](glossary.html#camelcase) and + [dash-case](glossary.html#dash-case) style property naming schemes are + equivalent in Angular Dart, only dash-case names are recognized by the + `dart:html` [CssStyleDeclaration][CssSD] methods `getPropertyValue()` + and `setProperty()`. Hence, we recommend only using dash-case for style + property names. + + [CssSD]: https://api.dartlang.org/stable/1.16.1/dart-html/CssStyleDeclaration-class.html + + +block dart-no-truthy-falsey + .callout.is-helpful + header Dart difference: No truthy/falsey 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). + +block remember-the-brackets + //- 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`. + +block dart-safe-nav-op + .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. + +block json-pipe + //- TODO: explain alternative in Dart + //- {{ e | json }} --> {{ e }} + //- which causes the object's toString() method to be invoked. + //- Of course the `json` pipe can be used if the instance supports + //- JSON encoding. + +block null-deref-example :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') + Dart throws an exception, and so does Angular: + code-example(format="nocode"). + EXCEPTION: The null object does not have a getter 'firstName'. -+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=".") -
- :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=".") - - -.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') +block safe-op-alt + //- N/A diff --git a/public/docs/ts/latest/guide/template-syntax.jade b/public/docs/ts/latest/guide/template-syntax.jade index 3f1bf57a21..63760deaef 100644 --- a/public/docs/ts/latest/guide/template-syntax.jade +++ b/public/docs/ts/latest/guide/template-syntax.jade @@ -1,18 +1,24 @@ -include ../_util-fns +block includes + include ../_util-fns + - var _JavaScript = 'JavaScript'; + //- Double underscore means don't escape var, use !{__var}. + - var __chaining_op = '; or ,'; + - var __new_op = 'new'; + - var __objectAsMap = 'object'; -// #docregion intro :marked - Our Angular application manages what the user sees and does through the interaction of a Component class instance (the *component*) and its user-facing template. - - 我们的Angular应用管理着用户之所见,并通过组件类的实例以及组件面向用户的模板来与用户交互。 + Our Angular application manages what the user sees and can do, achieving this through the interaction of a Component class instance (the *component*) and its user-facing template. + + 我们的Angular应用管理着用户之所见和之所能,并通过组件类的实例以及组件面向用户的模板来与用户交互。 + Many of us are familiar with the component/template duality from our experience with model-view-controller (MVC) or model-view-viewmodel (MVVM). In Angular, the component plays the part of the controller/viewmodel, and the template represents the view. - + 从使用模型-视图-控制器(MVC)或模型-视图-视图模型(MVVM)的经验中,很多用户都熟悉了组件/模板这两个概念。 在Angular中,组件扮演着控制器或视图模型部分,模板则扮演视图部分。 Let’s find out what it takes to write a template for our view. We’ll cover these basic elements of template syntax: - + 我们来看看写视图的模板都需要什么。我们将覆盖模板语法中的下列基本元素: * [HTML](#html) @@ -57,105 +63,96 @@ include ../_util-fns * [管道](#pipe) * ["safe navigation operator" (?.)](#safe-navigation-operator) * [“安全导航操作符”(?.)](#safe-navigation-operator) -// #enddocregion intro -.l-sub-section - :marked - The [live example](/resources/live-examples/template-syntax/ts/plnkr.html) - demonstrates all of the syntax and code snippets described in this chapter. +p. + The #[+liveExampleLink2()] + demonstrates all of the syntax and code snippets described in this chapter. - 这个[在线例子](/resources/live-examples/template-syntax/ts/plnkr.html)演示了本章中描述的所有语法和代码片段。 + The #[+liveExampleLink2()] + 演示了本章中描述的所有语法和代码片段。 // #docregion html-1 .l-main-section :marked ## HTML ## HTML HTML is the language of the Angular template. Our [QuickStart](../quickstart.html) application had a template that was pure HTML: - - HTML是Angular模板的“语言”。我们的[“快速起步”](../quickstart.html)应用就有一个模板是纯HTML的: -// #enddocregion html-1 -+makeExample('template-syntax/ts/app/app.component.html', 'my-first-app')(format=".") -// #docregion html-2 + HTML是Angular模板的“语言”。我们的[“快速起步”](../quickstart.html)应用就有一个模板是纯HTML的: + + +code-example(language="html" escape="html"). +

My First Angular 2 App

+ :marked Almost all HTML syntax is valid template syntax. The `