movie.hero === value).length > 0 ;
+ }
+// #docregion class
+}
+// #enddocregion class
diff --git a/public/docs/_examples/cb-ajs-quick-reference/ts/src/app/movie.service.ts b/public/docs/_examples/cb-ajs-quick-reference/ts/src/app/movie.service.ts
new file mode 100644
index 0000000000..404fd4454c
--- /dev/null
+++ b/public/docs/_examples/cb-ajs-quick-reference/ts/src/app/movie.service.ts
@@ -0,0 +1,44 @@
+import { Injectable } from '@angular/core';
+
+import { IMovie } from './movie';
+
+@Injectable()
+export class MovieService {
+ getMovies(): IMovie[] {
+ return [
+ {
+ hero: 'Celeritas',
+ imageurl: 'images/hero.png',
+ movieId: 1,
+ mpaa: 'pg-13',
+ releaseDate: '2015-12-19T00:00:00',
+ title: 'Celeritas Reigns',
+ price: 12.95,
+ starRating: 4.925,
+ approvalRating: .97
+ },
+ {
+ hero: 'Mr. Nice',
+ imageurl: 'images/villain.png',
+ movieId: 2,
+ mpaa: 'pg-13',
+ releaseDate: '2015-12-18T00:00:00',
+ title: 'No More Mr. Nice Guy',
+ price: 14.95,
+ starRating: 4.6,
+ approvalRating: .94
+ },
+ {
+ hero: 'Angular',
+ imageurl: 'images/ng-logo.png',
+ movieId: 3,
+ mpaa: 'pg-13',
+ releaseDate: '2015-12-17T00:00:00',
+ title: 'Angular to the Rescue',
+ price: 15.95,
+ starRating: 4.98,
+ approvalRating: .9995
+ }
+ ];
+ }
+}
diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie.ts b/public/docs/_examples/cb-ajs-quick-reference/ts/src/app/movie.ts
similarity index 100%
rename from public/docs/_examples/cb-a1-a2-quick-reference/ts/app/movie.ts
rename to public/docs/_examples/cb-ajs-quick-reference/ts/src/app/movie.ts
diff --git a/public/docs/_examples/cb-ajs-quick-reference/ts/src/images/hero.png b/public/docs/_examples/cb-ajs-quick-reference/ts/src/images/hero.png
new file mode 100644
index 0000000000..2a128ac367
Binary files /dev/null and b/public/docs/_examples/cb-ajs-quick-reference/ts/src/images/hero.png differ
diff --git a/public/docs/_examples/cb-ajs-quick-reference/ts/src/images/ng-logo.png b/public/docs/_examples/cb-ajs-quick-reference/ts/src/images/ng-logo.png
new file mode 100644
index 0000000000..1e488b1a49
Binary files /dev/null and b/public/docs/_examples/cb-ajs-quick-reference/ts/src/images/ng-logo.png differ
diff --git a/public/docs/_examples/cb-ajs-quick-reference/ts/src/images/villain.png b/public/docs/_examples/cb-ajs-quick-reference/ts/src/images/villain.png
new file mode 100644
index 0000000000..26697d1a42
Binary files /dev/null and b/public/docs/_examples/cb-ajs-quick-reference/ts/src/images/villain.png differ
diff --git a/public/docs/_examples/cb-ajs-quick-reference/ts/src/index.html b/public/docs/_examples/cb-ajs-quick-reference/ts/src/index.html
new file mode 100644
index 0000000000..829f080ae3
--- /dev/null
+++ b/public/docs/_examples/cb-ajs-quick-reference/ts/src/index.html
@@ -0,0 +1,28 @@
+
+
+
+
+
+ AngularJS to Angular Quick Reference
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading app...
+
+
+
diff --git a/public/docs/_examples/cb-ajs-quick-reference/ts/src/main.ts b/public/docs/_examples/cb-ajs-quick-reference/ts/src/main.ts
new file mode 100644
index 0000000000..6b6532d428
--- /dev/null
+++ b/public/docs/_examples/cb-ajs-quick-reference/ts/src/main.ts
@@ -0,0 +1,5 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/cb-aot-compiler/e2e-spec.ts b/public/docs/_examples/cb-aot-compiler/e2e-spec.ts
new file mode 100644
index 0000000000..4744f06e50
--- /dev/null
+++ b/public/docs/_examples/cb-aot-compiler/e2e-spec.ts
@@ -0,0 +1,27 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by } from 'protractor';
+
+/* tslint:disable:quotemark */
+describe('AOT Compilation', function () {
+
+ beforeAll(function () {
+ browser.get('');
+ });
+
+ it('should load page and click button', function (done: any) {
+ let headingSelector = element.all(by.css('h1')).get(0);
+ expect(headingSelector.getText()).toEqual('Hello Angular');
+
+ expect(element.all(by.xpath('//div[text()="Magneta"]')).get(0).isPresent()).toBe(true);
+ expect(element.all(by.xpath('//div[text()="Bombasto"]')).get(0).isPresent()).toBe(true);
+ expect(element.all(by.xpath('//div[text()="Magma"]')).get(0).isPresent()).toBe(true);
+ expect(element.all(by.xpath('//div[text()="Tornado"]')).get(0).isPresent()).toBe(true);
+
+ let toggleButton = element.all(by.css('button')).get(0);
+ toggleButton.click().then(function() {
+ expect(headingSelector.isPresent()).toBe(false);
+ done();
+ });
+ });
+});
diff --git a/public/docs/_examples/cb-aot-compiler/ts/.gitignore b/public/docs/_examples/cb-aot-compiler/ts/.gitignore
new file mode 100644
index 0000000000..91da4c79a2
--- /dev/null
+++ b/public/docs/_examples/cb-aot-compiler/ts/.gitignore
@@ -0,0 +1,7 @@
+**/*.ngfactory.ts
+**/*.ngsummary.json
+**/*.shim.ngstyle.ts
+**/*.metadata.json
+dist
+!app/tsconfig.json
+!rollup-config.js
diff --git a/public/docs/_examples/cb-aot-compiler/ts/example-config.json b/public/docs/_examples/cb-aot-compiler/ts/example-config.json
new file mode 100644
index 0000000000..473b80a572
--- /dev/null
+++ b/public/docs/_examples/cb-aot-compiler/ts/example-config.json
@@ -0,0 +1,3 @@
+{
+ "build": "build:aot"
+}
diff --git a/public/docs/_examples/cb-aot-compiler/ts/rollup-config.js b/public/docs/_examples/cb-aot-compiler/ts/rollup-config.js
new file mode 100644
index 0000000000..1cd25515ba
--- /dev/null
+++ b/public/docs/_examples/cb-aot-compiler/ts/rollup-config.js
@@ -0,0 +1,34 @@
+// #docregion
+import rollup from 'rollup'
+import nodeResolve from 'rollup-plugin-node-resolve'
+import commonjs from 'rollup-plugin-commonjs';
+import uglify from 'rollup-plugin-uglify'
+
+// #docregion config
+export default {
+ entry: 'src/main.js',
+ dest: 'src/build.js', // output a single application bundle
+ sourceMap: false,
+ format: 'iife',
+ onwarn: function(warning) {
+ // Skip certain warnings
+
+ // should intercept ... but doesn't in some rollup versions
+ if ( warning.code === 'THIS_IS_UNDEFINED' ) { return; }
+
+ // console.warn everything else
+ console.warn( warning.message );
+ },
+ plugins: [
+ nodeResolve({jsnext: true, module: true}),
+ // #docregion commonjs
+ commonjs({
+ include: 'node_modules/rxjs/**',
+ }),
+ // #enddocregion commonjs
+ // #docregion uglify
+ uglify()
+ // #enddocregion uglify
+ ]
+}
+// #enddocregion config
diff --git a/public/docs/_examples/cb-aot-compiler/ts/src/app/app.component.html b/public/docs/_examples/cb-aot-compiler/ts/src/app/app.component.html
new file mode 100644
index 0000000000..1d3a8de932
--- /dev/null
+++ b/public/docs/_examples/cb-aot-compiler/ts/src/app/app.component.html
@@ -0,0 +1,7 @@
+
+Toggle Heading
+Hello Angular
+
+List of Heroes
+{{hero}}
+
diff --git a/public/docs/_examples/cb-aot-compiler/ts/src/app/app.component.ts b/public/docs/_examples/cb-aot-compiler/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..879f7f663c
--- /dev/null
+++ b/public/docs/_examples/cb-aot-compiler/ts/src/app/app.component.ts
@@ -0,0 +1,15 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ templateUrl: './app.component.html'
+})
+export class AppComponent {
+ showHeading = true;
+ heroes = ['Magneta', 'Bombasto', 'Magma', 'Tornado'];
+
+ toggleHeading() {
+ this.showHeading = !this.showHeading;
+ }
+}
diff --git a/public/docs/_examples/cb-aot-compiler/ts/src/app/app.module.ts b/public/docs/_examples/cb-aot-compiler/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..b4fc185c24
--- /dev/null
+++ b/public/docs/_examples/cb-aot-compiler/ts/src/app/app.module.ts
@@ -0,0 +1,12 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+import { AppComponent } from './app.component';
+
+@NgModule({
+ imports: [ BrowserModule ],
+ declarations: [ AppComponent ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/cb-aot-compiler/ts/src/index-jit.html b/public/docs/_examples/cb-aot-compiler/ts/src/index-jit.html
new file mode 100644
index 0000000000..713a04970e
--- /dev/null
+++ b/public/docs/_examples/cb-aot-compiler/ts/src/index-jit.html
@@ -0,0 +1,24 @@
+
+
+
+
+ Ahead of time compilation (JIT)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
diff --git a/public/docs/_examples/cb-aot-compiler/ts/src/index.html b/public/docs/_examples/cb-aot-compiler/ts/src/index.html
new file mode 100644
index 0000000000..09e5f0de0e
--- /dev/null
+++ b/public/docs/_examples/cb-aot-compiler/ts/src/index.html
@@ -0,0 +1,20 @@
+
+
+
+
+ Ahead of time compilation
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
+
+
diff --git a/public/docs/_examples/cb-aot-compiler/ts/src/main-jit.ts b/public/docs/_examples/cb-aot-compiler/ts/src/main-jit.ts
new file mode 100644
index 0000000000..88e2c16ed5
--- /dev/null
+++ b/public/docs/_examples/cb-aot-compiler/ts/src/main-jit.ts
@@ -0,0 +1,6 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module';
+
+console.log('Running JIT compiled');
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/cb-aot-compiler/ts/src/main.ts b/public/docs/_examples/cb-aot-compiler/ts/src/main.ts
new file mode 100644
index 0000000000..4446bc07d1
--- /dev/null
+++ b/public/docs/_examples/cb-aot-compiler/ts/src/main.ts
@@ -0,0 +1,6 @@
+// #docregion
+import { platformBrowser } from '@angular/platform-browser';
+import { AppModuleNgFactory } from '../aot/src/app/app.module.ngfactory';
+
+console.log('Running AOT compiled');
+platformBrowser().bootstrapModuleFactory(AppModuleNgFactory);
diff --git a/public/docs/_examples/cb-aot-compiler/ts/tsconfig-aot.json b/public/docs/_examples/cb-aot-compiler/ts/tsconfig-aot.json
new file mode 100644
index 0000000000..d0a3d00ad4
--- /dev/null
+++ b/public/docs/_examples/cb-aot-compiler/ts/tsconfig-aot.json
@@ -0,0 +1,23 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "module": "es2015",
+ "moduleResolution": "node",
+ "sourceMap": true,
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "lib": ["es2015", "dom"],
+ "noImplicitAny": true,
+ "suppressImplicitAnyIndexErrors": true
+ },
+
+ "files": [
+ "src/app/app.module.ts",
+ "src/main.ts"
+ ],
+
+ "angularCompilerOptions": {
+ "genDir": "aot",
+ "skipMetadataEmit" : true
+ }
+}
diff --git a/public/docs/_examples/cb-component-communication/e2e-spec.js b/public/docs/_examples/cb-component-communication/e2e-spec.js
deleted file mode 100644
index 84729e0cef..0000000000
--- a/public/docs/_examples/cb-component-communication/e2e-spec.js
+++ /dev/null
@@ -1,210 +0,0 @@
-describe('Component Communication Cookbook Tests', function () {
-
-
- beforeAll(function () {
- browser.get('');
- });
-
- describe('Parent-to-child communication', function() {
- // #docregion parent-to-child
- // ...
- var _heroNames = ['Mr. IQ', 'Magneta', 'Bombasto'];
- var _masterName = 'Master';
-
- it('should pass properties to children properly', function () {
- var parent = element.all(by.tagName('hero-parent')).get(0);
- var heroes = parent.all(by.tagName('hero-child'));
-
- for (var i = 0; i < _heroNames.length; i++) {
- var childTitle = heroes.get(i).element(by.tagName('h3')).getText();
- var childDetail = heroes.get(i).element(by.tagName('p')).getText();
- expect(childTitle).toEqual(_heroNames[i] + ' says:')
- expect(childDetail).toContain(_masterName)
- }
- });
- // ...
- // #enddocregion parent-to-child
- });
-
- describe('Parent-to-child communication with setter', function() {
- // #docregion parent-to-child-setter
- // ...
- it('should display trimmed, non-empty names', function () {
- var _nonEmptyNameIndex = 0;
- var _nonEmptyName = '"Mr. IQ"';
- var parent = element.all(by.tagName('name-parent')).get(0);
- var hero = parent.all(by.tagName('name-child')).get(_nonEmptyNameIndex);
-
- var displayName = hero.element(by.tagName('h3')).getText();
- expect(displayName).toEqual(_nonEmptyName)
- });
-
- it('should replace empty name with default name', function () {
- var _emptyNameIndex = 1;
- var _defaultName = '""';
- var parent = element.all(by.tagName('name-parent')).get(0);
- var hero = parent.all(by.tagName('name-child')).get(_emptyNameIndex);
-
- var displayName = hero.element(by.tagName('h3')).getText();
- expect(displayName).toEqual(_defaultName)
- });
- // ...
- // #enddocregion parent-to-child-setter
- });
-
- describe('Parent-to-child communication with ngOnChanges', function() {
- // #docregion parent-to-child-onchanges
- // ...
- // Test must all execute in this exact order
- it('should set expected initial values', function () {
- var actual = getActual();
-
- var initialLabel = "Version 1.23";
- var initialLog = 'major changed from {} to 1, minor changed from {} to 23';
-
- expect(actual.label).toBe(initialLabel);
- expect(actual.count).toBe(1);
- expect(actual.logs.get(0).getText()).toBe(initialLog);
- });
-
- it('should set expected values after clicking "Minor" twice', function () {
- var repoTag = element(by.tagName('version-parent'));
- var newMinorButton = repoTag.all(by.tagName('button')).get(0);
-
- newMinorButton.click().then(function() {
- newMinorButton.click().then(function() {
- var actual = getActual();
-
- var labelAfter2Minor = "Version 1.25";
- var logAfter2Minor = 'minor changed from 24 to 25';
-
- expect(actual.label).toBe(labelAfter2Minor);
- expect(actual.count).toBe(3);
- expect(actual.logs.get(2).getText()).toBe(logAfter2Minor);
- })
- });
- });
-
- it('should set expected values after clicking "Major" once', function () {
- var repoTag = element(by.tagName('version-parent'));
- var newMajorButton = repoTag.all(by.tagName('button')).get(1);
-
- newMajorButton.click().then(function() {
- var actual = getActual();
-
- var labelAfterMajor = "Version 2.0";
- var logAfterMajor = 'major changed from 1 to 2, minor changed from 25 to 0';
-
- expect(actual.label).toBe(labelAfterMajor);
- expect(actual.count).toBe(4);
- expect(actual.logs.get(3).getText()).toBe(logAfterMajor);
- });
- });
-
- function getActual() {
- var versionTag = element(by.tagName('version-child'));
- var label = versionTag.element(by.tagName('h3')).getText();
- var ul = versionTag.element((by.tagName('ul')));
- var logs = ul.all(by.tagName('li'));
-
- return {
- label: label,
- logs: logs,
- count: logs.count()
- };
- }
- // ...
- // #enddocregion parent-to-child-onchanges
-
- });
-
- describe('Child-to-parent communication', function() {
- // #docregion child-to-parent
- // ...
- it('should not emit the event initially', function () {
- var voteLabel = element(by.tagName('vote-taker'))
- .element(by.tagName('h3')).getText();
- expect(voteLabel).toBe("Agree: 0, Disagree: 0");
- });
-
- it('should process Agree vote', function () {
- var agreeButton1 = element.all(by.tagName('my-voter')).get(0)
- .all(by.tagName('button')).get(0);
- agreeButton1.click().then(function() {
- var voteLabel = element(by.tagName('vote-taker'))
- .element(by.tagName('h3')).getText();
- expect(voteLabel).toBe("Agree: 1, Disagree: 0");
- });
- });
-
- it('should process Disagree vote', function () {
- var agreeButton1 = element.all(by.tagName('my-voter')).get(1)
- .all(by.tagName('button')).get(1);
- agreeButton1.click().then(function() {
- var voteLabel = element(by.tagName('vote-taker'))
- .element(by.tagName('h3')).getText();
- expect(voteLabel).toBe("Agree: 1, Disagree: 1");
- });
- });
- // ...
- // #enddocregion child-to-parent
- });
-
- describe('Parent calls ViewChild', function() {
- // #docregion parent-to-view-child
- // ...
- it('should stop the countdown', function () {
- var stopButton = element
- .all(by.tagName('countdown-parent')).get(0)
- .all(by.tagName('button')).get(1);
-
- stopButton.click().then(function() {
- var message = element(by.tagName('countdown-timer'))
- .element(by.tagName('p')).getText();
- expect(message).toContain('Holding');
- });
- });
- // ...
- // #enddocregion parent-to-view-child
- });
-
- describe('Parent and children communicate via a service', function() {
- // #docregion bidirectional-service
- // ...
- it('should announce a mission', function () {
- var missionControl = element(by.tagName('mission-control'));
- var announceButton = missionControl.all(by.tagName('button')).get(0);
- announceButton.click().then(function () {
- var history = missionControl.all(by.tagName('li'));
- expect(history.count()).toBe(1);
- expect(history.get(0).getText()).toMatch(/Mission.* announced/);
- });
- });
-
- it('should confirm the mission by Lovell', function () {
- testConfirmMission(1, 2, 'Lovell');
- });
-
- it('should confirm the mission by Haise', function () {
- testConfirmMission(3, 3, 'Haise');
- });
-
- it('should confirm the mission by Swigert', function () {
- testConfirmMission(2, 4, 'Swigert');
- });
-
- function testConfirmMission(buttonIndex, expectedLogCount, astronaut) {
- var _confirmedLog = ' confirmed the mission';
- var missionControl = element(by.tagName('mission-control'));
- var confirmButton = missionControl.all(by.tagName('button')).get(buttonIndex);
- confirmButton.click().then(function () {
- var history = missionControl.all(by.tagName('li'));
- expect(history.count()).toBe(expectedLogCount);
- expect(history.get(expectedLogCount-1).getText()).toBe(astronaut + _confirmedLog);
- });
- }
- // ...
- // #enddocregion bidirectional-service
- });
-
-});
diff --git a/public/docs/_examples/cb-component-communication/e2e-spec.ts b/public/docs/_examples/cb-component-communication/e2e-spec.ts
new file mode 100644
index 0000000000..d78e0784d9
--- /dev/null
+++ b/public/docs/_examples/cb-component-communication/e2e-spec.ts
@@ -0,0 +1,232 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by } from 'protractor';
+
+describe('Component Communication Cookbook Tests', function () {
+
+ // Note: '?e2e' which app can read to know it is running in protractor
+ // e.g. `if (!/e2e/.test(location.search)) { ...`
+ beforeAll(function () {
+ browser.get('?e2e');
+ });
+
+ describe('Parent-to-child communication', function() {
+ // #docregion parent-to-child
+ // ...
+ let _heroNames = ['Mr. IQ', 'Magneta', 'Bombasto'];
+ let _masterName = 'Master';
+
+ it('should pass properties to children properly', function () {
+ let parent = element.all(by.tagName('hero-parent')).get(0);
+ let heroes = parent.all(by.tagName('hero-child'));
+
+ for (let i = 0; i < _heroNames.length; i++) {
+ let childTitle = heroes.get(i).element(by.tagName('h3')).getText();
+ let childDetail = heroes.get(i).element(by.tagName('p')).getText();
+ expect(childTitle).toEqual(_heroNames[i] + ' says:');
+ expect(childDetail).toContain(_masterName);
+ }
+ });
+ // ...
+ // #enddocregion parent-to-child
+ });
+
+ describe('Parent-to-child communication with setter', function() {
+ // #docregion parent-to-child-setter
+ // ...
+ it('should display trimmed, non-empty names', function () {
+ let _nonEmptyNameIndex = 0;
+ let _nonEmptyName = '"Mr. IQ"';
+ let parent = element.all(by.tagName('name-parent')).get(0);
+ let hero = parent.all(by.tagName('name-child')).get(_nonEmptyNameIndex);
+
+ let displayName = hero.element(by.tagName('h3')).getText();
+ expect(displayName).toEqual(_nonEmptyName);
+ });
+
+ it('should replace empty name with default name', function () {
+ let _emptyNameIndex = 1;
+ let _defaultName = '""';
+ let parent = element.all(by.tagName('name-parent')).get(0);
+ let hero = parent.all(by.tagName('name-child')).get(_emptyNameIndex);
+
+ let displayName = hero.element(by.tagName('h3')).getText();
+ expect(displayName).toEqual(_defaultName);
+ });
+ // ...
+ // #enddocregion parent-to-child-setter
+ });
+
+ describe('Parent-to-child communication with ngOnChanges', function() {
+ // #docregion parent-to-child-onchanges
+ // ...
+ // Test must all execute in this exact order
+ it('should set expected initial values', function () {
+ let actual = getActual();
+
+ let initialLabel = 'Version 1.23';
+ let initialLog = 'Initial value of major set to 1, Initial value of minor set to 23';
+
+ expect(actual.label).toBe(initialLabel);
+ expect(actual.count).toBe(1);
+ expect(actual.logs.get(0).getText()).toBe(initialLog);
+ });
+
+ it('should set expected values after clicking \'Minor\' twice', function () {
+ let repoTag = element(by.tagName('version-parent'));
+ let newMinorButton = repoTag.all(by.tagName('button')).get(0);
+
+ newMinorButton.click().then(function() {
+ newMinorButton.click().then(function() {
+ let actual = getActual();
+
+ let labelAfter2Minor = 'Version 1.25';
+ let logAfter2Minor = 'minor changed from 24 to 25';
+
+ expect(actual.label).toBe(labelAfter2Minor);
+ expect(actual.count).toBe(3);
+ expect(actual.logs.get(2).getText()).toBe(logAfter2Minor);
+ });
+ });
+ });
+
+ it('should set expected values after clicking \'Major\' once', function () {
+ let repoTag = element(by.tagName('version-parent'));
+ let newMajorButton = repoTag.all(by.tagName('button')).get(1);
+
+ newMajorButton.click().then(function() {
+ let actual = getActual();
+
+ let labelAfterMajor = 'Version 2.0';
+ let logAfterMajor = 'major changed from 1 to 2, minor changed from 25 to 0';
+
+ expect(actual.label).toBe(labelAfterMajor);
+ expect(actual.count).toBe(4);
+ expect(actual.logs.get(3).getText()).toBe(logAfterMajor);
+ });
+ });
+
+ function getActual() {
+ let versionTag = element(by.tagName('version-child'));
+ let label = versionTag.element(by.tagName('h3')).getText();
+ let ul = versionTag.element((by.tagName('ul')));
+ let logs = ul.all(by.tagName('li'));
+
+ return {
+ label: label,
+ logs: logs,
+ count: logs.count()
+ };
+ }
+ // ...
+ // #enddocregion parent-to-child-onchanges
+
+ });
+
+ describe('Child-to-parent communication', function() {
+ // #docregion child-to-parent
+ // ...
+ it('should not emit the event initially', function () {
+ let voteLabel = element(by.tagName('vote-taker'))
+ .element(by.tagName('h3')).getText();
+ expect(voteLabel).toBe('Agree: 0, Disagree: 0');
+ });
+
+ it('should process Agree vote', function () {
+ let agreeButton1 = element.all(by.tagName('my-voter')).get(0)
+ .all(by.tagName('button')).get(0);
+ agreeButton1.click().then(function() {
+ let voteLabel = element(by.tagName('vote-taker'))
+ .element(by.tagName('h3')).getText();
+ expect(voteLabel).toBe('Agree: 1, Disagree: 0');
+ });
+ });
+
+ it('should process Disagree vote', function () {
+ let agreeButton1 = element.all(by.tagName('my-voter')).get(1)
+ .all(by.tagName('button')).get(1);
+ agreeButton1.click().then(function() {
+ let voteLabel = element(by.tagName('vote-taker'))
+ .element(by.tagName('h3')).getText();
+ expect(voteLabel).toBe('Agree: 1, Disagree: 1');
+ });
+ });
+ // ...
+ // #enddocregion child-to-parent
+ });
+
+ // Can't run timer tests in protractor because
+ // interaction w/ zones causes all tests to freeze & timeout.
+ xdescribe('Parent calls child via local var', function() {
+ countDownTimerTests('countdown-parent-lv');
+ });
+
+ xdescribe('Parent calls ViewChild', function() {
+ countDownTimerTests('countdown-parent-vc');
+ });
+
+ function countDownTimerTests(parentTag: string) {
+ // #docregion countdown-timer-tests
+ // ...
+ it('timer and parent seconds should match', function () {
+ let parent = element(by.tagName(parentTag));
+ let message = parent.element(by.tagName('countdown-timer')).getText();
+ browser.sleep(10); // give `seconds` a chance to catchup with `message`
+ let seconds = parent.element(by.className('seconds')).getText();
+ expect(message).toContain(seconds);
+ });
+
+ it('should stop the countdown', function () {
+ let parent = element(by.tagName(parentTag));
+ let stopButton = parent.all(by.tagName('button')).get(1);
+
+ stopButton.click().then(function() {
+ let message = parent.element(by.tagName('countdown-timer')).getText();
+ expect(message).toContain('Holding');
+ });
+ });
+ // ...
+ // #enddocregion countdown-timer-tests
+ }
+
+
+ describe('Parent and children communicate via a service', function() {
+ // #docregion bidirectional-service
+ // ...
+ it('should announce a mission', function () {
+ let missionControl = element(by.tagName('mission-control'));
+ let announceButton = missionControl.all(by.tagName('button')).get(0);
+ announceButton.click().then(function () {
+ let history = missionControl.all(by.tagName('li'));
+ expect(history.count()).toBe(1);
+ expect(history.get(0).getText()).toMatch(/Mission.* announced/);
+ });
+ });
+
+ it('should confirm the mission by Lovell', function () {
+ testConfirmMission(1, 2, 'Lovell');
+ });
+
+ it('should confirm the mission by Haise', function () {
+ testConfirmMission(3, 3, 'Haise');
+ });
+
+ it('should confirm the mission by Swigert', function () {
+ testConfirmMission(2, 4, 'Swigert');
+ });
+
+ function testConfirmMission(buttonIndex: number, expectedLogCount: number, astronaut: string) {
+ let _confirmedLog = ' confirmed the mission';
+ let missionControl = element(by.tagName('mission-control'));
+ let confirmButton = missionControl.all(by.tagName('button')).get(buttonIndex);
+ confirmButton.click().then(function () {
+ let history = missionControl.all(by.tagName('li'));
+ expect(history.count()).toBe(expectedLogCount);
+ expect(history.get(expectedLogCount - 1).getText()).toBe(astronaut + _confirmedLog);
+ });
+ }
+ // ...
+ // #enddocregion bidirectional-service
+ });
+
+});
diff --git a/public/docs/_examples/cb-component-communication/ts/app/app.component.html b/public/docs/_examples/cb-component-communication/ts/app/app.component.html
deleted file mode 100644
index 6cfb5b76ed..0000000000
--- a/public/docs/_examples/cb-component-communication/ts/app/app.component.html
+++ /dev/null
@@ -1,44 +0,0 @@
-Component Communication Cookbook
-
-Pass data from parent to child with input binding
-Intercept input property changes with a setter
-Intercept input property changes with ngOnChanges
-Parent listens for child event
-Parent calls ViewChild
-Parent and children communicate via a service
-
-
-
-
-Back to Top
-
-
-
-
-
-Back to Top
-
-
-
-
-
-Back to Top
-
-
-
-
-
-Back to Top
-
-
-
-
-
-Back to Top
-
-
-
-
-
-Back to Top
-
diff --git a/public/docs/_examples/cb-component-communication/ts/app/app.component.ts b/public/docs/_examples/cb-component-communication/ts/app/app.component.ts
deleted file mode 100644
index a1d11ed518..0000000000
--- a/public/docs/_examples/cb-component-communication/ts/app/app.component.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import {Component} from 'angular2/core';
-import {HeroParentComponent} from './hero-parent.component';
-import {NameParentComponent} from './name-parent.component';
-import {VersionParentComponent} from './version-parent.component';
-import {VoteTakerComponent} from './votetaker.component';
-import {CountdownParentComponent} from './countdown-parent.component';
-import {MissionControlComponent} from './missioncontrol.component';
-
-@Component({
- selector: 'app',
- templateUrl: 'app/app.component.html',
- directives: [
- HeroParentComponent,
- NameParentComponent,
- VersionParentComponent,
- VoteTakerComponent,
- CountdownParentComponent,
- MissionControlComponent
- ]
-})
-export class AppComponent { }
\ No newline at end of file
diff --git a/public/docs/_examples/cb-component-communication/ts/app/astronaut.component.ts b/public/docs/_examples/cb-component-communication/ts/app/astronaut.component.ts
deleted file mode 100644
index 686543be33..0000000000
--- a/public/docs/_examples/cb-component-communication/ts/app/astronaut.component.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-// #docregion
-import {Component, Input, OnDestroy} from 'angular2/core';
-import {MissionService} from './mission.service';
-import {Subscription} from 'rxjs/Subscription';
-
-@Component({
- selector: 'my-astronaut',
- template: `
-
- {{astronaut}}: {{mission}}
-
- Confirm
-
-
- `
-})
-export class AstronautComponent implements OnDestroy{
- @Input() astronaut: string;
- mission = "";
- confirmed = false;
- announced = false;
- subscription:Subscription;
-
- constructor(private missionService: MissionService) {
- this.subscription = missionService.missionAnnounced$.subscribe(
- mission => {
- this.mission = mission;
- this.announced = true;
- this.confirmed = false;
- })
- }
-
- confirm() {
- this.confirmed = true;
- this.missionService.confirmMission(this.astronaut);
- }
-
- ngOnDestroy(){
- // prevent memory leak when component destroyed
- this.subscription.unsubscribe();
- }
-}
-// #enddocregion
\ No newline at end of file
diff --git a/public/docs/_examples/cb-component-communication/ts/app/countdown-parent.component.ts b/public/docs/_examples/cb-component-communication/ts/app/countdown-parent.component.ts
deleted file mode 100644
index d1e2a00cc9..0000000000
--- a/public/docs/_examples/cb-component-communication/ts/app/countdown-parent.component.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-// #docregion
-import {Component, ViewChild} from 'angular2/core';
-import {CountdownTimerComponent} from './countdown-timer.component';
-
-@Component({
- selector:'countdown-parent',
- template: `
- Countdown to Liftoff
- Start
- Stop
-
- `,
- directives: [CountdownTimerComponent]
-})
-export class CountdownParentComponent {
-
- @ViewChild(CountdownTimerComponent)
- private _timerComponent:CountdownTimerComponent;
-
- start(){ this._timerComponent.start(); }
- stop() { this._timerComponent.stop(); }
-}
\ No newline at end of file
diff --git a/public/docs/_examples/cb-component-communication/ts/app/countdown-timer.component.ts b/public/docs/_examples/cb-component-communication/ts/app/countdown-timer.component.ts
deleted file mode 100644
index 0175993303..0000000000
--- a/public/docs/_examples/cb-component-communication/ts/app/countdown-timer.component.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-// #docregion
-import {Component, OnInit, OnDestroy} from 'angular2/core';
-
-@Component({
- selector:'countdown-timer',
- template: '{{message}}
'
-})
-export class CountdownTimerComponent implements OnInit, OnDestroy {
-
- intervalId = 0;
- message = '';
- seconds = 11;
-
- clearTimer() {clearInterval(this.intervalId);}
-
- ngOnInit() { this.start(); }
- ngOnDestroy() { this.clearTimer(); }
-
- start() { this._countDown(); }
- stop() {
- this.clearTimer();
- this.message = `Holding at T-${this.seconds} seconds`;
- }
-
- private _countDown() {
- this.clearTimer();
- this.intervalId = setInterval(()=>{
- this.seconds -= 1;
- if (this.seconds == 0) {
- this.message = "Blast off!";
- this.seconds = 11; // reset
- } else {
- this.message = `T-${this.seconds} seconds and counting`;
- }
- }, 1000);
- }
-}
\ No newline at end of file
diff --git a/public/docs/_examples/cb-component-communication/ts/app/hero-parent.component.ts b/public/docs/_examples/cb-component-communication/ts/app/hero-parent.component.ts
deleted file mode 100644
index 17a2dcc93c..0000000000
--- a/public/docs/_examples/cb-component-communication/ts/app/hero-parent.component.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-// #docregion
-import {Component} from 'angular2/core';
-import {HeroChildComponent} from './hero-child.component';
-import {HEROES} from './hero';
-
-@Component({
- selector: 'hero-parent',
- template: `
- {{master}} controls {{heroes.length}} heroes
-
-
- `,
- directives: [HeroChildComponent]
-})
-export class HeroParentComponent {
- heroes = HEROES;
- master: string = 'Master';
-}
-// #enddocregion
diff --git a/public/docs/_examples/cb-component-communication/ts/app/hero.ts b/public/docs/_examples/cb-component-communication/ts/app/hero.ts
deleted file mode 100644
index 5b99f17132..0000000000
--- a/public/docs/_examples/cb-component-communication/ts/app/hero.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-export interface Hero {
- name: string;
-}
-
-export const HEROES = [
- {name: 'Mr. IQ'},
- {name: 'Magneta'},
- {name: 'Bombasto'}
-];
\ No newline at end of file
diff --git a/public/docs/_examples/cb-component-communication/ts/app/main.ts b/public/docs/_examples/cb-component-communication/ts/app/main.ts
deleted file mode 100644
index dc1879e9b5..0000000000
--- a/public/docs/_examples/cb-component-communication/ts/app/main.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import {bootstrap} from 'angular2/platform/browser';
-import {AppComponent} from './app.component';
-
-bootstrap(AppComponent);
\ No newline at end of file
diff --git a/public/docs/_examples/cb-component-communication/ts/app/mission.service.ts b/public/docs/_examples/cb-component-communication/ts/app/mission.service.ts
deleted file mode 100644
index b651646b4b..0000000000
--- a/public/docs/_examples/cb-component-communication/ts/app/mission.service.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-// #docregion
-import {Injectable} from 'angular2/core'
-import {Subject} from 'rxjs/Subject';
-
-@Injectable()
-export class MissionService {
-
- // Observable string sources
- private _missionAnnouncedSource = new Subject();
- private _missionConfirmedSource = new Subject();
-
- // Observable string streams
- missionAnnounced$ = this._missionAnnouncedSource.asObservable();
- missionConfirmed$ = this._missionConfirmedSource.asObservable();
-
- // Service message commands
- announceMission(mission: string) {
- this._missionAnnouncedSource.next(mission)
- }
-
- confirmMission(astronaut: string) {
- this._missionConfirmedSource.next(astronaut);
- }
-}
-// #enddocregion
diff --git a/public/docs/_examples/cb-component-communication/ts/app/missioncontrol.component.ts b/public/docs/_examples/cb-component-communication/ts/app/missioncontrol.component.ts
deleted file mode 100644
index 2f0ac129c0..0000000000
--- a/public/docs/_examples/cb-component-communication/ts/app/missioncontrol.component.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-// #docregion
-import {Component} from 'angular2/core';
-import {AstronautComponent} from './astronaut.component';
-import {MissionService} from './mission.service';
-
-@Component({
- selector: 'mission-control',
- template: `
- Mission Control
- Announce mission
-
-
- History
-
- `,
- directives: [AstronautComponent],
- providers: [MissionService]
-})
-export class MissionControlComponent {
- astronauts = ['Lovell', 'Swigert', 'Haise']
- history: string[] = [];
- missions = ['Fly to the moon!',
- 'Fly to mars!',
- 'Fly to Vegas!'];
- nextMission = 0;
-
- constructor(private missionService: MissionService) {
- missionService.missionConfirmed$.subscribe(
- astronaut => {
- this.history.push(`${astronaut} confirmed the mission`);
- })
- }
-
- announce() {
- let mission = this.missions[this.nextMission++];
- this.missionService.announceMission(mission);
- this.history.push(`Mission "${mission}" announced`);
- if (this.nextMission >= this.missions.length) { this.nextMission = 0; }
- }
-}
-// #enddocregion
\ No newline at end of file
diff --git a/public/docs/_examples/cb-component-communication/ts/app/name-child.component.ts b/public/docs/_examples/cb-component-communication/ts/app/name-child.component.ts
deleted file mode 100644
index a02fa7949e..0000000000
--- a/public/docs/_examples/cb-component-communication/ts/app/name-child.component.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-// #docregion
-import {Component, Input} from 'angular2/core';
-
-@Component({
- selector: 'name-child',
- template: `
- "{{name}}"
- `
-})
-export class NameChildComponent {
- _name: string = '';
-
- @Input()
- set name(name: string) {
- this._name = (name && name.trim()) || '';
- }
-
- get name() { return this._name; }
-}
-// #enddocregion
diff --git a/public/docs/_examples/cb-component-communication/ts/app/name-parent.component.ts b/public/docs/_examples/cb-component-communication/ts/app/name-parent.component.ts
deleted file mode 100644
index ec99f31675..0000000000
--- a/public/docs/_examples/cb-component-communication/ts/app/name-parent.component.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-// #docregion
-import {Component} from 'angular2/core';
-import {NameChildComponent} from './name-child.component';
-
-@Component({
- selector: 'name-parent',
- template: `
- Master controls {{names.length}} names
-
-
- `,
- directives: [NameChildComponent]
-})
-export class NameParentComponent {
- // Displays 'Mr. IQ', '', 'Bombasto'
- names = ['Mr. IQ', ' ', ' Bombasto '];
-}
-// #enddocregion
diff --git a/public/docs/_examples/cb-component-communication/ts/app/version-child.component.ts b/public/docs/_examples/cb-component-communication/ts/app/version-child.component.ts
deleted file mode 100644
index 944c2888f6..0000000000
--- a/public/docs/_examples/cb-component-communication/ts/app/version-child.component.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-// #docregion
-import {Component, Input, OnChanges, SimpleChange} from 'angular2/core';
-
-@Component({
- selector: 'version-child',
- template: `
- Version {{major}}.{{minor}}
- Change log:
-
- `
-})
-export class VersionChildComponent implements OnChanges {
- @Input() major: number;
- @Input() minor: number;
- changeLog: string[] = [];
-
- ngOnChanges(changes: {[propKey:string]: SimpleChange}){
- let log: string[] = [];
- for (let propName in changes) {
- let changedProp = changes[propName];
- let from = JSON.stringify(changedProp.previousValue);
- let to = JSON.stringify(changedProp.currentValue);
- log.push( `${propName} changed from ${from} to ${to}`);
- }
- this.changeLog.push(log.join(', '));
- }
-}
-// #enddocregion
\ No newline at end of file
diff --git a/public/docs/_examples/cb-component-communication/ts/app/votetaker.component.ts b/public/docs/_examples/cb-component-communication/ts/app/votetaker.component.ts
deleted file mode 100644
index 02aeda9fd9..0000000000
--- a/public/docs/_examples/cb-component-communication/ts/app/votetaker.component.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-// #docregion
-import {Component} from 'angular2/core';
-import {VoterComponent} from './voter.component';
-
-@Component({
- selector: 'vote-taker',
- template: `
- Should mankind colonize the Universe?
- Agree: {{agreed}}, Disagree: {{disagreed}}
-
-
- `,
- directives: [VoterComponent]
-})
-export class VoteTakerComponent {
- agreed = 0;
- disagreed = 0;
- voters = ['Mr. IQ', 'Ms. Universe', 'Bombasto']
-
- onVoted(agreed: boolean) {
- agreed ? this.agreed++ : this.disagreed++;
- }
-}
-// #enddocregion
\ No newline at end of file
diff --git a/public/docs/_examples/cb-component-communication/ts/index.html b/public/docs/_examples/cb-component-communication/ts/index.html
deleted file mode 100644
index 8678794506..0000000000
--- a/public/docs/_examples/cb-component-communication/ts/index.html
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-
-
- Passing information from parent to child
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- loading...
-
-
-
diff --git a/public/docs/_examples/cb-component-communication/ts/plnkr.json b/public/docs/_examples/cb-component-communication/ts/plnkr.json
index 3c83b2d0f9..03bd55cd1a 100644
--- a/public/docs/_examples/cb-component-communication/ts/plnkr.json
+++ b/public/docs/_examples/cb-component-communication/ts/plnkr.json
@@ -1,8 +1,9 @@
{
"description": "Component Communication Cookbook samples",
+ "basePath": "src/",
"files":[
- "!**/*.d.ts",
+ "!**/*.d.ts",
"!**/*.js"
],
"tags":["cookbook", "component"]
-}
\ No newline at end of file
+}
diff --git a/public/docs/_examples/cb-component-communication/ts/src/app/app.component.html b/public/docs/_examples/cb-component-communication/ts/src/app/app.component.html
new file mode 100644
index 0000000000..ef94020efb
--- /dev/null
+++ b/public/docs/_examples/cb-component-communication/ts/src/app/app.component.html
@@ -0,0 +1,51 @@
+Component Communication Cookbook
+
+Pass data from parent to child with input binding ("Heroes")
+Intercept input property changes with a setter ("Master")
+Intercept input property changes with ngOnChanges ("Source code version")
+Parent listens for child event ("Colonize Universe")
+Parent to child via local variable ("Countdown to Liftoff")
+Parent calls ViewChild ("Countdown to Liftoff")
+Parent and children communicate via a service ("Mission Control")
+
+
+
+
+Back to Top
+
+
+
+
+
+Back to Top
+
+
+
+
+
+Back to Top
+
+
+
+
+
+Back to Top
+
+
+
+
+
+Back to Top
+
+
+
+
+
+Back to Top
+
+
+
+
+
+Back to Top
+
diff --git a/public/docs/_examples/cb-component-communication/ts/src/app/app.component.ts b/public/docs/_examples/cb-component-communication/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..7556beb1ff
--- /dev/null
+++ b/public/docs/_examples/cb-component-communication/ts/src/app/app.component.ts
@@ -0,0 +1,7 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ templateUrl: './app.component.html'
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/cb-component-communication/ts/src/app/app.module.ts b/public/docs/_examples/cb-component-communication/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..a008fc5486
--- /dev/null
+++ b/public/docs/_examples/cb-component-communication/ts/src/app/app.module.ts
@@ -0,0 +1,54 @@
+import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+import { AppComponent } from './app.component';
+import { AstronautComponent } from './astronaut.component';
+import { CountdownLocalVarParentComponent, CountdownViewChildParentComponent } from './countdown-parent.component';
+import { CountdownTimerComponent } from './countdown-timer.component';
+import { HeroChildComponent } from './hero-child.component';
+import { HeroParentComponent } from './hero-parent.component';
+import { MissionControlComponent } from './missioncontrol.component';
+import { NameChildComponent } from './name-child.component';
+import { NameParentComponent } from './name-parent.component';
+import { VersionChildComponent } from './version-child.component';
+import { VersionParentComponent } from './version-parent.component';
+import { VoterComponent } from './voter.component';
+import { VoteTakerComponent } from './votetaker.component';
+
+let directives: any[] = [
+ AppComponent,
+ AstronautComponent,
+ CountdownTimerComponent,
+ HeroChildComponent,
+ HeroParentComponent,
+ MissionControlComponent,
+ NameChildComponent,
+ NameParentComponent,
+ VersionChildComponent,
+ VersionParentComponent,
+ VoterComponent,
+ VoteTakerComponent
+ ];
+
+let schemas: any[] = [];
+
+// Include Countdown examples
+// unless in e2e tests which they break.
+if (!/e2e/.test(location.search)) {
+ console.log('adding countdown timer examples');
+ directives.push(CountdownLocalVarParentComponent);
+ directives.push(CountdownViewChildParentComponent);
+} else {
+ // In e2e test use CUSTOM_ELEMENTS_SCHEMA to supress unknown element errors
+ schemas.push(CUSTOM_ELEMENTS_SCHEMA);
+}
+
+@NgModule({
+ imports: [
+ BrowserModule
+ ],
+ declarations: directives,
+ bootstrap: [ AppComponent ],
+ schemas: schemas
+})
+export class AppModule { }
diff --git a/public/docs/_examples/cb-component-communication/ts/src/app/astronaut.component.ts b/public/docs/_examples/cb-component-communication/ts/src/app/astronaut.component.ts
new file mode 100644
index 0000000000..bc24964f86
--- /dev/null
+++ b/public/docs/_examples/cb-component-communication/ts/src/app/astronaut.component.ts
@@ -0,0 +1,46 @@
+// #docregion
+import { Component, Input, OnDestroy } from '@angular/core';
+
+import { MissionService } from './mission.service';
+import { Subscription } from 'rxjs/Subscription';
+
+@Component({
+ selector: 'my-astronaut',
+ template: `
+
+ {{astronaut}}: {{mission}}
+
+ Confirm
+
+
+ `
+})
+export class AstronautComponent implements OnDestroy {
+ @Input() astronaut: string;
+ mission = '';
+ confirmed = false;
+ announced = false;
+ subscription: Subscription;
+
+ constructor(private missionService: MissionService) {
+ this.subscription = missionService.missionAnnounced$.subscribe(
+ mission => {
+ this.mission = mission;
+ this.announced = true;
+ this.confirmed = false;
+ });
+ }
+
+ confirm() {
+ this.confirmed = true;
+ this.missionService.confirmMission(this.astronaut);
+ }
+
+ ngOnDestroy() {
+ // prevent memory leak when component destroyed
+ this.subscription.unsubscribe();
+ }
+}
+// #enddocregion
diff --git a/public/docs/_examples/cb-component-communication/ts/src/app/countdown-parent.component.ts b/public/docs/_examples/cb-component-communication/ts/src/app/countdown-parent.component.ts
new file mode 100644
index 0000000000..5bcf0645c9
--- /dev/null
+++ b/public/docs/_examples/cb-component-communication/ts/src/app/countdown-parent.component.ts
@@ -0,0 +1,57 @@
+// #docplaster
+// #docregion vc
+import { AfterViewInit, ViewChild } from '@angular/core';
+// #docregion lv
+import { Component } from '@angular/core';
+import { CountdownTimerComponent } from './countdown-timer.component';
+
+// #enddocregion lv
+// #enddocregion vc
+
+//// Local variable, #timer, version
+// #docregion lv
+@Component({
+ selector: 'countdown-parent-lv',
+ template: `
+ Countdown to Liftoff (via local variable)
+ Start
+ Stop
+ {{timer.seconds}}
+
+ `,
+ styleUrls: ['demo.css']
+})
+export class CountdownLocalVarParentComponent { }
+// #enddocregion lv
+
+//// View Child version
+// #docregion vc
+@Component({
+ selector: 'countdown-parent-vc',
+ template: `
+ Countdown to Liftoff (via ViewChild)
+ Start
+ Stop
+ {{ seconds() }}
+
+ `,
+ styleUrls: ['demo.css']
+})
+export class CountdownViewChildParentComponent implements AfterViewInit {
+
+ @ViewChild(CountdownTimerComponent)
+ private timerComponent: CountdownTimerComponent;
+
+ seconds() { return 0; }
+
+ ngAfterViewInit() {
+ // Redefine `seconds()` to get from the `CountdownTimerComponent.seconds` ...
+ // but wait a tick first to avoid one-time devMode
+ // unidirectional-data-flow-violation error
+ setTimeout(() => this.seconds = () => this.timerComponent.seconds, 0);
+ }
+
+ start() { this.timerComponent.start(); }
+ stop() { this.timerComponent.stop(); }
+}
+// #enddocregion vc
diff --git a/public/docs/_examples/cb-component-communication/ts/src/app/countdown-timer.component.ts b/public/docs/_examples/cb-component-communication/ts/src/app/countdown-timer.component.ts
new file mode 100644
index 0000000000..a9a1a2fa7c
--- /dev/null
+++ b/public/docs/_examples/cb-component-communication/ts/src/app/countdown-timer.component.ts
@@ -0,0 +1,37 @@
+// #docregion
+import { Component, OnDestroy, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'countdown-timer',
+ template: '{{message}}
'
+})
+export class CountdownTimerComponent implements OnInit, OnDestroy {
+
+ intervalId = 0;
+ message = '';
+ seconds = 11;
+
+ clearTimer() { clearInterval(this.intervalId); }
+
+ ngOnInit() { this.start(); }
+ ngOnDestroy() { this.clearTimer(); }
+
+ start() { this.countDown(); }
+ stop() {
+ this.clearTimer();
+ this.message = `Holding at T-${this.seconds} seconds`;
+ }
+
+ private countDown() {
+ this.clearTimer();
+ this.intervalId = window.setInterval(() => {
+ this.seconds -= 1;
+ if (this.seconds === 0) {
+ this.message = 'Blast off!';
+ } else {
+ if (this.seconds < 0) { this.seconds = 10; } // reset
+ this.message = `T-${this.seconds} seconds and counting`;
+ }
+ }, 1000);
+ }
+}
diff --git a/public/docs/_examples/cb-component-communication/ts/app/hero-child.component.ts b/public/docs/_examples/cb-component-communication/ts/src/app/hero-child.component.ts
similarity index 77%
rename from public/docs/_examples/cb-component-communication/ts/app/hero-child.component.ts
rename to public/docs/_examples/cb-component-communication/ts/src/app/hero-child.component.ts
index 748d543983..7447542a74 100644
--- a/public/docs/_examples/cb-component-communication/ts/app/hero-child.component.ts
+++ b/public/docs/_examples/cb-component-communication/ts/src/app/hero-child.component.ts
@@ -1,6 +1,7 @@
// #docregion
-import {Component, Input} from 'angular2/core';
-import {Hero} from './hero';
+import { Component, Input } from '@angular/core';
+
+import { Hero } from './hero';
@Component({
selector: 'hero-child',
diff --git a/public/docs/_examples/cb-component-communication/ts/src/app/hero-parent.component.ts b/public/docs/_examples/cb-component-communication/ts/src/app/hero-parent.component.ts
new file mode 100644
index 0000000000..bf3861c455
--- /dev/null
+++ b/public/docs/_examples/cb-component-communication/ts/src/app/hero-parent.component.ts
@@ -0,0 +1,20 @@
+// #docregion
+import { Component } from '@angular/core';
+
+import { HEROES } from './hero';
+
+@Component({
+ selector: 'hero-parent',
+ template: `
+ {{master}} controls {{heroes.length}} heroes
+
+
+ `
+})
+export class HeroParentComponent {
+ heroes = HEROES;
+ master: string = 'Master';
+}
+// #enddocregion
diff --git a/public/docs/_examples/cb-component-communication/ts/src/app/hero.ts b/public/docs/_examples/cb-component-communication/ts/src/app/hero.ts
new file mode 100644
index 0000000000..a7b70f48e8
--- /dev/null
+++ b/public/docs/_examples/cb-component-communication/ts/src/app/hero.ts
@@ -0,0 +1,9 @@
+export class Hero {
+ name: string;
+}
+
+export const HEROES = [
+ {name: 'Mr. IQ'},
+ {name: 'Magneta'},
+ {name: 'Bombasto'}
+];
diff --git a/public/docs/_examples/cb-component-communication/ts/src/app/mission.service.ts b/public/docs/_examples/cb-component-communication/ts/src/app/mission.service.ts
new file mode 100644
index 0000000000..25c86866b0
--- /dev/null
+++ b/public/docs/_examples/cb-component-communication/ts/src/app/mission.service.ts
@@ -0,0 +1,25 @@
+// #docregion
+import { Injectable } from '@angular/core';
+import { Subject } from 'rxjs/Subject';
+
+@Injectable()
+export class MissionService {
+
+ // Observable string sources
+ private missionAnnouncedSource = new Subject();
+ private missionConfirmedSource = new Subject();
+
+ // Observable string streams
+ missionAnnounced$ = this.missionAnnouncedSource.asObservable();
+ missionConfirmed$ = this.missionConfirmedSource.asObservable();
+
+ // Service message commands
+ announceMission(mission: string) {
+ this.missionAnnouncedSource.next(mission);
+ }
+
+ confirmMission(astronaut: string) {
+ this.missionConfirmedSource.next(astronaut);
+ }
+}
+// #enddocregion
diff --git a/public/docs/_examples/cb-component-communication/ts/src/app/missioncontrol.component.ts b/public/docs/_examples/cb-component-communication/ts/src/app/missioncontrol.component.ts
new file mode 100644
index 0000000000..a27e9b16b1
--- /dev/null
+++ b/public/docs/_examples/cb-component-communication/ts/src/app/missioncontrol.component.ts
@@ -0,0 +1,43 @@
+// #docregion
+import { Component } from '@angular/core';
+
+import { MissionService } from './mission.service';
+
+@Component({
+ selector: 'mission-control',
+ template: `
+ Mission Control
+ Announce mission
+
+
+ History
+
+ `,
+ providers: [MissionService]
+})
+export class MissionControlComponent {
+ astronauts = ['Lovell', 'Swigert', 'Haise'];
+ history: string[] = [];
+ missions = ['Fly to the moon!',
+ 'Fly to mars!',
+ 'Fly to Vegas!'];
+ nextMission = 0;
+
+ constructor(private missionService: MissionService) {
+ missionService.missionConfirmed$.subscribe(
+ astronaut => {
+ this.history.push(`${astronaut} confirmed the mission`);
+ });
+ }
+
+ announce() {
+ let mission = this.missions[this.nextMission++];
+ this.missionService.announceMission(mission);
+ this.history.push(`Mission "${mission}" announced`);
+ if (this.nextMission >= this.missions.length) { this.nextMission = 0; }
+ }
+}
+// #enddocregion
diff --git a/public/docs/_examples/cb-component-communication/ts/src/app/name-child.component.ts b/public/docs/_examples/cb-component-communication/ts/src/app/name-child.component.ts
new file mode 100644
index 0000000000..bc6d3c6f59
--- /dev/null
+++ b/public/docs/_examples/cb-component-communication/ts/src/app/name-child.component.ts
@@ -0,0 +1,18 @@
+// #docregion
+import { Component, Input } from '@angular/core';
+
+@Component({
+ selector: 'name-child',
+ template: '"{{name}}" '
+})
+export class NameChildComponent {
+ private _name = '';
+
+ @Input()
+ set name(name: string) {
+ this._name = (name && name.trim()) || '';
+ }
+
+ get name(): string { return this._name; }
+}
+// #enddocregion
diff --git a/public/docs/_examples/cb-component-communication/ts/src/app/name-parent.component.ts b/public/docs/_examples/cb-component-communication/ts/src/app/name-parent.component.ts
new file mode 100644
index 0000000000..99753303aa
--- /dev/null
+++ b/public/docs/_examples/cb-component-communication/ts/src/app/name-parent.component.ts
@@ -0,0 +1,15 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'name-parent',
+ template: `
+ Master controls {{names.length}} names
+
+ `
+})
+export class NameParentComponent {
+ // Displays 'Mr. IQ', '', 'Bombasto'
+ names = ['Mr. IQ', ' ', ' Bombasto '];
+}
+// #enddocregion
diff --git a/public/docs/_examples/cb-component-communication/ts/src/app/version-child.component.ts b/public/docs/_examples/cb-component-communication/ts/src/app/version-child.component.ts
new file mode 100644
index 0000000000..89d365cf9f
--- /dev/null
+++ b/public/docs/_examples/cb-component-communication/ts/src/app/version-child.component.ts
@@ -0,0 +1,35 @@
+/* tslint:disable:forin */
+// #docregion
+import { Component, Input, OnChanges, SimpleChange } from '@angular/core';
+
+@Component({
+ selector: 'version-child',
+ template: `
+ Version {{major}}.{{minor}}
+ Change log:
+
+ `
+})
+export class VersionChildComponent implements OnChanges {
+ @Input() major: number;
+ @Input() minor: number;
+ changeLog: string[] = [];
+
+ ngOnChanges(changes: {[propKey: string]: SimpleChange}) {
+ let log: string[] = [];
+ for (let propName in changes) {
+ let changedProp = changes[propName];
+ let to = JSON.stringify(changedProp.currentValue);
+ if (changedProp.isFirstChange()) {
+ log.push(`Initial value of ${propName} set to ${to}`);
+ } else {
+ let from = JSON.stringify(changedProp.previousValue);
+ log.push(`${propName} changed from ${from} to ${to}`);
+ }
+ }
+ this.changeLog.push(log.join(', '));
+ }
+}
+// #enddocregion
diff --git a/public/docs/_examples/cb-component-communication/ts/app/version-parent.component.ts b/public/docs/_examples/cb-component-communication/ts/src/app/version-parent.component.ts
similarity index 76%
rename from public/docs/_examples/cb-component-communication/ts/app/version-parent.component.ts
rename to public/docs/_examples/cb-component-communication/ts/src/app/version-parent.component.ts
index fa3cff767a..bbc9101702 100644
--- a/public/docs/_examples/cb-component-communication/ts/app/version-parent.component.ts
+++ b/public/docs/_examples/cb-component-communication/ts/src/app/version-parent.component.ts
@@ -1,6 +1,5 @@
// #docregion
-import {Component} from 'angular2/core';
-import {VersionChildComponent} from './version-child.component';
+import { Component } from '@angular/core';
@Component({
selector: 'version-parent',
@@ -9,8 +8,7 @@ import {VersionChildComponent} from './version-child.component';
New minor version
New major version
- `,
- directives: [VersionChildComponent]
+ `
})
export class VersionParentComponent {
major: number = 1;
diff --git a/public/docs/_examples/cb-component-communication/ts/app/voter.component.ts b/public/docs/_examples/cb-component-communication/ts/src/app/voter.component.ts
similarity index 78%
rename from public/docs/_examples/cb-component-communication/ts/app/voter.component.ts
rename to public/docs/_examples/cb-component-communication/ts/src/app/voter.component.ts
index 1c5fd16e25..c0cb23abc0 100644
--- a/public/docs/_examples/cb-component-communication/ts/app/voter.component.ts
+++ b/public/docs/_examples/cb-component-communication/ts/src/app/voter.component.ts
@@ -1,5 +1,5 @@
// #docregion
-import {Component, EventEmitter, Input, Output} from 'angular2/core';
+import { Component, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'my-voter',
@@ -14,9 +14,9 @@ export class VoterComponent {
@Output() onVoted = new EventEmitter();
voted = false;
- vote(agreed:boolean){
+ vote(agreed: boolean) {
this.onVoted.emit(agreed);
this.voted = true;
}
}
-// #enddocregion
\ No newline at end of file
+// #enddocregion
diff --git a/public/docs/_examples/cb-component-communication/ts/src/app/votetaker.component.ts b/public/docs/_examples/cb-component-communication/ts/src/app/votetaker.component.ts
new file mode 100644
index 0000000000..87f06161f5
--- /dev/null
+++ b/public/docs/_examples/cb-component-communication/ts/src/app/votetaker.component.ts
@@ -0,0 +1,24 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'vote-taker',
+ template: `
+ Should mankind colonize the Universe?
+ Agree: {{agreed}}, Disagree: {{disagreed}}
+
+
+ `
+})
+export class VoteTakerComponent {
+ agreed = 0;
+ disagreed = 0;
+ voters = ['Mr. IQ', 'Ms. Universe', 'Bombasto'];
+
+ onVoted(agreed: boolean) {
+ agreed ? this.agreed++ : this.disagreed++;
+ }
+}
+// #enddocregion
diff --git a/public/docs/_examples/cb-component-communication/ts/src/demo.css b/public/docs/_examples/cb-component-communication/ts/src/demo.css
new file mode 100644
index 0000000000..b63a8b38dd
--- /dev/null
+++ b/public/docs/_examples/cb-component-communication/ts/src/demo.css
@@ -0,0 +1,9 @@
+/* Component Communication cookbook specific styles */
+.seconds {
+ background-color: black;
+ color: red;
+ font-size: 3em;
+ margin: 0.3em 0;
+ text-align: center;
+ width: 1.5em;
+}
diff --git a/public/docs/_examples/cb-component-communication/ts/src/index.html b/public/docs/_examples/cb-component-communication/ts/src/index.html
new file mode 100644
index 0000000000..64c8a3430f
--- /dev/null
+++ b/public/docs/_examples/cb-component-communication/ts/src/index.html
@@ -0,0 +1,29 @@
+
+
+
+
+ Passing information from parent to child
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ loading...
+
+
+
diff --git a/public/docs/_examples/cb-component-communication/ts/src/main.ts b/public/docs/_examples/cb-component-communication/ts/src/main.ts
new file mode 100644
index 0000000000..311c44b76d
--- /dev/null
+++ b/public/docs/_examples/cb-component-communication/ts/src/main.ts
@@ -0,0 +1,5 @@
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/cb-dependency-injection/e2e-spec.ts b/public/docs/_examples/cb-dependency-injection/e2e-spec.ts
new file mode 100644
index 0000000000..8c9d163d5e
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/e2e-spec.ts
@@ -0,0 +1,102 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by } from 'protractor';
+
+describe('Dependency Injection Cookbook', function () {
+
+ beforeAll(function () {
+ browser.get('');
+ });
+
+ it('should render Logged in User example', function () {
+ let loggedInUser = element.all(by.xpath('//h3[text()="Logged in user"]')).get(0);
+ expect(loggedInUser).toBeDefined();
+ });
+
+ it('"Bombasto" should be the logged in user', function () {
+ let loggedInUser = element.all(by.xpath('//div[text()="Name: Bombasto"]')).get(0);
+ expect(loggedInUser).toBeDefined();
+ });
+
+ it('should render sorted heroes', function () {
+ let sortedHeroes = element.all(by.xpath('//h3[text()="Sorted Heroes" and position()=1]')).get(0);
+ expect(sortedHeroes).toBeDefined();
+ });
+
+ it('Mr. Nice should be in sorted heroes', function () {
+ let sortedHero = element.all(by.xpath('//sorted-heroes/[text()="Mr. Nice" and position()=2]')).get(0);
+ expect(sortedHero).toBeDefined();
+ });
+
+ it('RubberMan should be in sorted heroes', function () {
+ let sortedHero = element.all(by.xpath('//sorted-heroes/[text()="RubberMan" and position()=3]')).get(0);
+ expect(sortedHero).toBeDefined();
+ });
+
+ it('Magma should be in sorted heroes', function () {
+ let sortedHero = element.all(by.xpath('//sorted-heroes/[text()="Magma"]')).get(0);
+ expect(sortedHero).toBeDefined();
+ });
+
+ it('should render Hero of the Month', function () {
+ let heroOfTheMonth = element.all(by.xpath('//h3[text()="Hero of the month"]')).get(0);
+ expect(heroOfTheMonth).toBeDefined();
+ });
+
+ it('should render Hero Bios', function () {
+ let heroBios = element.all(by.xpath('//h3[text()="Hero Bios"]')).get(0);
+ expect(heroBios).toBeDefined();
+ });
+
+ it('should render Magma\'s description in Hero Bios', function () {
+ let magmaText = element.all(by.xpath('//textarea[text()="Hero of all trades"]')).get(0);
+ expect(magmaText).toBeDefined();
+ });
+
+ it('should render Magma\'s phone in Hero Bios and Contacts', function () {
+ let magmaPhone = element.all(by.xpath('//div[text()="Phone #: 555-555-5555"]')).get(0);
+ expect(magmaPhone).toBeDefined();
+ });
+
+ it('should render Hero-of-the-Month runner-ups', function () {
+ let runnersUp = element(by.id('rups1')).getText();
+ expect(runnersUp).toContain('RubberMan, Mr. Nice');
+ });
+
+ it('should render DateLogger log entry in Hero-of-the-Month', function () {
+ let logs = element.all(by.id('logs')).get(0).getText();
+ expect(logs).toContain('INFO: starting up at');
+ });
+
+ it('should highlight Hero Bios and Contacts container when mouseover', function () {
+ let target = element(by.css('div[myHighlight="yellow"]'));
+ let yellow = 'rgba(255, 255, 0, 1)';
+
+ expect(target.getCssValue('background-color')).not.toEqual(yellow);
+ browser.actions().mouseMove(target.getWebElement()).perform();
+ expect(target.getCssValue('background-color')).toEqual(yellow);
+ });
+
+ describe('in Parent Finder', function () {
+ let cathy1 = element(by.css('alex cathy'));
+ let craig1 = element(by.css('alex craig'));
+ let carol1 = element(by.css('alex carol p'));
+ let carol2 = element(by.css('barry carol p'));
+
+ it('"Cathy" should find "Alex" via the component class', function () {
+ expect(cathy1.getText()).toContain('Found Alex via the component');
+ });
+
+ it('"Craig" should not find "Alex" via the base class', function () {
+ expect(craig1.getText()).toContain('Did not find Alex via the base');
+ });
+
+ it('"Carol" within "Alex" should have "Alex" parent', function () {
+ expect(carol1.getText()).toContain('Alex');
+ });
+
+ it('"Carol" within "Barry" should have "Barry" parent', function () {
+ expect(carol2.getText()).toContain('Barry');
+ });
+ });
+});
diff --git a/public/docs/_examples/tutorial/ts/example-config.json b/public/docs/_examples/cb-dependency-injection/ts/example-config.json
similarity index 100%
rename from public/docs/_examples/tutorial/ts/example-config.json
rename to public/docs/_examples/cb-dependency-injection/ts/example-config.json
diff --git a/public/docs/_examples/cb-dependency-injection/ts/plnkr.json b/public/docs/_examples/cb-dependency-injection/ts/plnkr.json
new file mode 100644
index 0000000000..ff0aedca01
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/plnkr.json
@@ -0,0 +1,10 @@
+{
+ "description": "Dependency Injection",
+ "basePath": "src/",
+ "files":[
+ "!**/*.d.ts",
+ "!**/*.js",
+ "!**/*.[1].*"
+ ],
+ "tags":["cookbook"]
+}
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/app/app-routing.module.ts b/public/docs/_examples/cb-dependency-injection/ts/src/app/app-routing.module.ts
new file mode 100644
index 0000000000..09a0592d00
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/app/app-routing.module.ts
@@ -0,0 +1,11 @@
+import { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+
+const routes: Routes = [];
+
+@NgModule({
+ imports: [RouterModule.forRoot(routes)],
+ providers: [],
+ exports: [RouterModule]
+})
+export class AppRoutingModule {}
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/app/app.component.html b/public/docs/_examples/cb-dependency-injection/ts/src/app/app.component.html
new file mode 100644
index 0000000000..a715e484fe
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/app/app.component.html
@@ -0,0 +1,38 @@
+DI Cookbook
+
+
Logged in user
+
Name: {{userContext.name}}
+
Role: {{userContext.role}}
+
+
+
+
Hero Bios
+
+
+
+
+
+
Hero Bios and Contacts
+
+
+
+
+
+
+
+
+
+
+
+
Unsorted Heroes
+
+
+
+
+
Sorted Heroes
+
+
+
+
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/app/app.component.ts b/public/docs/_examples/cb-dependency-injection/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..3045893c58
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/app/app.component.ts
@@ -0,0 +1,29 @@
+// #docregion
+import { Component } from '@angular/core';
+
+// #docregion import-services
+import { LoggerService } from './logger.service';
+import { UserContextService } from './user-context.service';
+import { UserService } from './user.service';
+
+@Component({
+ selector: 'my-app',
+ templateUrl: './app.component.html',
+// #docregion providers
+ providers: [ LoggerService, UserContextService, UserService ]
+// #enddocregion providers
+})
+export class AppComponent {
+// #enddocregion import-services
+
+ private userId: number = 1;
+
+ // #docregion ctor
+ constructor(logger: LoggerService, public userContext: UserContextService) {
+ userContext.loadUser(this.userId);
+ logger.logInfo('AppComponent initialized');
+ }
+ // #enddocregion ctor
+// #docregion import-services
+}
+// #enddocregion import-services
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/app/app.module.ts b/public/docs/_examples/cb-dependency-injection/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..a240e21f7c
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/app/app.module.ts
@@ -0,0 +1,74 @@
+// #docregion
+import { BrowserModule } from '@angular/platform-browser';
+import { FormsModule } from '@angular/forms';
+import { HttpModule } from '@angular/http';
+
+// import { AppRoutingModule } from './app-routing.module';
+import { LocationStrategy,
+ HashLocationStrategy } from '@angular/common';
+import { NgModule } from '@angular/core';
+
+import { HeroData } from './hero-data';
+import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
+
+
+import { AppComponent } from './app.component';
+import { HeroBioComponent } from './hero-bio.component';
+import { HeroBiosComponent,
+ HeroBiosAndContactsComponent } from './hero-bios.component';
+import { HeroOfTheMonthComponent } from './hero-of-the-month.component';
+import { HeroContactComponent } from './hero-contact.component';
+import { HeroesBaseComponent,
+ SortedHeroesComponent } from './sorted-heroes.component';
+import { HighlightDirective } from './highlight.directive';
+import { ParentFinderComponent,
+ AlexComponent,
+ AliceComponent,
+ CarolComponent,
+ ChrisComponent,
+ CraigComponent,
+ CathyComponent,
+ BarryComponent,
+ BethComponent,
+ BobComponent } from './parent-finder.component';
+
+const declarations = [
+ AppComponent,
+ HeroBiosComponent, HeroBiosAndContactsComponent, HeroBioComponent,
+ HeroesBaseComponent, SortedHeroesComponent,
+ HeroOfTheMonthComponent, HeroContactComponent,
+ HighlightDirective,
+ ParentFinderComponent,
+];
+
+const a_components = [AliceComponent, AlexComponent ];
+
+const b_components = [ BarryComponent, BethComponent, BobComponent ];
+
+const c_components = [
+ CarolComponent, ChrisComponent, CraigComponent,
+ CathyComponent
+];
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ FormsModule,
+ HttpModule,
+ InMemoryWebApiModule.forRoot(HeroData)
+ // AppRoutingModule TODO: add routes
+ ],
+ declarations: [
+ declarations,
+ a_components,
+ b_components,
+ c_components,
+ ],
+ bootstrap: [ AppComponent ],
+ // #docregion providers
+ providers: [
+ { provide: LocationStrategy, useClass: HashLocationStrategy }
+ ]
+ // #enddocregion providers
+})
+export class AppModule { }
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/app/date-logger.service.ts b/public/docs/_examples/cb-dependency-injection/ts/src/app/date-logger.service.ts
new file mode 100644
index 0000000000..875779be40
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/app/date-logger.service.ts
@@ -0,0 +1,19 @@
+/* tslint:disable:one-line:check-open-brace*/
+// #docregion
+import { Injectable } from '@angular/core';
+
+import { LoggerService } from './logger.service';
+
+// #docregion date-logger-service
+@Injectable()
+// #docregion date-logger-service-signature
+export class DateLoggerService extends LoggerService
+// #enddocregion date-logger-service-signature
+{
+ logInfo(msg: any) { super.logInfo(stamp(msg)); }
+ logDebug(msg: any) { super.logInfo(stamp(msg)); }
+ logError(msg: any) { super.logError(stamp(msg)); }
+}
+
+function stamp(msg: any) { return msg + ' at ' + new Date(); }
+// #enddocregion date-logger-service
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/app/hero-bio.component.ts b/public/docs/_examples/cb-dependency-injection/ts/src/app/hero-bio.component.ts
new file mode 100644
index 0000000000..84f8e05e66
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/app/hero-bio.component.ts
@@ -0,0 +1,27 @@
+// #docregion
+import { Component, Input, OnInit } from '@angular/core';
+
+import { HeroCacheService } from './hero-cache.service';
+
+// #docregion component
+@Component({
+ selector: 'hero-bio',
+ // #docregion template
+ template: `
+ {{hero.name}}
+
+ `,
+ // #enddocregion template
+ providers: [HeroCacheService]
+})
+
+export class HeroBioComponent implements OnInit {
+ @Input() heroId: number;
+
+ constructor(private heroCache: HeroCacheService) { }
+
+ ngOnInit() { this.heroCache.fetchCachedHero(this.heroId); }
+
+ get hero() { return this.heroCache.hero; }
+}
+// #enddocregion component
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/app/hero-bios.component.ts b/public/docs/_examples/cb-dependency-injection/ts/src/app/hero-bios.component.ts
new file mode 100644
index 0000000000..217c5edcd0
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/app/hero-bios.component.ts
@@ -0,0 +1,48 @@
+// #docplaster
+// #docregion
+import { Component } from '@angular/core';
+
+import { HeroService } from './hero.service';
+import { LoggerService } from './logger.service';
+
+//////// HeroBiosComponent ////
+// #docregion simple
+@Component({
+ selector: 'hero-bios',
+ template: `
+
+
+ `,
+ providers: [HeroService]
+})
+export class HeroBiosComponent {
+// #enddocregion simple
+// #docregion ctor
+ constructor(logger: LoggerService) {
+ logger.logInfo('Creating HeroBiosComponent');
+ }
+// #enddocregion ctor
+// #docregion simple
+}
+// #enddocregion simple
+
+//////// HeroBiosAndContactsComponent ////
+// #docregion hero-bios-and-contacts
+@Component({
+ selector: 'hero-bios-and-contacts',
+ // #docregion template
+ template: `
+
+
+ `,
+ // #enddocregion template
+ // #docregion class-provider
+ providers: [HeroService]
+ // #enddocregion class-provider
+})
+export class HeroBiosAndContactsComponent {
+ constructor(logger: LoggerService) {
+ logger.logInfo('Creating HeroBiosAndContactsComponent');
+ }
+}
+// #enddocregion hero-bios-and-contacts
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/app/hero-cache.service.ts b/public/docs/_examples/cb-dependency-injection/ts/src/app/hero-cache.service.ts
new file mode 100644
index 0000000000..6dbc7a0c4f
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/app/hero-cache.service.ts
@@ -0,0 +1,20 @@
+// #docregion
+import { Injectable } from '@angular/core';
+
+import { Hero } from './hero';
+import { HeroService } from './hero.service';
+
+// #docregion service
+@Injectable()
+export class HeroCacheService {
+ hero: Hero;
+ constructor(private heroService: HeroService) {}
+
+ fetchCachedHero(id: number) {
+ if (!this.hero) {
+ this.hero = this.heroService.getHeroById(id);
+ }
+ return this.hero;
+ }
+}
+// #enddocregion service
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/app/hero-contact.component.ts b/public/docs/_examples/cb-dependency-injection/ts/src/app/hero-contact.component.ts
new file mode 100644
index 0000000000..add6df91c5
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/app/hero-contact.component.ts
@@ -0,0 +1,40 @@
+// #docplaster
+// #docregion
+import { Component, Host, Optional } from '@angular/core';
+
+import { HeroCacheService } from './hero-cache.service';
+import { LoggerService } from './logger.service';
+
+// #docregion component
+@Component({
+ selector: 'hero-contact',
+ template: `
+ Phone #: {{phoneNumber}}
+ !!!
`
+})
+export class HeroContactComponent {
+
+ hasLogger = false;
+
+ constructor(
+ // #docregion ctor-params
+ @Host() // limit to the host component's instance of the HeroCacheService
+ private heroCache: HeroCacheService,
+
+ @Host() // limit search for logger; hides the application-wide logger
+ @Optional() // ok if the logger doesn't exist
+ private loggerService: LoggerService
+ // #enddocregion ctor-params
+ ) {
+ if (loggerService) {
+ this.hasLogger = true;
+ loggerService.logInfo('HeroContactComponent can log!');
+ }
+ // #docregion ctor
+ }
+ // #enddocregion ctor
+
+ get phoneNumber() { return this.heroCache.hero.phone; }
+
+}
+// #enddocregion component
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/app/hero-data.ts b/public/docs/_examples/cb-dependency-injection/ts/src/app/hero-data.ts
new file mode 100644
index 0000000000..10cdbcaab1
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/app/hero-data.ts
@@ -0,0 +1,14 @@
+// #docregion
+import { Hero } from './hero';
+
+export class HeroData {
+ createDb() {
+ let heroes = [
+ new Hero(1, 'Windstorm'),
+ new Hero(2, 'Bombasto'),
+ new Hero(3, 'Magneta'),
+ new Hero(4, 'Tornado')
+ ];
+ return {heroes};
+ }
+}
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/app/hero-of-the-month.component.1.ts b/public/docs/_examples/cb-dependency-injection/ts/src/app/hero-of-the-month.component.1.ts
new file mode 100644
index 0000000000..da2c57aeaf
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/app/hero-of-the-month.component.1.ts
@@ -0,0 +1,26 @@
+// Illustrative (not used), mini-version of the actual HeroOfTheMonthComponent
+// Injecting with the MinimalLogger "interface-class"
+import { Component, NgModule } from '@angular/core';
+import { LoggerService } from './logger.service';
+import { MinimalLogger } from './minimal-logger.service';
+
+// #docregion
+@Component({
+ selector: 'hero-of-the-month',
+ templateUrl: './hero-of-the-month.component.html',
+ // Todo: move this aliasing, `useExisting` provider to the AppModule
+ providers: [{ provide: MinimalLogger, useExisting: LoggerService }]
+})
+export class HeroOfTheMonthComponent {
+ logs: string[] = [];
+ constructor(logger: MinimalLogger) {
+ logger.logInfo('starting up');
+ }
+}
+// #enddocregion
+
+// This NgModule exists only to avoid the Angular language service's "undeclared component" error
+@NgModule({
+ declarations: [ HeroOfTheMonthComponent ]
+})
+class NoopModule {}
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/app/hero-of-the-month.component.html b/public/docs/_examples/cb-dependency-injection/ts/src/app/hero-of-the-month.component.html
new file mode 100644
index 0000000000..f0ae619d6a
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/app/hero-of-the-month.component.html
@@ -0,0 +1,9 @@
+{{title}}
+Winner: {{heroOfTheMonth.name}}
+Reason for award: {{heroOfTheMonth.description}}
+Runners-up: {{runnersUp}}
+
+Logs:
+
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/app/hero-of-the-month.component.ts b/public/docs/_examples/cb-dependency-injection/ts/src/app/hero-of-the-month.component.ts
new file mode 100644
index 0000000000..90ad13d639
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/app/hero-of-the-month.component.ts
@@ -0,0 +1,63 @@
+/* tslint:disable:one-line:check-open-brace*/
+// #docplaster
+// #docregion injection-token
+import { InjectionToken } from '@angular/core';
+
+export const TITLE = new InjectionToken('title');
+// #enddocregion injection-token
+
+// #docregion hero-of-the-month
+import { Component, Inject } from '@angular/core';
+
+import { DateLoggerService } from './date-logger.service';
+import { Hero } from './hero';
+import { HeroService } from './hero.service';
+import { LoggerService } from './logger.service';
+import { MinimalLogger } from './minimal-logger.service';
+import { RUNNERS_UP,
+ runnersUpFactory } from './runners-up';
+
+// #enddocregion hero-of-the-month
+// #docregion some-hero
+const someHero = new Hero(42, 'Magma', 'Had a great month!', '555-555-5555');
+// #enddocregion some-hero
+
+// #docregion hero-of-the-month
+@Component({
+ selector: 'hero-of-the-month',
+ templateUrl: './hero-of-the-month.component.html',
+ providers: [
+ // #docregion use-value
+ { provide: Hero, useValue: someHero },
+ // #docregion provide-injection-token
+ { provide: TITLE, useValue: 'Hero of the Month' },
+ // #enddocregion provide-injection-token
+ // #enddocregion use-value
+ // #docregion use-class
+ { provide: HeroService, useClass: HeroService },
+ { provide: LoggerService, useClass: DateLoggerService },
+ // #enddocregion use-class
+ // #docregion use-existing
+ { provide: MinimalLogger, useExisting: LoggerService },
+ // #enddocregion use-existing
+ // #docregion provide-injection-token, use-factory
+ { provide: RUNNERS_UP, useFactory: runnersUpFactory(2), deps: [Hero, HeroService] }
+ // #enddocregion provide-injection-token, use-factory
+ ]
+})
+export class HeroOfTheMonthComponent {
+ logs: string[] = [];
+
+// #docregion ctor-signature
+ constructor(
+ logger: MinimalLogger,
+ public heroOfTheMonth: Hero,
+ @Inject(RUNNERS_UP) public runnersUp: string,
+ @Inject(TITLE) public title: string)
+// #enddocregion ctor-signature
+ {
+ this.logs = logger.logs;
+ logger.logInfo('starting up');
+ }
+}
+// #enddocregion hero-of-the-month
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/app/hero.service.ts b/public/docs/_examples/cb-dependency-injection/ts/src/app/hero.service.ts
new file mode 100644
index 0000000000..2063c30d7a
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/app/hero.service.ts
@@ -0,0 +1,22 @@
+// #docregion
+import { Injectable } from '@angular/core';
+import { Hero } from './hero';
+
+@Injectable()
+export class HeroService {
+
+ // TODO move to database
+ private heroes: Array = [
+ new Hero(1, 'RubberMan', 'Hero of many talents', '123-456-7899'),
+ new Hero(2, 'Magma', 'Hero of all trades', '555-555-5555'),
+ new Hero(3, 'Mr. Nice', 'The name says it all', '111-222-3333')
+ ];
+
+ getHeroById(id: number): Hero {
+ return this.heroes.find(hero => hero.id === id);
+ }
+
+ getAllHeroes(): Array {
+ return this.heroes;
+ }
+}
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/app/hero.ts b/public/docs/_examples/cb-dependency-injection/ts/src/app/hero.ts
new file mode 100644
index 0000000000..c17069e727
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/app/hero.ts
@@ -0,0 +1,9 @@
+// #docregion
+export class Hero {
+ constructor(
+ public id: number,
+ public name: string,
+ public description?: string,
+ public phone?: string) {
+ }
+}
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/app/highlight.directive.ts b/public/docs/_examples/cb-dependency-injection/ts/src/app/highlight.directive.ts
new file mode 100644
index 0000000000..e220114daa
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/app/highlight.directive.ts
@@ -0,0 +1,29 @@
+// #docplaster
+// #docregion
+import { Directive, ElementRef, HostListener, Input } from '@angular/core';
+
+@Directive({
+ selector: '[myHighlight]'
+})
+export class HighlightDirective {
+
+ @Input('myHighlight') highlightColor: string;
+
+ private el: HTMLElement;
+
+ constructor(el: ElementRef) {
+ this.el = el.nativeElement;
+ }
+
+ @HostListener('mouseenter') onMouseEnter() {
+ this.highlight(this.highlightColor || 'cyan');
+ }
+
+ @HostListener('mouseleave') onMouseLeave() {
+ this.highlight(null);
+ }
+
+ private highlight(color: string) {
+ this.el.style.backgroundColor = color;
+ }
+}
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/app/logger.service.ts b/public/docs/_examples/cb-dependency-injection/ts/src/app/logger.service.ts
new file mode 100644
index 0000000000..df8ee6b9c7
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/app/logger.service.ts
@@ -0,0 +1,16 @@
+// #docregion
+import { Injectable } from '@angular/core';
+
+@Injectable()
+export class LoggerService {
+ logs: string[] = [];
+
+ logInfo(msg: any) { this.log(`INFO: ${msg}`); }
+ logDebug(msg: any) { this.log(`DEBUG: ${msg}`); }
+ logError(msg: any) { this.log(`ERROR: ${msg}`, true); }
+
+ private log(msg: any, isErr = false) {
+ this.logs.push(msg);
+ isErr ? console.error(msg) : console.log(msg);
+ }
+}
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/app/minimal-logger.service.ts b/public/docs/_examples/cb-dependency-injection/ts/src/app/minimal-logger.service.ts
new file mode 100644
index 0000000000..d87fa594d1
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/app/minimal-logger.service.ts
@@ -0,0 +1,22 @@
+// #docregion
+// Class used as a "narrowing" interface that exposes a minimal logger
+// Other members of the actual implementation are invisible
+export abstract class MinimalLogger {
+ logs: string[];
+ logInfo: (msg: string) => void;
+}
+// #enddocregion
+
+/*
+// Transpiles to:
+// #docregion minimal-logger-transpiled
+ var MinimalLogger = (function () {
+ function MinimalLogger() {}
+ return MinimalLogger;
+ }());
+ exports("MinimalLogger", MinimalLogger);
+// #enddocregion minimal-logger-transpiled
+*/
+
+// See http://stackoverflow.com/questions/43154832/unexpected-token-export-in-angular-app-with-systemjs-and-typescript/
+export const _ = 0;
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/app/parent-finder.component.ts b/public/docs/_examples/cb-dependency-injection/ts/src/app/parent-finder.component.ts
new file mode 100644
index 0000000000..c6f208f79b
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/app/parent-finder.component.ts
@@ -0,0 +1,215 @@
+/* tslint:disable:no-unused-variable component-selector-name one-line check-open-brace */
+/* tslint:disable:*/
+// #docplaster
+// #docregion
+import { Component, forwardRef, Optional, SkipSelf } from '@angular/core';
+
+// A component base class (see AlexComponent)
+export abstract class Base { name = 'Count Basie'; }
+
+// Marker class, used as an interface
+// #docregion parent
+export abstract class Parent { name: string; }
+// #enddocregion parent
+
+const DifferentParent = Parent;
+
+// #docregion provide-parent, provide-the-parent
+// Helper method to provide the current component instance in the name of a `parentType`.
+// #enddocregion provide-the-parent
+// The `parentType` defaults to `Parent` when omitting the second parameter.
+// #docregion provide-the-parent
+const provideParent =
+// #enddocregion provide-parent, provide-the-parent
+// #docregion provide-parent
+ (component: any, parentType?: any) => {
+ return { provide: parentType || Parent, useExisting: forwardRef(() => component) };
+ };
+// #enddocregion provide-parent
+
+// Simpler syntax version that always provides the component in the name of `Parent`.
+const provideTheParent =
+// #docregion provide-the-parent
+ (component: any) => {
+ return { provide: Parent, useExisting: forwardRef(() => component) };
+ };
+// #enddocregion provide-the-parent
+
+
+///////// C - Child //////////
+// #docregion carol
+const templateC = `
+
+
{{name}}
+
My parent is {{parent?.name}}
+
`;
+
+@Component({
+ selector: 'carol',
+ template: templateC
+})
+// #docregion carol-class
+export class CarolComponent {
+ name= 'Carol';
+ // #docregion carol-ctor
+ constructor( @Optional() public parent: Parent ) { }
+ // #enddocregion carol-ctor
+}
+// #enddocregion carol-class
+// #enddocregion carol
+
+@Component({
+ selector: 'chris',
+ template: templateC
+})
+export class ChrisComponent {
+ name= 'Chris';
+ constructor( @Optional() public parent: Parent ) { }
+}
+
+////// Craig ///////////
+/**
+ * Show we cannot inject a parent by its base class.
+ */
+// #docregion craig
+@Component({
+ selector: 'craig',
+ template: `
+
+
Craig
+ {{alex ? 'Found' : 'Did not find'}} Alex via the base class.
+ `
+})
+export class CraigComponent {
+ constructor( @Optional() public alex: Base ) { }
+}
+// #enddocregion craig
+
+//////// B - Parent /////////
+// #docregion barry
+const templateB = `
+
+
+
{{name}}
+
My parent is {{parent?.name}}
+
+
+
+
`;
+
+@Component({
+ selector: 'barry',
+ template: templateB,
+ providers: [{ provide: Parent, useExisting: forwardRef(() => BarryComponent) }]
+})
+export class BarryComponent implements Parent {
+ name = 'Barry';
+// #docregion barry-ctor
+ constructor( @SkipSelf() @Optional() public parent: Parent ) { }
+// #enddocregion barry-ctor
+}
+// #enddocregion barry
+
+@Component({
+ selector: 'bob',
+ template: templateB,
+ providers: [ provideParent(BobComponent) ]
+})
+export class BobComponent implements Parent {
+ name= 'Bob';
+ constructor( @SkipSelf() @Optional() public parent: Parent ) { }
+}
+
+@Component({
+ selector: 'beth',
+ template: templateB,
+// #docregion beth-providers
+ providers: [ provideParent(BethComponent, DifferentParent) ]
+// #enddocregion beth-providers
+})
+export class BethComponent implements Parent {
+ name= 'Beth';
+ constructor( @SkipSelf() @Optional() public parent: Parent ) { }
+}
+
+///////// A - Grandparent //////
+
+// #docregion alex, alex-1
+@Component({
+ selector: 'alex',
+ template: `
+
+
{{name}}
+
+
+
+ `,
+// #enddocregion alex-1
+// #docregion alex-providers
+ providers: [{ provide: Parent, useExisting: forwardRef(() => AlexComponent) }],
+// #enddocregion alex-providers
+// #docregion alex-1
+})
+// #enddocregion alex-1
+// Todo: Add `... implements Parent` to class signature
+// #docregion alex-1
+// #docregion alex-class-signature
+export class AlexComponent extends Base
+// #enddocregion alex-class-signature
+{
+ name= 'Alex';
+}
+// #enddocregion alex, alex-1
+
+/////
+
+// #docregion alice
+@Component({
+ selector: 'alice',
+ template: `
+
+
{{name}}
+
+
+
+
+ `,
+// #docregion alice-providers
+ providers: [ provideParent(AliceComponent) ]
+// #enddocregion alice-providers
+})
+// #docregion alice-class-signature
+export class AliceComponent implements Parent
+// #enddocregion alice-class-signature
+{
+ name= 'Alice';
+}
+// #enddocregion alice
+
+////// Cathy ///////////
+/**
+ * Show we can inject a parent by component type
+ */
+// #docregion cathy
+@Component({
+ selector: 'cathy',
+ template: `
+
+
Cathy
+ {{alex ? 'Found' : 'Did not find'}} Alex via the component class.
+ `
+})
+export class CathyComponent {
+ constructor( @Optional() public alex: AlexComponent ) { }
+}
+// #enddocregion cathy
+
+///////// ParentFinder //////
+@Component({
+ selector: 'parent-finder',
+ template: `
+ Parent Finder
+
+ `
+})
+export class ParentFinderComponent { }
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/app/runners-up.ts b/public/docs/_examples/cb-dependency-injection/ts/src/app/runners-up.ts
new file mode 100644
index 0000000000..0ce81ca55c
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/app/runners-up.ts
@@ -0,0 +1,26 @@
+// #docplaster
+// #docregion
+import { InjectionToken } from '@angular/core';
+
+import { Hero } from './hero';
+import { HeroService } from './hero.service';
+
+// #docregion runners-up
+export const RUNNERS_UP = new InjectionToken('RunnersUp');
+// #enddocregion runners-up
+
+// #docregion factory-synopsis
+export function runnersUpFactory(take: number) {
+ return (winner: Hero, heroService: HeroService): string => {
+ /* ... */
+// #enddocregion factory-synopsis
+ return heroService
+ .getAllHeroes()
+ .filter((hero) => hero.name !== winner.name)
+ .map(hero => hero.name)
+ .slice(0, Math.max(0, take))
+ .join(', ');
+// #docregion factory-synopsis
+ };
+};
+// #enddocregion factory-synopsis
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/app/sorted-heroes.component.ts b/public/docs/_examples/cb-dependency-injection/ts/src/app/sorted-heroes.component.ts
new file mode 100644
index 0000000000..8cb6e3c69c
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/app/sorted-heroes.component.ts
@@ -0,0 +1,52 @@
+// #docplaster
+// #docregion
+import { Component, OnInit } from '@angular/core';
+
+import { Hero } from './hero';
+import { HeroService } from './hero.service';
+
+/////// HeroesBaseComponent /////
+// #docregion heroes-base, injection
+@Component({
+ selector: 'unsorted-heroes',
+ template: `{{hero.name}}
`,
+ providers: [HeroService]
+})
+export class HeroesBaseComponent implements OnInit {
+ constructor(private heroService: HeroService) { }
+// #enddocregion injection
+
+ heroes: Array;
+
+ ngOnInit() {
+ this.heroes = this.heroService.getAllHeroes();
+ this.afterGetHeroes();
+ }
+
+ // Post-process heroes in derived class override.
+ protected afterGetHeroes() {}
+
+// #docregion injection
+}
+// #enddocregion heroes-base,injection
+
+/////// SortedHeroesComponent /////
+// #docregion sorted-heroes
+@Component({
+ selector: 'sorted-heroes',
+ template: `{{hero.name}}
`,
+ providers: [HeroService]
+})
+export class SortedHeroesComponent extends HeroesBaseComponent {
+ constructor(heroService: HeroService) {
+ super(heroService);
+ }
+
+ protected afterGetHeroes() {
+ this.heroes = this.heroes.sort((h1, h2) => {
+ return h1.name < h2.name ? -1 :
+ (h1.name > h2.name ? 1 : 0);
+ });
+ }
+}
+// #enddocregion sorted-heroes
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/app/user-context.service.ts b/public/docs/_examples/cb-dependency-injection/ts/src/app/user-context.service.ts
new file mode 100644
index 0000000000..ed394fc734
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/app/user-context.service.ts
@@ -0,0 +1,33 @@
+// #docplaster
+// #docregion
+import { Injectable } from '@angular/core';
+
+import { LoggerService } from './logger.service';
+import { UserService } from './user.service';
+
+// #docregion injectables, injectable
+@Injectable()
+export class UserContextService {
+// #enddocregion injectables, injectable
+ name: string;
+ role: string;
+ loggedInSince: Date;
+
+ // #docregion ctor, injectables
+ constructor(private userService: UserService, private loggerService: LoggerService) {
+ // #enddocregion ctor, injectables
+ this.loggedInSince = new Date();
+ // #docregion ctor, injectables
+ }
+ // #enddocregion ctor, injectables
+
+ loadUser(userId: number) {
+ let user = this.userService.getUserById(userId);
+ this.name = user.name;
+ this.role = user.role;
+
+ this.loggerService.logDebug('loaded User');
+ }
+// #docregion injectables, injectable
+}
+// #enddocregion injectables, injectable
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/app/user.service.ts b/public/docs/_examples/cb-dependency-injection/ts/src/app/user.service.ts
new file mode 100644
index 0000000000..c48b025a08
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/app/user.service.ts
@@ -0,0 +1,10 @@
+// #docregion
+import { Injectable } from '@angular/core';
+
+@Injectable()
+export class UserService {
+
+ getUserById(userId: number): any {
+ return {name: 'Bombasto', role: 'Admin'};
+ }
+}
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/index.html b/public/docs/_examples/cb-dependency-injection/ts/src/index.html
new file mode 100644
index 0000000000..0308c72155
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/index.html
@@ -0,0 +1,29 @@
+
+
+
+
+
+ Dependency Injection
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading app...
+
+
+
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/main.ts b/public/docs/_examples/cb-dependency-injection/ts/src/main.ts
new file mode 100644
index 0000000000..6b6532d428
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/main.ts
@@ -0,0 +1,5 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/cb-dependency-injection/ts/src/sample.css b/public/docs/_examples/cb-dependency-injection/ts/src/sample.css
new file mode 100644
index 0000000000..a8b59efd05
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/src/sample.css
@@ -0,0 +1,26 @@
+.di-component{
+ padding: 10px;
+ width:300px;
+ margin-bottom: 10px;
+}
+div[myHighlight] {
+ padding: 2px 8px;
+}
+
+/* Parent Finder */
+.a, .b, .c {
+ margin: 6px 2px 6px;
+ padding: 4px 6px;
+}
+.a {
+ border: solid 2px black;
+}
+.b {
+ background: lightblue;
+ border: solid 1px darkblue;
+ display: flex;
+}
+.c {
+ background: pink;
+ border: solid 1px red;
+}
\ No newline at end of file
diff --git a/public/docs/_examples/cb-dynamic-component-loader/e2e-spec.ts b/public/docs/_examples/cb-dynamic-component-loader/e2e-spec.ts
new file mode 100644
index 0000000000..5036ac2a88
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-component-loader/e2e-spec.ts
@@ -0,0 +1,21 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by } from 'protractor';
+
+/* tslint:disable:quotemark */
+describe('Dynamic Component Loader', function () {
+
+ beforeEach(function () {
+ browser.get('');
+ });
+
+ it('should load ad banner', function () {
+ let headline = element(by.xpath("//h4[text()='Featured Hero Profile']"));
+ let name = element(by.xpath("//h3[text()='Bombasto']"));
+ let bio = element(by.xpath("//p[text()='Brave as they come']"));
+
+ expect(name).toBeDefined();
+ expect(headline).toBeDefined();
+ expect(bio).toBeDefined();
+ });
+});
diff --git a/public/docs/_examples/upgrade/ts/classes/app/css/.gitkeep b/public/docs/_examples/cb-dynamic-component-loader/ts/example-config.json
similarity index 100%
rename from public/docs/_examples/upgrade/ts/classes/app/css/.gitkeep
rename to public/docs/_examples/cb-dynamic-component-loader/ts/example-config.json
diff --git a/public/docs/_examples/cb-dynamic-component-loader/ts/plnkr.json b/public/docs/_examples/cb-dynamic-component-loader/ts/plnkr.json
new file mode 100644
index 0000000000..c43fb15c12
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-component-loader/ts/plnkr.json
@@ -0,0 +1,9 @@
+{
+ "description": "Dynamic Component Loader",
+ "basePath": "src/",
+ "files":[
+ "!**/*.d.ts",
+ "!**/*.js"
+ ],
+ "tags":["cookbook component"]
+}
diff --git a/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/ad-banner.component.ts b/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/ad-banner.component.ts
new file mode 100644
index 0000000000..8489fce5b2
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/ad-banner.component.ts
@@ -0,0 +1,57 @@
+// #docregion
+import { Component, Input, AfterViewInit, ViewChild, ComponentFactoryResolver, OnDestroy } from '@angular/core';
+
+import { AdDirective } from './ad.directive';
+import { AdItem } from './ad-item';
+import { AdComponent } from './ad.component';
+
+@Component({
+ selector: 'add-banner',
+ // #docregion ad-host
+ template: `
+
+
Advertisements
+
+
+ `
+ // #enddocregion ad-host
+})
+// #docregion class
+export class AdBannerComponent implements AfterViewInit, OnDestroy {
+ @Input() ads: AdItem[];
+ currentAddIndex: number = -1;
+ @ViewChild(AdDirective) adHost: AdDirective;
+ subscription: any;
+ interval: any;
+
+ constructor(private _componentFactoryResolver: ComponentFactoryResolver) { }
+
+ ngAfterViewInit() {
+ this.loadComponent();
+ this.getAds();
+ }
+
+ ngOnDestroy() {
+ clearInterval(this.interval);
+ }
+
+ loadComponent() {
+ this.currentAddIndex = (this.currentAddIndex + 1) % this.ads.length;
+ let adItem = this.ads[this.currentAddIndex];
+
+ let componentFactory = this._componentFactoryResolver.resolveComponentFactory(adItem.component);
+
+ let viewContainerRef = this.adHost.viewContainerRef;
+ viewContainerRef.clear();
+
+ let componentRef = viewContainerRef.createComponent(componentFactory);
+ (componentRef.instance).data = adItem.data;
+ }
+
+ getAds() {
+ this.interval = setInterval(() => {
+ this.loadComponent();
+ }, 3000);
+ }
+}
+// #enddocregion class
diff --git a/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/ad-item.ts b/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/ad-item.ts
new file mode 100644
index 0000000000..ef8ca70577
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/ad-item.ts
@@ -0,0 +1,6 @@
+// #docregion
+import { Type } from '@angular/core';
+
+export class AdItem {
+ constructor(public component: Type, public data: any) {}
+}
diff --git a/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/ad.component.ts b/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/ad.component.ts
new file mode 100644
index 0000000000..dee3b47953
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/ad.component.ts
@@ -0,0 +1,4 @@
+// #docregion
+export interface AdComponent {
+ data: any;
+}
diff --git a/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/ad.directive.ts b/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/ad.directive.ts
new file mode 100644
index 0000000000..312e605228
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/ad.directive.ts
@@ -0,0 +1,10 @@
+// #docregion
+import { Directive, ViewContainerRef } from '@angular/core';
+
+@Directive({
+ selector: '[ad-host]',
+})
+export class AdDirective {
+ constructor(public viewContainerRef: ViewContainerRef) { }
+}
+
diff --git a/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/ad.service.ts b/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/ad.service.ts
new file mode 100644
index 0000000000..91b0758771
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/ad.service.ts
@@ -0,0 +1,23 @@
+// #docregion
+import { Injectable } from '@angular/core';
+
+import { HeroJobAdComponent } from './hero-job-ad.component';
+import { HeroProfileComponent } from './hero-profile.component';
+import { AdItem } from './ad-item';
+
+@Injectable()
+export class AdService {
+ getAds() {
+ return [
+ new AdItem(HeroProfileComponent, {name: 'Bombasto', bio: 'Brave as they come'}),
+
+ new AdItem(HeroProfileComponent, {name: 'Dr IQ', bio: 'Smart as they come'}),
+
+ new AdItem(HeroJobAdComponent, {headline: 'Hiring for several positions',
+ body: 'Submit your resume today!'}),
+
+ new AdItem(HeroJobAdComponent, {headline: 'Openings in all departments',
+ body: 'Apply today'}),
+ ];
+ }
+}
diff --git a/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/app.component.ts b/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..89359ccdf6
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/app.component.ts
@@ -0,0 +1,24 @@
+// #docregion
+import { Component, OnInit } from '@angular/core';
+
+import { AdService } from './ad.service';
+import { AdItem } from './ad-item';
+
+@Component({
+ selector: 'my-app',
+ template: `
+
+ `
+})
+export class AppComponent implements OnInit {
+ ads: AdItem[];
+
+ constructor(private adService: AdService) {}
+
+ ngOnInit() {
+ this.ads = this.adService.getAds();
+ }
+}
+
diff --git a/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/app.module.ts b/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..a65d394709
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/app.module.ts
@@ -0,0 +1,27 @@
+// #docregion
+import { BrowserModule } from '@angular/platform-browser';
+import { NgModule } from '@angular/core';
+import { AppComponent } from './app.component';
+import { HeroJobAdComponent } from './hero-job-ad.component';
+import { AdBannerComponent } from './ad-banner.component';
+import { HeroProfileComponent } from './hero-profile.component';
+import { AdDirective } from './ad.directive';
+import { AdService } from './ad.service';
+
+@NgModule({
+ imports: [ BrowserModule ],
+ providers: [AdService],
+ declarations: [ AppComponent,
+ AdBannerComponent,
+ HeroJobAdComponent,
+ HeroProfileComponent,
+ AdDirective ],
+ // #docregion entry-components
+ entryComponents: [ HeroJobAdComponent, HeroProfileComponent ],
+ // #enddocregion entry-components
+ bootstrap: [ AppComponent ]
+})
+export class AppModule {
+ constructor() {}
+}
+
diff --git a/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/hero-job-ad.component.ts b/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/hero-job-ad.component.ts
new file mode 100644
index 0000000000..675a03d0e0
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/hero-job-ad.component.ts
@@ -0,0 +1,19 @@
+// #docregion
+import { Component, Input } from '@angular/core';
+
+import { AdComponent } from './ad.component';
+
+@Component({
+ template: `
+
+
{{data.headline}}
+
+ {{data.body}}
+
+ `
+})
+export class HeroJobAdComponent implements AdComponent {
+ @Input() data: any;
+
+}
+
diff --git a/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/hero-profile.component.ts b/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/hero-profile.component.ts
new file mode 100644
index 0000000000..1c266db3c9
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-component-loader/ts/src/app/hero-profile.component.ts
@@ -0,0 +1,22 @@
+// #docregion
+import { Component, Input } from '@angular/core';
+
+import { AdComponent } from './ad.component';
+
+@Component({
+ template: `
+
+
Featured Hero Profile
+
{{data.name}}
+
+
{{data.bio}}
+
+
Hire this hero today!
+
+ `
+})
+export class HeroProfileComponent implements AdComponent {
+ @Input() data: any;
+}
+
+
diff --git a/public/docs/_examples/cb-dynamic-component-loader/ts/src/index.html b/public/docs/_examples/cb-dynamic-component-loader/ts/src/index.html
new file mode 100644
index 0000000000..9239d91d9a
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-component-loader/ts/src/index.html
@@ -0,0 +1,26 @@
+
+
+
+
+
+ Dynamic Component Loader
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading app...
+
+
+
diff --git a/public/docs/_examples/cb-dynamic-component-loader/ts/src/main.ts b/public/docs/_examples/cb-dynamic-component-loader/ts/src/main.ts
new file mode 100644
index 0000000000..53d16fa43a
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-component-loader/ts/src/main.ts
@@ -0,0 +1,6 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
+
diff --git a/public/docs/_examples/cb-dynamic-component-loader/ts/src/sample.css b/public/docs/_examples/cb-dynamic-component-loader/ts/src/sample.css
new file mode 100644
index 0000000000..7a2ca1f2dc
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-component-loader/ts/src/sample.css
@@ -0,0 +1,23 @@
+.hero-profile {
+ border: 1px solid gray;
+ padding: 5px;
+ padding-bottom: 20px;
+ padding-left: 20px;
+ border-radius: 10px;
+ background-color: lightgreen;
+ color: black;
+}
+
+.job-ad {
+ border: 1px solid gray;
+ padding: 5px;
+ padding-bottom: 20px;
+ padding-left: 20px;
+ border-radius: 10px;
+ background-color: lightblue;
+ color: black;
+}
+
+.ad-banner {
+ width: 400px;
+}
\ No newline at end of file
diff --git a/public/docs/_examples/cb-dynamic-form/e2e-spec.ts b/public/docs/_examples/cb-dynamic-form/e2e-spec.ts
new file mode 100644
index 0000000000..408ac75766
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-form/e2e-spec.ts
@@ -0,0 +1,29 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by } from 'protractor';
+
+/* tslint:disable:quotemark */
+describe('Dynamic Form', function () {
+
+ beforeAll(function () {
+ browser.get('');
+ });
+
+ it('should submit form', function () {
+ let firstNameElement = element.all(by.css('input[id=firstName]')).get(0);
+ expect(firstNameElement.getAttribute('value')).toEqual('Bombasto');
+
+ let emailElement = element.all(by.css('input[id=emailAddress]')).get(0);
+ let email = 'test@test.com';
+ emailElement.sendKeys(email);
+ expect(emailElement.getAttribute('value')).toEqual(email);
+
+ element(by.css('select option[value="solid"]')).click();
+
+ let saveButton = element.all(by.css('button')).get(0);
+ saveButton.click().then(function(){
+ expect(element(by.xpath("//strong[contains(text(),'Saved the following values')]")).isPresent()).toBe(true);
+ });
+ });
+
+});
diff --git a/public/docs/_examples/upgrade/ts/classes/app/img/.gitkeep b/public/docs/_examples/cb-dynamic-form/ts/example-config.json
similarity index 100%
rename from public/docs/_examples/upgrade/ts/classes/app/img/.gitkeep
rename to public/docs/_examples/cb-dynamic-form/ts/example-config.json
diff --git a/public/docs/_examples/cb-dynamic-form/ts/plnkr.json b/public/docs/_examples/cb-dynamic-form/ts/plnkr.json
new file mode 100644
index 0000000000..1f50b4a992
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-form/ts/plnkr.json
@@ -0,0 +1,10 @@
+{
+ "description": "Dynamic Form",
+ "basePath": "src/",
+ "files":[
+ "!**/*.d.ts",
+ "!**/*.js",
+ "!**/*.[1].*"
+ ],
+ "tags":["cookbook"]
+}
diff --git a/public/docs/_examples/cb-dynamic-form/ts/src/app/app.component.ts b/public/docs/_examples/cb-dynamic-form/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..582daced2e
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-form/ts/src/app/app.component.ts
@@ -0,0 +1,22 @@
+// #docregion
+import { Component } from '@angular/core';
+
+import { QuestionService } from './question.service';
+
+@Component({
+ selector: 'my-app',
+ template: `
+
+
Job Application for Heroes
+
+
+ `,
+ providers: [QuestionService]
+})
+export class AppComponent {
+ questions: any[];
+
+ constructor(service: QuestionService) {
+ this.questions = service.getQuestions();
+ }
+}
diff --git a/public/docs/_examples/cb-dynamic-form/ts/src/app/app.module.ts b/public/docs/_examples/cb-dynamic-form/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..7a68e45a92
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-form/ts/src/app/app.module.ts
@@ -0,0 +1,18 @@
+// #docregion
+import { BrowserModule } from '@angular/platform-browser';
+import { ReactiveFormsModule } from '@angular/forms';
+import { NgModule } from '@angular/core';
+
+import { AppComponent } from './app.component';
+import { DynamicFormComponent } from './dynamic-form.component';
+import { DynamicFormQuestionComponent } from './dynamic-form-question.component';
+
+@NgModule({
+ imports: [ BrowserModule, ReactiveFormsModule ],
+ declarations: [ AppComponent, DynamicFormComponent, DynamicFormQuestionComponent ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule {
+ constructor() {
+ }
+}
diff --git a/public/docs/_examples/cb-dynamic-form/ts/src/app/dynamic-form-question.component.html b/public/docs/_examples/cb-dynamic-form/ts/src/app/dynamic-form-question.component.html
new file mode 100644
index 0000000000..9f1b8cd4a6
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-form/ts/src/app/dynamic-form-question.component.html
@@ -0,0 +1,17 @@
+
+
+
{{question.label}}
+
+
+
+
+
+
+ {{opt.value}}
+
+
+
+
+
{{question.label}} is required
+
diff --git a/public/docs/_examples/cb-dynamic-form/ts/src/app/dynamic-form-question.component.ts b/public/docs/_examples/cb-dynamic-form/ts/src/app/dynamic-form-question.component.ts
new file mode 100644
index 0000000000..024571a7c2
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-form/ts/src/app/dynamic-form-question.component.ts
@@ -0,0 +1,15 @@
+// #docregion
+import { Component, Input } from '@angular/core';
+import { FormGroup } from '@angular/forms';
+
+import { QuestionBase } from './question-base';
+
+@Component({
+ selector: 'df-question',
+ templateUrl: './dynamic-form-question.component.html'
+})
+export class DynamicFormQuestionComponent {
+ @Input() question: QuestionBase;
+ @Input() form: FormGroup;
+ get isValid() { return this.form.controls[this.question.key].valid; }
+}
diff --git a/public/docs/_examples/cb-dynamic-form/ts/src/app/dynamic-form.component.html b/public/docs/_examples/cb-dynamic-form/ts/src/app/dynamic-form.component.html
new file mode 100644
index 0000000000..717f09ff71
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-form/ts/src/app/dynamic-form.component.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+ Saved the following values {{payLoad}}
+
+
diff --git a/public/docs/_examples/cb-dynamic-form/ts/src/app/dynamic-form.component.ts b/public/docs/_examples/cb-dynamic-form/ts/src/app/dynamic-form.component.ts
new file mode 100644
index 0000000000..8d95c0d3a4
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-form/ts/src/app/dynamic-form.component.ts
@@ -0,0 +1,28 @@
+// #docregion
+import { Component, Input, OnInit } from '@angular/core';
+import { FormGroup } from '@angular/forms';
+
+import { QuestionBase } from './question-base';
+import { QuestionControlService } from './question-control.service';
+
+@Component({
+ selector: 'dynamic-form',
+ templateUrl: './dynamic-form.component.html',
+ providers: [ QuestionControlService ]
+})
+export class DynamicFormComponent implements OnInit {
+
+ @Input() questions: QuestionBase[] = [];
+ form: FormGroup;
+ payLoad = '';
+
+ constructor(private qcs: QuestionControlService) { }
+
+ ngOnInit() {
+ this.form = this.qcs.toFormGroup(this.questions);
+ }
+
+ onSubmit() {
+ this.payLoad = JSON.stringify(this.form.value);
+ }
+}
diff --git a/public/docs/_examples/cb-dynamic-form/ts/src/app/question-base.ts b/public/docs/_examples/cb-dynamic-form/ts/src/app/question-base.ts
new file mode 100644
index 0000000000..2b32b00f2a
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-form/ts/src/app/question-base.ts
@@ -0,0 +1,25 @@
+// #docregion
+export class QuestionBase{
+ value: T;
+ key: string;
+ label: string;
+ required: boolean;
+ order: number;
+ controlType: string;
+
+ constructor(options: {
+ value?: T,
+ key?: string,
+ label?: string,
+ required?: boolean,
+ order?: number,
+ controlType?: string
+ } = {}) {
+ this.value = options.value;
+ this.key = options.key || '';
+ this.label = options.label || '';
+ this.required = !!options.required;
+ this.order = options.order === undefined ? 1 : options.order;
+ this.controlType = options.controlType || '';
+ }
+}
diff --git a/public/docs/_examples/cb-dynamic-form/ts/src/app/question-control.service.ts b/public/docs/_examples/cb-dynamic-form/ts/src/app/question-control.service.ts
new file mode 100644
index 0000000000..1378ba8490
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-form/ts/src/app/question-control.service.ts
@@ -0,0 +1,20 @@
+// #docregion
+import { Injectable } from '@angular/core';
+import { FormControl, FormGroup, Validators } from '@angular/forms';
+
+import { QuestionBase } from './question-base';
+
+@Injectable()
+export class QuestionControlService {
+ constructor() { }
+
+ toFormGroup(questions: QuestionBase[] ) {
+ let group: any = {};
+
+ questions.forEach(question => {
+ group[question.key] = question.required ? new FormControl(question.value || '', Validators.required)
+ : new FormControl(question.value || '');
+ });
+ return new FormGroup(group);
+ }
+}
diff --git a/public/docs/_examples/cb-dynamic-form/ts/src/app/question-dropdown.ts b/public/docs/_examples/cb-dynamic-form/ts/src/app/question-dropdown.ts
new file mode 100644
index 0000000000..35a9074c74
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-form/ts/src/app/question-dropdown.ts
@@ -0,0 +1,12 @@
+// #docregion
+import { QuestionBase } from './question-base';
+
+export class DropdownQuestion extends QuestionBase {
+ controlType = 'dropdown';
+ options: {key: string, value: string}[] = [];
+
+ constructor(options: {} = {}) {
+ super(options);
+ this.options = options['options'] || [];
+ }
+}
diff --git a/public/docs/_examples/cb-dynamic-form/ts/src/app/question-textbox.ts b/public/docs/_examples/cb-dynamic-form/ts/src/app/question-textbox.ts
new file mode 100644
index 0000000000..aaa7edf267
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-form/ts/src/app/question-textbox.ts
@@ -0,0 +1,12 @@
+// #docregion
+import { QuestionBase } from './question-base';
+
+export class TextboxQuestion extends QuestionBase {
+ controlType = 'textbox';
+ type: string;
+
+ constructor(options: {} = {}) {
+ super(options);
+ this.type = options['type'] || '';
+ }
+}
diff --git a/public/docs/_examples/cb-dynamic-form/ts/src/app/question.service.ts b/public/docs/_examples/cb-dynamic-form/ts/src/app/question.service.ts
new file mode 100644
index 0000000000..bb452cf5e6
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-form/ts/src/app/question.service.ts
@@ -0,0 +1,47 @@
+// #docregion
+import { Injectable } from '@angular/core';
+
+import { DropdownQuestion } from './question-dropdown';
+import { QuestionBase } from './question-base';
+import { TextboxQuestion } from './question-textbox';
+
+@Injectable()
+export class QuestionService {
+
+ // Todo: get from a remote source of question metadata
+ // Todo: make asynchronous
+ getQuestions() {
+
+ let questions: QuestionBase[] = [
+
+ new DropdownQuestion({
+ key: 'brave',
+ label: 'Bravery Rating',
+ options: [
+ {key: 'solid', value: 'Solid'},
+ {key: 'great', value: 'Great'},
+ {key: 'good', value: 'Good'},
+ {key: 'unproven', value: 'Unproven'}
+ ],
+ order: 3
+ }),
+
+ new TextboxQuestion({
+ key: 'firstName',
+ label: 'First name',
+ value: 'Bombasto',
+ required: true,
+ order: 1
+ }),
+
+ new TextboxQuestion({
+ key: 'emailAddress',
+ label: 'Email',
+ type: 'email',
+ order: 2
+ })
+ ];
+
+ return questions.sort((a, b) => a.order - b.order);
+ }
+}
diff --git a/public/docs/_examples/cb-dynamic-form/ts/src/index.html b/public/docs/_examples/cb-dynamic-form/ts/src/index.html
new file mode 100644
index 0000000000..01963f71e2
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-form/ts/src/index.html
@@ -0,0 +1,28 @@
+
+
+
+
+
+ Dynamic Form
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading app...
+
+
+
diff --git a/public/docs/_examples/cb-dynamic-form/ts/src/main.ts b/public/docs/_examples/cb-dynamic-form/ts/src/main.ts
new file mode 100644
index 0000000000..6b6532d428
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-form/ts/src/main.ts
@@ -0,0 +1,5 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/cb-dynamic-form/ts/src/sample.css b/public/docs/_examples/cb-dynamic-form/ts/src/sample.css
new file mode 100644
index 0000000000..fe2cc28481
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-form/ts/src/sample.css
@@ -0,0 +1,7 @@
+.errorMessage{
+ color:red;
+}
+
+.form-row{
+ margin-top: 10px;
+}
\ No newline at end of file
diff --git a/public/docs/_examples/cb-form-validation/e2e-spec.ts b/public/docs/_examples/cb-form-validation/e2e-spec.ts
new file mode 100644
index 0000000000..8ffc01e250
--- /dev/null
+++ b/public/docs/_examples/cb-form-validation/e2e-spec.ts
@@ -0,0 +1,182 @@
+'use strict'; // necessary for node!
+
+import { browser, element, by, protractor, ElementFinder, ElementArrayFinder } from 'protractor';
+import { appLang, describeIf } from '../protractor-helpers';
+
+// THESE TESTS ARE INCOMPLETE
+describeIf(appLang.appIsTs || appLang.appIsJs, 'Form Validation Tests', function () {
+
+ beforeAll(function () {
+ browser.get('');
+ });
+
+ describe('Hero Form 1', () => {
+ beforeAll(() => {
+ getPage('hero-form-template1');
+ });
+
+ tests();
+ });
+
+ describe('Hero Form 2', () => {
+ beforeAll(() => {
+ getPage('hero-form-template2');
+ });
+
+ tests();
+ bobTests();
+ });
+
+ describe('Hero Form 3 (Reactive)', () => {
+ beforeAll(() => {
+ getPage('hero-form-reactive3');
+ makeNameTooLong();
+ });
+
+ tests();
+ bobTests();
+ });
+});
+
+//////////
+
+const testName = 'Test Name';
+
+let page: {
+ section: ElementFinder,
+ form: ElementFinder,
+ title: ElementFinder,
+ nameInput: ElementFinder,
+ alterEgoInput: ElementFinder,
+ powerSelect: ElementFinder,
+ errorMessages: ElementArrayFinder,
+ heroFormButtons: ElementArrayFinder,
+ heroSubmitted: ElementFinder
+};
+
+function getPage(sectionTag: string) {
+ let section = element(by.css(sectionTag));
+ let buttons = section.all(by.css('button'));
+
+ page = {
+ section: section,
+ form: section.element(by.css('form')),
+ title: section.element(by.css('h1')),
+ nameInput: section.element(by.css('#name')),
+ alterEgoInput: section.element(by.css('#alterEgo')),
+ powerSelect: section.element(by.css('#power')),
+ errorMessages: section.all(by.css('div.alert')),
+ heroFormButtons: buttons,
+ heroSubmitted: section.element(by.css('hero-submitted > div'))
+ };
+}
+
+function tests() {
+ it('should display correct title', function () {
+ expect(page.title.getText()).toContain('Hero Form');
+ });
+
+ it('should not display submitted message before submit', function () {
+ expect(page.heroSubmitted.isElementPresent(by.css('h2'))).toBe(false);
+ });
+
+ it('should have form buttons', function () {
+ expect(page.heroFormButtons.count()).toEqual(2);
+ });
+
+ it('should have error at start', function () {
+ expectFormIsInvalid();
+ });
+
+ // it('showForm', function () {
+ // page.form.getInnerHtml().then(html => console.log(html));
+ // });
+
+ it('should have disabled submit button', function () {
+ expect(page.heroFormButtons.get(0).isEnabled()).toBe(false);
+ });
+
+ it('resetting name to valid name should clear errors', function () {
+ const ele = page.nameInput;
+ expect(ele.isPresent()).toBe(true, 'nameInput should exist');
+ ele.clear();
+ ele.sendKeys(testName);
+ expectFormIsValid();
+ });
+
+ it('should produce "required" error after clearing name', function () {
+ page.nameInput.clear();
+ // page.alterEgoInput.click(); // to blur ... didn't work
+ page.nameInput.sendKeys('x', protractor.Key.BACK_SPACE); // ugh!
+ expect(page.form.getAttribute('class')).toMatch('ng-invalid');
+ expect(page.errorMessages.get(0).getText()).toContain('required');
+ });
+
+ it('should produce "at least 4 characters" error when name="x"', function () {
+ page.nameInput.clear();
+ page.nameInput.sendKeys('x'); // too short
+ expectFormIsInvalid();
+ expect(page.errorMessages.get(0).getText()).toContain('at least 4 characters');
+ });
+
+ it('resetting name to valid name again should clear errors', function () {
+ page.nameInput.sendKeys(testName);
+ expectFormIsValid();
+ });
+
+ it('should have enabled submit button', function () {
+ const submitBtn = page.heroFormButtons.get(0);
+ expect(submitBtn.isEnabled()).toBe(true);
+ });
+
+ it('should hide form after submit', function () {
+ page.heroFormButtons.get(0).click();
+ expect(page.title.isDisplayed()).toBe(false);
+ });
+
+ it('submitted form should be displayed', function () {
+ expect(page.heroSubmitted.isElementPresent(by.css('h2'))).toBe(true);
+ });
+
+ it('submitted form should have new hero name', function () {
+ expect(page.heroSubmitted.getText()).toContain(testName);
+ });
+
+ it('clicking edit button should reveal form again', function () {
+ const editBtn = page.heroSubmitted.element(by.css('button'));
+ editBtn.click();
+ expect(page.heroSubmitted.isElementPresent(by.css('h2')))
+ .toBe(false, 'submitted hidden again');
+ expect(page.title.isDisplayed()).toBe(true, 'can see form title');
+ });
+}
+
+function expectFormIsValid() {
+ expect(page.form.getAttribute('class')).toMatch('ng-valid');
+}
+
+function expectFormIsInvalid() {
+ expect(page.form.getAttribute('class')).toMatch('ng-invalid');
+}
+
+function bobTests() {
+ const emsg = 'Someone named "Bob" cannot be a hero.';
+
+ it('should produce "no bob" error after setting name to "Bobby"', function () {
+ page.nameInput.clear();
+ page.nameInput.sendKeys('Bobby');
+ expectFormIsInvalid();
+ expect(page.errorMessages.get(0).getText()).toBe(emsg);
+ });
+
+ it('should be ok again with valid name', function () {
+ page.nameInput.clear();
+ page.nameInput.sendKeys(testName);
+ expectFormIsValid();
+ });
+}
+
+function makeNameTooLong() {
+ // make the first name invalid
+ page.nameInput.sendKeys('ThisHeroNameHasWayWayTooManyLetters');
+}
diff --git a/public/docs/_examples/upgrade/ts/ng2_components/app/css/.gitkeep b/public/docs/_examples/cb-form-validation/ts/example-config.json
similarity index 100%
rename from public/docs/_examples/upgrade/ts/ng2_components/app/css/.gitkeep
rename to public/docs/_examples/cb-form-validation/ts/example-config.json
diff --git a/public/docs/_examples/cb-form-validation/ts/plnkr.json b/public/docs/_examples/cb-form-validation/ts/plnkr.json
new file mode 100644
index 0000000000..c5656d77f7
--- /dev/null
+++ b/public/docs/_examples/cb-form-validation/ts/plnkr.json
@@ -0,0 +1,8 @@
+{
+ "description": "Validation",
+ "basePath": "src/",
+ "files":[
+ "!**/*.d.ts",
+ "!**/*.js"
+ ]
+}
diff --git a/public/docs/_examples/cb-form-validation/ts/src/app/app.component.ts b/public/docs/_examples/cb-form-validation/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..2da4dc4d0a
--- /dev/null
+++ b/public/docs/_examples/cb-form-validation/ts/src/app/app.component.ts
@@ -0,0 +1,12 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ template: `
+
+
+
+ `
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/cb-form-validation/ts/src/app/app.module.ts b/public/docs/_examples/cb-form-validation/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..72b4e3a770
--- /dev/null
+++ b/public/docs/_examples/cb-form-validation/ts/src/app/app.module.ts
@@ -0,0 +1,18 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+import { AppComponent } from './app.component';
+import { HeroFormTemplateModule } from './template/hero-form-template.module';
+import { HeroFormReactiveModule } from './reactive/hero-form-reactive.module';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ HeroFormTemplateModule,
+ HeroFormReactiveModule
+ ],
+ declarations: [ AppComponent ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/cb-form-validation/ts/src/app/reactive/hero-form-reactive.component.html b/public/docs/_examples/cb-form-validation/ts/src/app/reactive/hero-form-reactive.component.html
new file mode 100644
index 0000000000..149537bd3e
--- /dev/null
+++ b/public/docs/_examples/cb-form-validation/ts/src/app/reactive/hero-form-reactive.component.html
@@ -0,0 +1,47 @@
+
+
+
+
Hero Form 3 (Reactive)
+
+
+
+
+
+
diff --git a/public/docs/_examples/cb-form-validation/ts/src/app/reactive/hero-form-reactive.component.ts b/public/docs/_examples/cb-form-validation/ts/src/app/reactive/hero-form-reactive.component.ts
new file mode 100644
index 0000000000..241ff1e782
--- /dev/null
+++ b/public/docs/_examples/cb-form-validation/ts/src/app/reactive/hero-form-reactive.component.ts
@@ -0,0 +1,116 @@
+/* tslint:disable: member-ordering forin */
+// #docplaster
+// #docregion
+import { Component, OnInit } from '@angular/core';
+import { FormGroup, FormBuilder, Validators } from '@angular/forms';
+
+import { Hero } from '../shared/hero';
+import { forbiddenNameValidator } from '../shared/forbidden-name.directive';
+
+@Component({
+ selector: 'hero-form-reactive3',
+ templateUrl: './hero-form-reactive.component.html'
+})
+export class HeroFormReactiveComponent implements OnInit {
+
+ powers = ['Really Smart', 'Super Flexible', 'Weather Changer'];
+
+ hero = new Hero(18, 'Dr. WhatIsHisName', this.powers[0], 'Dr. What');
+
+ submitted = false;
+
+ // #docregion on-submit
+ onSubmit() {
+ this.submitted = true;
+ this.hero = this.heroForm.value;
+ }
+ // #enddocregion on-submit
+// #enddocregion
+
+ // Reset the form with a new hero AND restore 'pristine' class state
+ // by toggling 'active' flag which causes the form
+ // to be removed/re-added in a tick via NgIf
+ // TODO: Workaround until NgForm has a reset method (#6822)
+ active = true;
+// #docregion class
+ // #docregion add-hero
+ addHero() {
+ this.hero = new Hero(42, '', '');
+ this.buildForm();
+ // #enddocregion add-hero
+// #enddocregion class
+
+ this.active = false;
+ setTimeout(() => this.active = true, 0);
+// #docregion
+ // #docregion add-hero
+ }
+ // #enddocregion add-hero
+
+ // #docregion form-builder
+ heroForm: FormGroup;
+ constructor(private fb: FormBuilder) { }
+
+ ngOnInit(): void {
+ this.buildForm();
+ }
+
+ buildForm(): void {
+ this.heroForm = this.fb.group({
+ // #docregion name-validators
+ 'name': [this.hero.name, [
+ Validators.required,
+ Validators.minLength(4),
+ Validators.maxLength(24),
+ forbiddenNameValidator(/bob/i)
+ ]
+ ],
+ // #enddocregion name-validators
+ 'alterEgo': [this.hero.alterEgo],
+ 'power': [this.hero.power, Validators.required]
+ });
+
+ this.heroForm.valueChanges
+ .subscribe(data => this.onValueChanged(data));
+
+ this.onValueChanged(); // (re)set validation messages now
+ }
+
+ // #enddocregion form-builder
+
+ onValueChanged(data?: any) {
+ if (!this.heroForm) { return; }
+ const form = this.heroForm;
+
+ for (const field in this.formErrors) {
+ // clear previous error message (if any)
+ this.formErrors[field] = '';
+ const control = form.get(field);
+
+ if (control && control.dirty && !control.valid) {
+ const messages = this.validationMessages[field];
+ for (const key in control.errors) {
+ this.formErrors[field] += messages[key] + ' ';
+ }
+ }
+ }
+ }
+
+ formErrors = {
+ 'name': '',
+ 'power': ''
+ };
+
+ validationMessages = {
+ 'name': {
+ 'required': 'Name is required.',
+ 'minlength': 'Name must be at least 4 characters long.',
+ 'maxlength': 'Name cannot be more than 24 characters long.',
+ 'forbiddenName': 'Someone named "Bob" cannot be a hero.'
+ },
+ 'power': {
+ 'required': 'Power is required.'
+ }
+ };
+}
+// #enddocregion
diff --git a/public/docs/_examples/cb-form-validation/ts/src/app/reactive/hero-form-reactive.module.ts b/public/docs/_examples/cb-form-validation/ts/src/app/reactive/hero-form-reactive.module.ts
new file mode 100644
index 0000000000..6ff9265e92
--- /dev/null
+++ b/public/docs/_examples/cb-form-validation/ts/src/app/reactive/hero-form-reactive.module.ts
@@ -0,0 +1,13 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { ReactiveFormsModule } from '@angular/forms';
+
+import { SharedModule } from '../shared/shared.module';
+import { HeroFormReactiveComponent } from './hero-form-reactive.component';
+
+@NgModule({
+ imports: [ SharedModule, ReactiveFormsModule ],
+ declarations: [ HeroFormReactiveComponent ],
+ exports: [ HeroFormReactiveComponent ]
+})
+export class HeroFormReactiveModule { }
diff --git a/public/docs/_examples/cb-form-validation/ts/src/app/shared/forbidden-name.directive.ts b/public/docs/_examples/cb-form-validation/ts/src/app/shared/forbidden-name.directive.ts
new file mode 100644
index 0000000000..870f514842
--- /dev/null
+++ b/public/docs/_examples/cb-form-validation/ts/src/app/shared/forbidden-name.directive.ts
@@ -0,0 +1,43 @@
+// #docregion
+import { Directive, Input, OnChanges, SimpleChanges } from '@angular/core';
+import { AbstractControl, NG_VALIDATORS, Validator, ValidatorFn, Validators } from '@angular/forms';
+
+// #docregion custom-validator
+/** A hero's name can't match the given regular expression */
+export function forbiddenNameValidator(nameRe: RegExp): ValidatorFn {
+ return (control: AbstractControl): {[key: string]: any} => {
+ const name = control.value;
+ const no = nameRe.test(name);
+ return no ? {'forbiddenName': {name}} : null;
+ };
+}
+// #enddocregion custom-validator
+
+// #docregion directive
+@Directive({
+ selector: '[forbiddenName]',
+ // #docregion directive-providers
+ providers: [{provide: NG_VALIDATORS, useExisting: ForbiddenValidatorDirective, multi: true}]
+ // #enddocregion directive-providers
+})
+export class ForbiddenValidatorDirective implements Validator, OnChanges {
+ @Input() forbiddenName: string;
+ private valFn = Validators.nullValidator;
+
+ ngOnChanges(changes: SimpleChanges): void {
+ const change = changes['forbiddenName'];
+ if (change) {
+ const val: string | RegExp = change.currentValue;
+ const re = val instanceof RegExp ? val : new RegExp(val, 'i');
+ this.valFn = forbiddenNameValidator(re);
+ } else {
+ this.valFn = Validators.nullValidator;
+ }
+ }
+
+ validate(control: AbstractControl): {[key: string]: any} {
+ return this.valFn(control);
+ }
+}
+// #enddocregion directive
+
diff --git a/public/docs/_examples/cb-form-validation/ts/src/app/shared/hero.ts b/public/docs/_examples/cb-form-validation/ts/src/app/shared/hero.ts
new file mode 100644
index 0000000000..fe2b55e51a
--- /dev/null
+++ b/public/docs/_examples/cb-form-validation/ts/src/app/shared/hero.ts
@@ -0,0 +1,9 @@
+// #docregion
+export class Hero {
+ constructor(
+ public id: number,
+ public name: string,
+ public power: string,
+ public alterEgo?: string
+ ) { }
+}
diff --git a/public/docs/_examples/cb-form-validation/ts/src/app/shared/shared.module.ts b/public/docs/_examples/cb-form-validation/ts/src/app/shared/shared.module.ts
new file mode 100644
index 0000000000..2b0ada59bd
--- /dev/null
+++ b/public/docs/_examples/cb-form-validation/ts/src/app/shared/shared.module.ts
@@ -0,0 +1,14 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { ForbiddenValidatorDirective } from './forbidden-name.directive';
+import { SubmittedComponent } from './submitted.component';
+
+@NgModule({
+ imports: [ CommonModule],
+ declarations: [ ForbiddenValidatorDirective, SubmittedComponent ],
+ exports: [ ForbiddenValidatorDirective, SubmittedComponent,
+ CommonModule ]
+})
+export class SharedModule { }
diff --git a/public/docs/_examples/cb-form-validation/ts/src/app/shared/submitted.component.ts b/public/docs/_examples/cb-form-validation/ts/src/app/shared/submitted.component.ts
new file mode 100644
index 0000000000..18cea6563f
--- /dev/null
+++ b/public/docs/_examples/cb-form-validation/ts/src/app/shared/submitted.component.ts
@@ -0,0 +1,32 @@
+// #docregion
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+
+import { Hero } from './hero';
+
+@Component({
+ selector: 'hero-submitted',
+ template: `
+
+
You submitted the following:
+
+
Name
+
{{ hero.name }}
+
+
+
Alter Ego
+
{{ hero.alterEgo }}
+
+
+
Power
+
{{ hero.power }}
+
+
+
Edit
+
`
+})
+export class SubmittedComponent {
+ @Input() hero: Hero;
+ @Input() submitted = false;
+ @Output() submittedChange = new EventEmitter();
+ onClick() { this.submittedChange.emit(false); }
+}
diff --git a/public/docs/_examples/cb-form-validation/ts/src/app/template/hero-form-template.module.ts b/public/docs/_examples/cb-form-validation/ts/src/app/template/hero-form-template.module.ts
new file mode 100644
index 0000000000..042c019d5e
--- /dev/null
+++ b/public/docs/_examples/cb-form-validation/ts/src/app/template/hero-form-template.module.ts
@@ -0,0 +1,14 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+
+import { SharedModule } from '../shared/shared.module';
+import { HeroFormTemplate1Component } from './hero-form-template1.component';
+import { HeroFormTemplate2Component } from './hero-form-template2.component';
+
+@NgModule({
+ imports: [ SharedModule, FormsModule ],
+ declarations: [ HeroFormTemplate1Component, HeroFormTemplate2Component ],
+ exports: [ HeroFormTemplate1Component, HeroFormTemplate2Component ]
+})
+export class HeroFormTemplateModule { }
diff --git a/public/docs/_examples/cb-form-validation/ts/src/app/template/hero-form-template1.component.html b/public/docs/_examples/cb-form-validation/ts/src/app/template/hero-form-template1.component.html
new file mode 100644
index 0000000000..22b374b622
--- /dev/null
+++ b/public/docs/_examples/cb-form-validation/ts/src/app/template/hero-form-template1.component.html
@@ -0,0 +1,61 @@
+
+
+
+
Hero Form 1 (Template)
+
+
+
+
+
+
diff --git a/public/docs/_examples/cb-form-validation/ts/src/app/template/hero-form-template1.component.ts b/public/docs/_examples/cb-form-validation/ts/src/app/template/hero-form-template1.component.ts
new file mode 100644
index 0000000000..1bc29db44d
--- /dev/null
+++ b/public/docs/_examples/cb-form-validation/ts/src/app/template/hero-form-template1.component.ts
@@ -0,0 +1,47 @@
+/* tslint:disable: member-ordering */
+// #docplaster
+// #docregion
+import { Component } from '@angular/core';
+
+
+import { Hero } from '../shared/hero';
+
+@Component({
+ selector: 'hero-form-template1',
+ templateUrl: './hero-form-template1.component.html'
+})
+// #docregion class
+export class HeroFormTemplate1Component {
+
+ powers = ['Really Smart', 'Super Flexible', 'Weather Changer'];
+
+ hero = new Hero(18, 'Dr. WhatIsHisWayTooLongName', this.powers[0], 'Dr. What');
+
+ submitted = false;
+
+ onSubmit() {
+ this.submitted = true;
+ }
+// #enddocregion class
+// #enddocregion
+ // Reset the form with a new hero AND restore 'pristine' class state
+ // by toggling 'active' flag which causes the form
+ // to be removed/re-added in a tick via NgIf
+ // TODO: Workaround until NgForm has a reset method (#6822)
+ active = true;
+// #docregion
+// #docregion class
+
+ addHero() {
+ this.hero = new Hero(42, '', '');
+// #enddocregion class
+// #enddocregion
+
+ this.active = false;
+ setTimeout(() => this.active = true, 0);
+// #docregion
+// #docregion class
+ }
+}
+// #enddocregion class
+// #enddocregion
diff --git a/public/docs/_examples/cb-form-validation/ts/src/app/template/hero-form-template2.component.html b/public/docs/_examples/cb-form-validation/ts/src/app/template/hero-form-template2.component.html
new file mode 100644
index 0000000000..8bb7066541
--- /dev/null
+++ b/public/docs/_examples/cb-form-validation/ts/src/app/template/hero-form-template2.component.html
@@ -0,0 +1,52 @@
+
+
+
+
Hero Form 2 (Template & Messages)
+
+
+
+
+
+
diff --git a/public/docs/_examples/cb-form-validation/ts/src/app/template/hero-form-template2.component.ts b/public/docs/_examples/cb-form-validation/ts/src/app/template/hero-form-template2.component.ts
new file mode 100644
index 0000000000..320ef09efd
--- /dev/null
+++ b/public/docs/_examples/cb-form-validation/ts/src/app/template/hero-form-template2.component.ts
@@ -0,0 +1,99 @@
+/* tslint:disable: member-ordering forin */
+// #docplaster
+// #docregion
+import { Component, AfterViewChecked, ViewChild } from '@angular/core';
+import { NgForm } from '@angular/forms';
+
+import { Hero } from '../shared/hero';
+
+@Component({
+ selector: 'hero-form-template2',
+ templateUrl: './hero-form-template2.component.html'
+})
+export class HeroFormTemplate2Component implements AfterViewChecked {
+
+ powers = ['Really Smart', 'Super Flexible', 'Weather Changer'];
+
+ hero = new Hero(18, 'Dr. WhatIsHisWayTooLongName', this.powers[0], 'Dr. What');
+
+ submitted = false;
+
+ onSubmit() {
+ this.submitted = true;
+ }
+// #enddocregion
+
+ // Reset the form with a new hero AND restore 'pristine' class state
+ // by toggling 'active' flag which causes the form
+ // to be removed/re-added in a tick via NgIf
+ // TODO: Workaround until NgForm has a reset method (#6822)
+ active = true;
+// #docregion
+
+ addHero() {
+ this.hero = new Hero(42, '', '');
+// #enddocregion
+
+ this.active = false;
+ setTimeout(() => this.active = true, 0);
+// #docregion
+ }
+
+ // #docregion view-child
+ heroForm: NgForm;
+ @ViewChild('heroForm') currentForm: NgForm;
+
+ ngAfterViewChecked() {
+ this.formChanged();
+ }
+
+ formChanged() {
+ if (this.currentForm === this.heroForm) { return; }
+ this.heroForm = this.currentForm;
+ if (this.heroForm) {
+ this.heroForm.valueChanges
+ .subscribe(data => this.onValueChanged(data));
+ }
+ }
+ // #enddocregion view-child
+
+ // #docregion handler
+ onValueChanged(data?: any) {
+ if (!this.heroForm) { return; }
+ const form = this.heroForm.form;
+
+ for (const field in this.formErrors) {
+ // clear previous error message (if any)
+ this.formErrors[field] = '';
+ const control = form.get(field);
+
+ if (control && control.dirty && !control.valid) {
+ const messages = this.validationMessages[field];
+ for (const key in control.errors) {
+ this.formErrors[field] += messages[key] + ' ';
+ }
+ }
+ }
+ }
+
+ formErrors = {
+ 'name': '',
+ 'power': ''
+ };
+ // #enddocregion handler
+
+ // #docregion messages
+ validationMessages = {
+ 'name': {
+ 'required': 'Name is required.',
+ 'minlength': 'Name must be at least 4 characters long.',
+ 'maxlength': 'Name cannot be more than 24 characters long.',
+ 'forbiddenName': 'Someone named "Bob" cannot be a hero.'
+ },
+ 'power': {
+ 'required': 'Power is required.'
+ }
+ };
+ // #enddocregion messages
+}
+// #enddocregion
diff --git a/public/docs/_examples/cb-form-validation/ts/src/forms.css b/public/docs/_examples/cb-form-validation/ts/src/forms.css
new file mode 100644
index 0000000000..67ad13037b
--- /dev/null
+++ b/public/docs/_examples/cb-form-validation/ts/src/forms.css
@@ -0,0 +1,7 @@
+.ng-valid[required], .ng-valid.required {
+ border-left: 5px solid #42A948; /* green */
+}
+
+.ng-invalid:not(form) {
+ border-left: 5px solid #a94442; /* red */
+}
diff --git a/public/docs/_examples/cb-form-validation/ts/src/index.html b/public/docs/_examples/cb-form-validation/ts/src/index.html
new file mode 100644
index 0000000000..e7201508d7
--- /dev/null
+++ b/public/docs/_examples/cb-form-validation/ts/src/index.html
@@ -0,0 +1,29 @@
+
+
+ Hero Form with Validation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
diff --git a/public/docs/_examples/cb-form-validation/ts/src/main.ts b/public/docs/_examples/cb-form-validation/ts/src/main.ts
new file mode 100644
index 0000000000..f332d1d245
--- /dev/null
+++ b/public/docs/_examples/cb-form-validation/ts/src/main.ts
@@ -0,0 +1,6 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/cb-i18n/e2e-spec.ts b/public/docs/_examples/cb-i18n/e2e-spec.ts
new file mode 100644
index 0000000000..3dcca5a670
--- /dev/null
+++ b/public/docs/_examples/cb-i18n/e2e-spec.ts
@@ -0,0 +1,33 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by } from 'protractor';
+
+describe('i18n E2E Tests', () => {
+
+ beforeEach(function () {
+ browser.get('');
+ });
+
+ it('should display i18n translated welcome: ¡Hola i18n!', function () {
+ expect(element(by.css('h1')).getText()).toEqual('¡Hola i18n!');
+ });
+
+ it('should display the node texts without elements', function () {
+ expect(element(by.css('my-app')).getText()).toContain('No genero ningún elemento');
+ expect(element(by.css('my-app')).getText()).toContain('Yo tampoco genero ningún elemento');
+ });
+
+ it('should display the translated title attribute', function () {
+ const title = element(by.css('img')).getAttribute('title');
+ expect(title).toBe('Logo de Angular');
+ });
+
+ it('should display the plural of: a horde of wolves', function () {
+ expect(element.all(by.css('span')).get(0).getText()).toBe('ningún lobo');
+ });
+
+ it('should display the select of gender', function () {
+ expect(element.all(by.css('span')).get(1).getText()).toBe('El heroe es mujer');
+ });
+
+});
diff --git a/public/docs/_examples/cb-i18n/ts/.gitignore b/public/docs/_examples/cb-i18n/ts/.gitignore
new file mode 100644
index 0000000000..d38bb50aa9
--- /dev/null
+++ b/public/docs/_examples/cb-i18n/ts/.gitignore
@@ -0,0 +1,6 @@
+**/*.ngfactory.ts
+**/*.metadata.json
+dist
+!app/tsconfig.json
+!rollup.js
+!src/systemjs-text-plugin.js
diff --git a/public/docs/_examples/upgrade/ts/ng2_components/app/img/.gitkeep b/public/docs/_examples/cb-i18n/ts/example-config.json
similarity index 100%
rename from public/docs/_examples/upgrade/ts/ng2_components/app/img/.gitkeep
rename to public/docs/_examples/cb-i18n/ts/example-config.json
diff --git a/public/docs/_examples/cb-i18n/ts/messages.xlf b/public/docs/_examples/cb-i18n/ts/messages.xlf
new file mode 100644
index 0000000000..dee8b65aca
--- /dev/null
+++ b/public/docs/_examples/cb-i18n/ts/messages.xlf
@@ -0,0 +1,47 @@
+
+
+
+
+
+ Hello i18n!
+
+ An introduction header for this sample
+ User welcome
+
+
+ I don't output any element
+
+
+
+
+I don't output any element either
+
+
+ optional description
+ optional meaning
+
+
+ Angular logo
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The hero is
+
+
+
+
+
+
+
+
+
diff --git a/public/docs/_examples/cb-i18n/ts/plnkr.json b/public/docs/_examples/cb-i18n/ts/plnkr.json
new file mode 100644
index 0000000000..36f2685129
--- /dev/null
+++ b/public/docs/_examples/cb-i18n/ts/plnkr.json
@@ -0,0 +1,19 @@
+{
+ "description": "i18n",
+ "basePath": "src/",
+ "files": [
+ "app/**/*.css",
+ "app/**/*.html",
+ "app/**/*.ts",
+ "messages.xlf",
+ "locale/messages.*.xlf",
+
+ "!**/*.[1].*",
+
+ "main.ts",
+ "styles.css",
+ "systemjs-text-plugin.js",
+ "index.html"
+ ],
+ "tags": ["i18n"]
+}
diff --git a/public/docs/_examples/cb-i18n/ts/src/app/app.component.1.html b/public/docs/_examples/cb-i18n/ts/src/app/app.component.1.html
new file mode 100644
index 0000000000..cc7d4f1155
--- /dev/null
+++ b/public/docs/_examples/cb-i18n/ts/src/app/app.component.1.html
@@ -0,0 +1,15 @@
+
+Hello i18n!
+
+
+
+Hello i18n!
+
+
+
+Hello i18n!
+
+
+
+
+
diff --git a/public/docs/_examples/cb-i18n/ts/src/app/app.component.html b/public/docs/_examples/cb-i18n/ts/src/app/app.component.html
new file mode 100644
index 0000000000..39ace24f79
--- /dev/null
+++ b/public/docs/_examples/cb-i18n/ts/src/app/app.component.html
@@ -0,0 +1,34 @@
+
+
+Hello i18n!
+
+
+
+I don't output any element
+
+
+
+
+
+
+I don't output any element either
+
+
+
+
+
+
+
+
+
++ -
+
+{wolves, plural, =0 {no wolves} =1 {one wolf} =2 {two wolves} other {a wolf pack}}
+
+({{wolves}})
+
+♂ ♀
+
+The hero is {gender, select, m {male} f {female}}
+
+
diff --git a/public/docs/_examples/cb-i18n/ts/src/app/app.component.ts b/public/docs/_examples/cb-i18n/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..09b8722e9b
--- /dev/null
+++ b/public/docs/_examples/cb-i18n/ts/src/app/app.component.ts
@@ -0,0 +1,19 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ templateUrl: './app.component.html'
+})
+export class AppComponent {
+ wolves = 0;
+ gender = 'f';
+ fly = true;
+ logo = 'https://angular.io/resources/images/logos/angular/angular.png';
+ inc(i: number) {
+ this.wolves = Math.min(5, Math.max(0, this.wolves + i));
+ }
+ male() { this.gender = 'm'; }
+ female() { this.gender = 'f'; }
+}
+
diff --git a/public/docs/_examples/cb-i18n/ts/src/app/app.module.ts b/public/docs/_examples/cb-i18n/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..64ad44075b
--- /dev/null
+++ b/public/docs/_examples/cb-i18n/ts/src/app/app.module.ts
@@ -0,0 +1,13 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+import { AppComponent } from './app.component';
+
+@NgModule({
+ imports: [ BrowserModule ],
+ declarations: [ AppComponent ],
+ bootstrap: [ AppComponent ]
+})
+
+export class AppModule { }
diff --git a/public/docs/_examples/cb-i18n/ts/src/app/i18n-providers.ts b/public/docs/_examples/cb-i18n/ts/src/app/i18n-providers.ts
new file mode 100644
index 0000000000..f0bb662dc3
--- /dev/null
+++ b/public/docs/_examples/cb-i18n/ts/src/app/i18n-providers.ts
@@ -0,0 +1,33 @@
+// #docregion
+import { TRANSLATIONS, TRANSLATIONS_FORMAT, LOCALE_ID } from '@angular/core';
+
+export function getTranslationProviders(): Promise {
+
+ // Get the locale id from the global
+ const locale = document['locale'] as string;
+
+ // return no providers if fail to get translation file for locale
+ const noProviders: Object[] = [];
+
+ // No locale or U.S. English: no translation providers
+ if (!locale || locale === 'en-US') {
+ return Promise.resolve(noProviders);
+ }
+
+ // Ex: 'locale/messages.es.xlf`
+ const translationFile = `./locale/messages.${locale}.xlf`;
+
+ return getTranslationsWithSystemJs(translationFile)
+ .then( (translations: string ) => [
+ { provide: TRANSLATIONS, useValue: translations },
+ { provide: TRANSLATIONS_FORMAT, useValue: 'xlf' },
+ { provide: LOCALE_ID, useValue: locale }
+ ])
+ .catch(() => noProviders); // ignore if file not found
+}
+
+declare var System: any;
+
+function getTranslationsWithSystemJs(file: string) {
+ return System.import(file + '!text'); // relies on text plugin
+}
diff --git a/public/docs/_examples/cb-i18n/ts/src/index.html b/public/docs/_examples/cb-i18n/ts/src/index.html
new file mode 100644
index 0000000000..ce90cd24c4
--- /dev/null
+++ b/public/docs/_examples/cb-i18n/ts/src/index.html
@@ -0,0 +1,39 @@
+
+
+
+
+ Angular i18n example
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
diff --git a/public/docs/_examples/cb-i18n/ts/src/locale/messages.es.xlf b/public/docs/_examples/cb-i18n/ts/src/locale/messages.es.xlf
new file mode 100644
index 0000000000..7b813c38dd
--- /dev/null
+++ b/public/docs/_examples/cb-i18n/ts/src/locale/messages.es.xlf
@@ -0,0 +1,41 @@
+
+
+
+
+
+ Hello i18n!
+ ¡Hola i18n!
+ An introduction header for this sample
+ User welcome
+
+
+ I don't output any element
+ No genero ningún elemento
+
+
+
+I don't output any element either
+
+ Yo tampoco genero ningún elemento
+ optional description
+ optional meaning
+
+
+ Angular logo
+ Logo de Angular
+
+
+
+ {wolves, plural, =0 {ningún lobo} =1 {un lobo} =2 {dos lobos} other {una horda de lobos}}
+
+
+ The hero is
+ El heroe es
+
+
+
+ {gender, select, m {hombre} f {mujer}}
+
+
+
+
diff --git a/public/docs/_examples/cb-i18n/ts/src/locale/messages.es.xlf.html b/public/docs/_examples/cb-i18n/ts/src/locale/messages.es.xlf.html
new file mode 100644
index 0000000000..a6cdccc6c1
--- /dev/null
+++ b/public/docs/_examples/cb-i18n/ts/src/locale/messages.es.xlf.html
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+ Hello i18n!
+ ¡Hola i18n!
+ An introduction header for this sample
+ User welcome
+
+
+
+
+ I don't output any element
+ No genero ningún elemento
+
+
+ I don't output any element either
+ Yo tampoco genero ningún elemento
+ optional description
+ optional meaning
+
+
+ Angular logo
+ Logo de Angular
+
+
+
+
+
+ {wolves, plural, =0 {ningún lobo} =1 {un lobo} =2 {dos lobos} other {una horda de lobos}}
+
+
+
+
+
+ The hero is
+ El heroe es
+
+
+
+
+
+ {gender, select, m {hombre} f {mujer}}
+
+
+
+
+
+
+
diff --git a/public/docs/_examples/cb-i18n/ts/src/main.1.ts b/public/docs/_examples/cb-i18n/ts/src/main.1.ts
new file mode 100644
index 0000000000..f332d1d245
--- /dev/null
+++ b/public/docs/_examples/cb-i18n/ts/src/main.1.ts
@@ -0,0 +1,6 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/cb-i18n/ts/src/main.ts b/public/docs/_examples/cb-i18n/ts/src/main.ts
new file mode 100644
index 0000000000..894cecfb10
--- /dev/null
+++ b/public/docs/_examples/cb-i18n/ts/src/main.ts
@@ -0,0 +1,10 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { getTranslationProviders } from './app/i18n-providers';
+
+import { AppModule } from './app/app.module';
+
+getTranslationProviders().then(providers => {
+ const options = { providers };
+ platformBrowserDynamic().bootstrapModule(AppModule, options);
+});
diff --git a/public/docs/_examples/cb-i18n/ts/src/systemjs-text-plugin.js b/public/docs/_examples/cb-i18n/ts/src/systemjs-text-plugin.js
new file mode 100644
index 0000000000..d5ca508fe0
--- /dev/null
+++ b/public/docs/_examples/cb-i18n/ts/src/systemjs-text-plugin.js
@@ -0,0 +1,14 @@
+// #docregion
+/*
+ SystemJS Text plugin from
+ https://github.com/systemjs/plugin-text/blob/master/text.js
+*/
+exports.translate = function(load) {
+ if (this.builder && this.transpiler) {
+ load.metadata.format = 'esm';
+ return 'exp' + 'ort var __useDefault = true; exp' + 'ort default ' + JSON.stringify(load.source) + ';';
+ }
+
+ load.metadata.format = 'amd';
+ return 'def' + 'ine(function() {\nreturn ' + JSON.stringify(load.source) + ';\n});';
+}
diff --git a/public/docs/_examples/cb-set-document-title/e2e-spec.ts b/public/docs/_examples/cb-set-document-title/e2e-spec.ts
new file mode 100644
index 0000000000..801b732995
--- /dev/null
+++ b/public/docs/_examples/cb-set-document-title/e2e-spec.ts
@@ -0,0 +1,31 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by, ElementFinder } from 'protractor';
+
+// gulp run-e2e-tests --filter=cb-set-document-title
+describe('Set Document Title', function () {
+
+ beforeAll(function () {
+ browser.get('');
+ });
+
+ it('should set the document title', function () {
+
+ let titles = [
+ 'Good morning!',
+ 'Good afternoon!',
+ 'Good evening!'
+ ];
+
+ element.all( by.css( 'ul li a' ) ).each(
+ function iterator( element: ElementFinder, i: number ) {
+
+ element.click();
+ expect( browser.getTitle() ).toEqual( titles[ i ] );
+
+ }
+ );
+
+ });
+
+});
diff --git a/public/docs/_examples/upgrade/ts/ng2_final/app/css/.gitkeep b/public/docs/_examples/cb-set-document-title/ts/example-config.json
similarity index 100%
rename from public/docs/_examples/upgrade/ts/ng2_final/app/css/.gitkeep
rename to public/docs/_examples/cb-set-document-title/ts/example-config.json
diff --git a/public/docs/_examples/cb-set-document-title/ts/plnkr.json b/public/docs/_examples/cb-set-document-title/ts/plnkr.json
new file mode 100644
index 0000000000..020d5a1db2
--- /dev/null
+++ b/public/docs/_examples/cb-set-document-title/ts/plnkr.json
@@ -0,0 +1,10 @@
+{
+ "description": "Set The Document Title In Angular",
+ "basePath": "src/",
+ "files": [
+ "!**/*.d.ts",
+ "!**/*.js",
+ "!**/*.[1].*"
+ ],
+ "tags": [ "cookbook" ]
+}
diff --git a/public/docs/_examples/cb-set-document-title/ts/src/app/app.component.ts b/public/docs/_examples/cb-set-document-title/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..f1905e635d
--- /dev/null
+++ b/public/docs/_examples/cb-set-document-title/ts/src/app/app.component.ts
@@ -0,0 +1,29 @@
+// #docplaster
+// #docregion
+// Import the native Angular services.
+import { Component } from '@angular/core';
+import { Title } from '@angular/platform-browser';
+
+@Component({
+selector: 'my-app',
+template:
+ `
+ Select a title to set on the current HTML document:
+
+
+
+ `
+})
+// #docregion class
+export class AppComponent {
+ public constructor(private titleService: Title ) { }
+
+ public setTitle( newTitle: string) {
+ this.titleService.setTitle( newTitle );
+ }
+}
+// #enddocregion class
diff --git a/public/docs/_examples/cb-set-document-title/ts/src/app/app.module.ts b/public/docs/_examples/cb-set-document-title/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..81f13c244c
--- /dev/null
+++ b/public/docs/_examples/cb-set-document-title/ts/src/app/app.module.ts
@@ -0,0 +1,19 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule, Title } from '@angular/platform-browser';
+
+import { AppComponent } from './app.component';
+
+@NgModule({
+ imports: [
+ BrowserModule
+ ],
+ declarations: [
+ AppComponent
+ ],
+ providers: [
+ Title
+ ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/cb-set-document-title/ts/src/index.html b/public/docs/_examples/cb-set-document-title/ts/src/index.html
new file mode 100644
index 0000000000..6b00948530
--- /dev/null
+++ b/public/docs/_examples/cb-set-document-title/ts/src/index.html
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+ Setting The Document Title Using The Title Service
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Setting The Document Title Using The Title Service
+
+
+ Loading app...
+
+
+
diff --git a/public/docs/_examples/cb-set-document-title/ts/src/main.ts b/public/docs/_examples/cb-set-document-title/ts/src/main.ts
new file mode 100644
index 0000000000..f332d1d245
--- /dev/null
+++ b/public/docs/_examples/cb-set-document-title/ts/src/main.ts
@@ -0,0 +1,6 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/cb-ts-to-js/e2e-spec.ts b/public/docs/_examples/cb-ts-to-js/e2e-spec.ts
new file mode 100644
index 0000000000..bc67bac8f0
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/e2e-spec.ts
@@ -0,0 +1,77 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by } from 'protractor';
+
+describe('TypeScript to Javascript tests', function () {
+
+ beforeAll(function () {
+ browser.get('');
+ });
+
+ it('should display the basic component example', function () {
+ testTag('hero-view', 'Hero Detail: Windstorm');
+ });
+
+ it('should display the component example with lifecycle methods', function () {
+ testTag('hero-lifecycle', 'Hero: Windstorm');
+ });
+
+ it('should display component with DI example', function () {
+ testTag('hero-di', 'Hero: Windstorm');
+ });
+
+ it('should display component with DI using @Inject example', function () {
+ testTag('hero-di-inject', 'Hero: Windstorm');
+ });
+
+ it('should support optional, attribute, and query injections', function () {
+ let app = element(by.css('hero-di-inject-additional'));
+ let h1 = app.element(by.css('h1'));
+ let okMsg = app.element(by.css('p'));
+
+ expect(h1.getText()).toBe('Tour of Heroes');
+ app.element(by.buttonText('OK')).click();
+ expect(okMsg.getText()).toBe('OK!');
+ });
+
+ it('should support component with inputs and outputs', function () {
+ let app = element(by.css('hero-io'));
+ let confirmComponent = app.element(by.css('app-confirm'));
+
+ confirmComponent.element(by.buttonText('OK')).click();
+ expect(app.element(by.cssContainingText('span', 'OK clicked')).isPresent()).toBe(true);
+
+ confirmComponent.element(by.buttonText('Cancel')).click();
+ expect(app.element(by.cssContainingText('span', 'Cancel clicked')).isPresent()).toBe(true);
+ });
+
+ it('should support host bindings and host listeners', function() {
+ let app = element(by.css('hero-host'));
+ let h1 = app.element(by.css('h1'));
+
+ expect(app.getAttribute('class')).toBe('heading');
+ expect(app.getAttribute('title')).toContain('Tooltip');
+
+ h1.click();
+ expect(h1.getAttribute('class')).toBe('active');
+
+ h1.click();
+ browser.actions().doubleClick(h1.getWebElement()).perform();
+ expect(h1.getAttribute('class')).toBe('active');
+ });
+
+ it('should support content and view queries', function() {
+ let app = element(by.css('hero-queries'));
+ let windstorm = app.element(by.css('view-child:first-child'));
+
+ app.element(by.css('button')).click();
+ expect(windstorm.element(by.css('h2')).getAttribute('class')).toBe('active');
+ expect(windstorm.element(by.css('content-child')).getText()).toBe('Active');
+ });
+
+ function testTag(selector: string, expectedText: string) {
+ let component = element(by.css(selector));
+ expect(component.getText()).toBe(expectedText);
+ }
+
+});
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6-decorators/example-config.json b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/example-config.json
new file mode 100644
index 0000000000..81f31aaf0d
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/example-config.json
@@ -0,0 +1,3 @@
+{
+ "build": "build:babel"
+}
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6-decorators/plnkr.json b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/plnkr.json
new file mode 100644
index 0000000000..447fc5f605
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/plnkr.json
@@ -0,0 +1,9 @@
+{
+ "description": "TypeScript to JavaScript",
+ "basePath": "src/",
+ "files":[
+ "!**/*.d.ts",
+ "!**/*.js"
+ ],
+ "tags":["cookbook"]
+}
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/.babelrc b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/.babelrc
new file mode 100644
index 0000000000..3aaf507508
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/.babelrc
@@ -0,0 +1,6 @@
+{
+ "presets": [
+ "es2015",
+ "angular2"
+ ]
+}
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/app.component.es6 b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/app.component.es6
new file mode 100644
index 0000000000..d425788f46
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/app.component.es6
@@ -0,0 +1,14 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ templateUrl: './app.component.html',
+ styles: [
+ // See hero-di-inject-additional.component
+ 'hero-host, hero-host-meta { border: 1px dashed black; display: block; padding: 4px;}',
+ '.heading {font-style: italic}'
+ ]
+})
+export class AppComponent {
+ title = 'ES6 JavaScript with Decorators';
+}
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/app.component.html b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/app.component.html
new file mode 100644
index 0000000000..995645073a
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/app.component.html
@@ -0,0 +1,31 @@
+
+{{title}}
+Classes and Class Metadata
+Input and Output Decorators
+Dependency Injection
+Host Metadata
+View and Child Metadata
+
+
+
+
+
+
+
+
+
+
+
+Dependency Injection
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/app.module.es6 b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/app.module.es6
new file mode 100644
index 0000000000..9c248a7ad3
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/app.module.es6
@@ -0,0 +1,55 @@
+import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+import { AppComponent } from './app.component';
+import { ConfirmComponent } from './confirm.component';
+// #docregion appimport
+import { HeroComponent } from './hero.component';
+// #enddocregion appimport
+import { HeroComponent as HeroDIComponent } from './hero-di.component';
+import { HeroComponent as HeroDIInjectComponent } from './hero-di-inject.component';
+import { HeroComponent as HeroDIInjectAdditionalComponent } from './hero-di-inject-additional.component';
+import { HeroHostComponent } from './hero-host.component';
+import { HeroHostMetaComponent } from './hero-host-meta.component';
+import { HeroIOComponent } from './hero-io.component';
+import { HeroComponent as HeroLifecycleComponent } from './hero-lifecycle.component';
+import { HeroQueriesComponent, ViewChildComponent, ContentChildComponent } from './hero-queries.component';
+import { HeroTitleComponent } from './hero-title.component';
+
+import { DataService } from './data.service';
+
+@NgModule({
+ imports: [
+ BrowserModule
+ ],
+ declarations: [
+ AppComponent,
+ ConfirmComponent,
+ HeroComponent,
+ HeroDIComponent,
+ HeroDIInjectComponent,
+ HeroDIInjectAdditionalComponent,
+ HeroHostComponent, HeroHostMetaComponent,
+ HeroIOComponent,
+ HeroLifecycleComponent,
+ HeroQueriesComponent, ViewChildComponent, ContentChildComponent,
+ HeroTitleComponent
+ ],
+ providers: [
+ DataService,
+ { provide: 'heroName', useValue: 'Windstorm' }
+ ],
+ bootstrap: [ AppComponent ],
+
+ // schemas: [ NO_ERRORS_SCHEMA ] // helpful for debugging
+})
+export class AppModule { }
+
+/* tslint:disable no-unused-variable */
+// #docregion ng2import
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import {
+ LocationStrategy,
+ HashLocationStrategy
+} from '@angular/common';
+// #enddocregion ng2import
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/confirm.component.es6 b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/confirm.component.es6
new file mode 100644
index 0000000000..f01fa4de40
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/confirm.component.es6
@@ -0,0 +1,21 @@
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+
+// #docregion
+@Component({
+ selector: 'app-confirm',
+ templateUrl: './confirm.component.html'
+})
+export class ConfirmComponent {
+ @Input() okMsg = '';
+ @Input('cancelMsg') notOkMsg = '';
+ @Output() ok = new EventEmitter();
+ @Output('cancel') notOk = new EventEmitter();
+
+ onOkClick() {
+ this.ok.emit(true);
+ }
+ onNotOkClick() {
+ this.notOk.emit(true);
+ }
+}
+// #enddocregion
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/confirm.component.html b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/confirm.component.html
new file mode 100644
index 0000000000..45275d218a
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/confirm.component.html
@@ -0,0 +1,6 @@
+
+ {{okMsg}}
+
+
+ {{notOkMsg}}
+
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/data.service.es6 b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/data.service.es6
new file mode 100644
index 0000000000..cd7f9e1aae
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/data.service.es6
@@ -0,0 +1,10 @@
+import { Injectable } from '@angular/core';
+
+@Injectable()
+export class DataService {
+ constructor() { }
+
+ getHeroName() {
+ return 'Windstorm';
+ }
+}
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-di-inject-additional.component.es6 b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-di-inject-additional.component.es6
new file mode 100644
index 0000000000..ec460a9dbc
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-di-inject-additional.component.es6
@@ -0,0 +1,7 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'hero-di-inject-additional',
+ template: ` `
+})
+export class HeroComponent { }
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-di-inject.component.es6 b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-di-inject.component.es6
new file mode 100644
index 0000000000..94b42f956a
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-di-inject.component.es6
@@ -0,0 +1,13 @@
+import { Component, Inject } from '@angular/core';
+
+// #docregion
+@Component({
+ selector: 'hero-di-inject',
+ template: `Hero: {{name}} `
+})
+export class HeroComponent {
+ constructor(@Inject('heroName') name) {
+ this.name = name;
+ }
+}
+// #enddocregion
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-di.component.es6 b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-di.component.es6
new file mode 100644
index 0000000000..3a17abd281
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-di.component.es6
@@ -0,0 +1,15 @@
+// #docregion
+import { Component } from '@angular/core';
+import { DataService } from './data.service';
+
+@Component({
+ selector: 'hero-di',
+ template: `Hero: {{name}} `
+})
+export class HeroComponent {
+ name = '';
+ constructor(dataService: DataService) {
+ this.name = dataService.getHeroName();
+ }
+}
+// #enddocregion
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-host-meta.component.es6 b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-host-meta.component.es6
new file mode 100644
index 0000000000..fefe4a5470
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-host-meta.component.es6
@@ -0,0 +1,44 @@
+import { Component } from '@angular/core';
+
+// #docregion
+@Component({
+ selector: 'hero-host-meta',
+ template: `
+ Hero Host in Metadata
+ Heading clicks: {{clicks}}
+ `,
+ host: {
+ // HostBindings to the element
+ '[title]': 'title',
+ '[class.heading]': 'headingClass',
+
+ // HostListeners on the entire element
+ '(click)': 'clicked()',
+ '(mouseenter)': 'enter($event)',
+ '(mouseleave)': 'leave($event)'
+ },
+ // Styles within (but excluding) the element
+ styles: ['.active {background-color: coral;}']
+})
+export class HeroHostMetaComponent {
+ title = 'Hero Host in Metadata Tooltip';
+ headingClass = true;
+
+ active = false;
+ clicks = 0;
+
+ clicked() {
+ this.clicks += 1;
+ }
+
+ enter(event: Event) {
+ this.active = true;
+ this.headingClass = false;
+ }
+
+ leave(event: Event) {
+ this.active = false;
+ this.headingClass = true;
+ }
+}
+// #enddocregion
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-host.component.es6 b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-host.component.es6
new file mode 100644
index 0000000000..e8d72233c8
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-host.component.es6
@@ -0,0 +1,39 @@
+import { Component, HostBinding, HostListener } from '@angular/core';
+
+// #docregion
+@Component({
+ selector: 'hero-host',
+ template: `
+ Hero Host in Decorators
+ Heading clicks: {{clicks}}
+ `,
+ // Styles within (but excluding) the element
+ styles: ['.active {background-color: yellow;}']
+})
+export class HeroHostComponent {
+ // HostBindings to the element
+ @HostBinding() title = 'Hero Host in Decorators Tooltip';
+ @HostBinding('class.heading') headingClass = true;
+
+ active = false;
+ clicks = 0;
+
+ // HostListeners on the entire element
+ @HostListener('click')
+ clicked() {
+ this.clicks += 1;
+ }
+
+ @HostListener('mouseenter', ['$event'])
+ enter(event: Event) {
+ this.active = true;
+ this.headingClass = false;
+ }
+
+ @HostListener('mouseleave', ['$event'])
+ leave(event: Event) {
+ this.active = false;
+ this.headingClass = true;
+ }
+}
+// #enddocregion
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-io.component.es6 b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-io.component.es6
new file mode 100644
index 0000000000..4b36411e78
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-io.component.es6
@@ -0,0 +1,26 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'hero-io',
+ template: `
+
+
+ OK clicked
+ Cancel clicked
+ `
+})
+export class HeroIOComponent {
+ okClicked = false;
+ cancelClicked = false;
+
+ onOk() {
+ this.okClicked = true;
+ }
+
+ onCancel() {
+ this.cancelClicked = true;
+ }
+}
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-lifecycle.component.es6 b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-lifecycle.component.es6
new file mode 100644
index 0000000000..2539266597
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-lifecycle.component.es6
@@ -0,0 +1,14 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'hero-lifecycle',
+ template: `Hero: {{name}} `
+})
+export class HeroComponent {
+ name = '';
+ ngOnInit() {
+ // todo: fetch from server async
+ setTimeout(() => this.name = 'Windstorm', 0);
+ }
+}
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-queries.component.es6 b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-queries.component.es6
new file mode 100644
index 0000000000..fced43d4d7
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-queries.component.es6
@@ -0,0 +1,81 @@
+import {
+ Component,
+ ContentChild,
+ Input,
+ QueryList,
+ ViewChildren
+} from '@angular/core';
+
+@Component({
+ selector: 'content-child',
+ template: `
+
+ Active
+ `
+})
+export class ContentChildComponent {
+ active = false;
+
+ activate() {
+ this.active = true;
+ }
+}
+
+////////////////////
+
+// #docregion content
+@Component({
+ selector: 'view-child',
+ template: `
+
+ {{hero.name}}
+
+ `,
+ styles: ['.active {font-weight: bold; background-color: skyblue;}']
+})
+export class ViewChildComponent {
+ @Input() hero;
+ active = false;
+
+ @ContentChild(ContentChildComponent) content;
+
+ activate() {
+ this.active = !this.active;
+ this.content.activate();
+ }
+}
+// #enddocregion content
+
+////////////////////
+
+// #docregion view
+@Component({
+ selector: 'hero-queries',
+ template: `
+
+
+
+ {{buttonLabel}} All
+ `
+})
+export class HeroQueriesComponent {
+ active = false;
+ heroData = [
+ {id: 1, name: 'Windstorm'},
+ {id: 2, name: 'LaughingGas'}
+ ];
+
+ @ViewChildren(ViewChildComponent) views;
+
+ activate() {
+ this.active = !this.active;
+ this.views.forEach(
+ view => view.activate()
+ );
+ }
+
+ get buttonLabel() {
+ return this.active ? 'Deactivate' : 'Activate';
+ }
+}
+// #enddocregion view
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-title.component.es6 b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-title.component.es6
new file mode 100644
index 0000000000..04c14a9631
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-title.component.es6
@@ -0,0 +1,25 @@
+import { Attribute, Component, Inject, Optional } from '@angular/core';
+
+// #docregion
+// #docregion templateUrl
+@Component({
+ selector: 'hero-title',
+ templateUrl: './hero-title.component.html'
+})
+// #enddocregion templateUrl
+export class HeroTitleComponent {
+ msg = '';
+ constructor(
+ @Inject('titlePrefix') @Optional() titlePrefix,
+ @Attribute('title') title
+ ) {
+ this.titlePrefix = titlePrefix;
+ this.title = title;
+ }
+
+ ok() {
+ this.msg = 'OK!';
+ }
+}
+// #enddocregion
+
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-title.component.html b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-title.component.html
new file mode 100644
index 0000000000..164683cb7c
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero-title.component.html
@@ -0,0 +1,4 @@
+
+{{titlePrefix}} {{title}}
+OK
+{{ msg }}
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero.component.es6 b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero.component.es6
new file mode 100644
index 0000000000..2976ec605e
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/app/hero.component.es6
@@ -0,0 +1,15 @@
+// #docregion
+// #docregion metadata
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'hero-view',
+ template: '{{title}}: {{getName()}} '
+})
+// #docregion appexport, class
+export class HeroComponent {
+ title = 'Hero Detail';
+ getName() {return 'Windstorm'; }
+}
+// #enddocregion appexport, class
+// #enddocregion metadata
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/index.html b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/index.html
new file mode 100644
index 0000000000..2a94db38cc
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/index.html
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+ TypeScript to JavaScript
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/main.es6 b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/main.es6
new file mode 100644
index 0000000000..f22933ba8e
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6-decorators/src/main.es6
@@ -0,0 +1,4 @@
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6/example-config.json b/public/docs/_examples/cb-ts-to-js/js-es6/example-config.json
new file mode 100644
index 0000000000..81f31aaf0d
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6/example-config.json
@@ -0,0 +1,3 @@
+{
+ "build": "build:babel"
+}
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6/plnkr.json b/public/docs/_examples/cb-ts-to-js/js-es6/plnkr.json
new file mode 100644
index 0000000000..447fc5f605
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6/plnkr.json
@@ -0,0 +1,9 @@
+{
+ "description": "TypeScript to JavaScript",
+ "basePath": "src/",
+ "files":[
+ "!**/*.d.ts",
+ "!**/*.js"
+ ],
+ "tags":["cookbook"]
+}
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6/src/.babelrc b/public/docs/_examples/cb-ts-to-js/js-es6/src/.babelrc
new file mode 100644
index 0000000000..3c078e9f99
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6/src/.babelrc
@@ -0,0 +1,5 @@
+{
+ "presets": [
+ "es2015"
+ ]
+}
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6/src/app/app.component.es6 b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/app.component.es6
new file mode 100644
index 0000000000..6079f7f246
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/app.component.es6
@@ -0,0 +1,19 @@
+import { Component } from '@angular/core';
+
+export class AppComponent {
+ constructor() {
+ this.title = 'Plain ES6 JavaScript';
+ }
+}
+
+AppComponent.annotations = [
+ new Component({
+ selector: 'my-app',
+ templateUrl: './app.component.html',
+ styles: [
+ // See hero-di-inject-additional.component
+ 'hero-host { border: 1px dashed black; display: block; padding: 4px;}',
+ '.heading {font-style: italic}'
+ ]
+ })
+];
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6/src/app/app.component.html b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/app.component.html
new file mode 100644
index 0000000000..52b9b4580e
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/app.component.html
@@ -0,0 +1,30 @@
+
+{{title}}
+Classes and Class Metadata
+Input and Output Metadata
+Dependency Injection
+Host Metadata
+View and Child Metadata
+
+
+
+
+
+
+
+
+
+
+
+Dependency Injection
+
+
+
+
+
+
+
+
+
+
+
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6/src/app/app.module.es6 b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/app.module.es6
new file mode 100644
index 0000000000..f31141e78f
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/app.module.es6
@@ -0,0 +1,56 @@
+import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+import { AppComponent } from './app.component';
+import { ConfirmComponent } from './confirm.component';
+// #docregion appimport
+import { HeroComponent } from './hero.component';
+
+// #enddocregion appimport
+import { HeroComponent as HeroDIComponent } from './hero-di.component';
+import { HeroComponent as HeroDIInjectComponent } from './hero-di-inject.component';
+import { HeroComponent as HeroDIInjectAdditionalComponent } from './hero-di-inject-additional.component';
+import { HeroHostComponent } from './hero-host.component';
+import { HeroIOComponent } from './hero-io.component';
+import { HeroComponent as HeroLifecycleComponent } from './hero-lifecycle.component';
+import { HeroQueriesComponent, ViewChildComponent, ContentChildComponent } from './hero-queries.component';
+import { HeroTitleComponent } from './hero-title.component';
+
+import { DataService } from './data.service';
+
+export class AppModule { }
+
+AppModule.annotations = [
+ new NgModule({
+ imports: [ BrowserModule],
+ declarations: [
+ AppComponent,
+ ConfirmComponent,
+ HeroComponent,
+ HeroDIComponent,
+ HeroDIInjectComponent,
+ HeroDIInjectAdditionalComponent,
+ HeroHostComponent,
+ HeroIOComponent,
+ HeroLifecycleComponent,
+ HeroQueriesComponent, ViewChildComponent, ContentChildComponent,
+ HeroTitleComponent
+ ],
+ providers: [
+ DataService,
+ { provide: 'heroName', useValue: 'Windstorm' }
+ ],
+ bootstrap: [ AppComponent ],
+
+ // schemas: [ NO_ERRORS_SCHEMA ] // helpful for debugging
+ })
+]
+
+/* tslint:disable no-unused-variable */
+// #docregion ng2import
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import {
+ LocationStrategy,
+ HashLocationStrategy
+} from '@angular/common';
+// #enddocregion ng2import
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6/src/app/confirm.component.es6 b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/confirm.component.es6
new file mode 100644
index 0000000000..296268dda4
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/confirm.component.es6
@@ -0,0 +1,31 @@
+import { Component, EventEmitter } from '@angular/core';
+
+// #docregion
+export class ConfirmComponent {
+ constructor(){
+ this.ok = new EventEmitter();
+ this.notOk = new EventEmitter();
+ }
+ onOkClick() {
+ this.ok.emit(true);
+ }
+ onNotOkClick() {
+ this.notOk.emit(true);
+ }
+}
+
+ConfirmComponent.annotations = [
+ new Component({
+ selector: 'app-confirm',
+ templateUrl: './confirm.component.html',
+ inputs: [
+ 'okMsg',
+ 'notOkMsg: cancelMsg'
+ ],
+ outputs: [
+ 'ok',
+ 'notOk: cancel'
+ ]
+ })
+];
+// #enddocregion
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6/src/app/confirm.component.html b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/confirm.component.html
new file mode 100644
index 0000000000..45275d218a
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/confirm.component.html
@@ -0,0 +1,6 @@
+
+ {{okMsg}}
+
+
+ {{notOkMsg}}
+
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6/src/app/data.service.es6 b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/data.service.es6
new file mode 100644
index 0000000000..de023ce5a0
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/data.service.es6
@@ -0,0 +1,13 @@
+import { Injectable } from '@angular/core';
+
+export class DataService {
+ constructor() {
+ }
+ getHeroName() {
+ return 'Windstorm';
+ }
+}
+
+DataService.annotations = [
+ new Injectable()
+];
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-di-inject-additional.component.es6 b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-di-inject-additional.component.es6
new file mode 100644
index 0000000000..5eb9bab815
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-di-inject-additional.component.es6
@@ -0,0 +1,10 @@
+import { Component } from '@angular/core';
+
+export class HeroComponent { }
+
+HeroComponent.annotations = [
+ new Component({
+ selector: 'hero-di-inject-additional',
+ template: ` `
+ })
+];
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-di-inject.component.es6 b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-di-inject.component.es6
new file mode 100644
index 0000000000..2f95a0b981
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-di-inject.component.es6
@@ -0,0 +1,20 @@
+import { Component, Inject } from '@angular/core';
+
+// #docregion
+export class HeroComponent {
+ constructor(name) {
+ this.name = name;
+ }
+}
+
+HeroComponent.annotations = [
+ new Component({
+ selector: 'hero-di-inject',
+ template: `Hero: {{name}} `
+ })
+];
+
+HeroComponent.parameters = [
+ [new Inject('heroName')]
+];
+// #enddocregion
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-di.component.es6 b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-di.component.es6
new file mode 100644
index 0000000000..a18b1ba777
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-di.component.es6
@@ -0,0 +1,21 @@
+// #docregion
+import { Component } from '@angular/core';
+import { DataService } from './data.service';
+
+export class HeroComponent {
+ constructor(dataService) {
+ this.name = dataService.getHeroName();
+ }
+}
+
+HeroComponent.annotations = [
+ new Component({
+ selector: 'hero-di',
+ template: `Hero: {{name}} `
+ })
+];
+
+HeroComponent.parameters = [
+ [DataService]
+];
+// #enddocregion
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-host.component.es6 b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-host.component.es6
new file mode 100644
index 0000000000..b06701ee8d
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-host.component.es6
@@ -0,0 +1,50 @@
+import { Component } from '@angular/core';
+
+// #docregion
+export class HeroHostComponent {
+ constructor() {
+ this.active = false;
+ this.clicks = 0;
+ this.headingClass = true;
+ this.title = 'Hero Host Tooltip';
+ }
+
+ clicked() {
+ this.clicks += 1;
+ }
+
+ enter(event) {
+ this.active = true;
+ this.headingClass = false;
+ }
+
+ leave(event) {
+ this.active = false;
+ this.headingClass = true;
+ }
+}
+
+// #docregion metadata
+HeroHostComponent.annotations = [
+ new Component({
+ selector: 'hero-host',
+ template: `
+ Hero Host
+ Heading clicks: {{clicks}}
+ `,
+ host: {
+ // HostBindings to the element
+ '[title]': 'title',
+ '[class.heading]': 'headingClass',
+ '(click)': 'clicked()',
+
+ // HostListeners on the entire element
+ '(mouseenter)': 'enter($event)',
+ '(mouseleave)': 'leave($event)'
+ },
+ // Styles within (but excluding) the element
+ styles: ['.active {background-color: yellow;}']
+ })
+];
+// #enddocregion metadata
+// #enddocregion
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-io.component.es6 b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-io.component.es6
new file mode 100644
index 0000000000..0dc8c08f2d
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-io.component.es6
@@ -0,0 +1,31 @@
+import { Component } from '@angular/core';
+
+export class HeroIOComponent {
+ constructor() {
+ this.okClicked = false;
+ this.cancelClicked = false;
+ }
+
+ onOk() {
+ this.okClicked = true;
+ }
+
+ onCancel() {
+ this.cancelClicked = true;
+ }
+}
+
+HeroIOComponent.annotations = [
+ new Component({
+ selector: 'hero-io',
+ template: `
+
+
+ OK clicked
+ Cancel clicked
+ `
+ })
+];
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-lifecycle.component.es6 b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-lifecycle.component.es6
new file mode 100644
index 0000000000..b394ff59aa
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-lifecycle.component.es6
@@ -0,0 +1,15 @@
+// #docregion
+import { Component } from '@angular/core';
+export class HeroComponent {
+ ngOnInit() {
+ // todo: fetch from server async
+ setTimeout(() => this.name = 'Windstorm', 0);
+ }
+}
+
+HeroComponent.annotations = [
+ new Component({
+ selector: 'hero-lifecycle',
+ template: `Hero: {{name}} `
+ })
+];
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-queries.component.es6 b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-queries.component.es6
new file mode 100644
index 0000000000..bf3b914406
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-queries.component.es6
@@ -0,0 +1,97 @@
+import {
+ Component,
+ ContentChild,
+ Input,
+ QueryList,
+ ViewChildren
+} from '@angular/core';
+
+export class ContentChildComponent {
+ constructor() {
+ this.active = false;
+ }
+
+ activate() {
+ this.active = !this.active;
+ }
+}
+
+ContentChildComponent.annotations = [
+ new Component({
+ selector: 'content-child',
+ template: `
+
+ Active
+ `
+ })
+];
+
+////////////////////
+
+// #docregion content
+export class ViewChildComponent {
+ constructor() {
+ this.active = false;
+ }
+
+ activate() {
+ this.active = !this.active;
+ this.content.activate();
+ }
+}
+
+ViewChildComponent.annotations = [
+ new Component({
+ selector: 'view-child',
+ template: `
+ {{hero.name}}
+
+ `,
+ styles: ['.active {font-weight: bold; background-color: skyblue;}'],
+ inputs: ['hero'],
+ queries: {
+ content: new ContentChild(ContentChildComponent)
+ }
+ })
+];
+// #enddocregion content
+
+////////////////////
+
+// #docregion view
+export class HeroQueriesComponent {
+ constructor(){
+ this.active = false;
+ this.heroData = [
+ {id: 1, name: 'Windstorm'},
+ {id: 2, name: 'LaughingGas'}
+ ];
+ }
+
+ activate() {
+ this.active = !this.active;
+ this.views.forEach(
+ view => view.activate()
+ );
+ }
+
+ get buttonLabel() {
+ return this.active ? 'Deactivate' : 'Activate';
+ }
+}
+
+HeroQueriesComponent.annotations = [
+ new Component({
+ selector: 'hero-queries',
+ template: `
+
+
+
+ {{buttonLabel}} All
+ `,
+ queries: {
+ views: new ViewChildren(ViewChildComponent)
+ }
+ })
+];
+// #enddocregion view
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-title.component.es6 b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-title.component.es6
new file mode 100644
index 0000000000..4b89dfba83
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-title.component.es6
@@ -0,0 +1,28 @@
+import { Attribute, Component, Inject, Optional } from '@angular/core';
+
+// #docregion
+export class HeroTitleComponent {
+ constructor(titlePrefix, title) {
+ this.titlePrefix = titlePrefix;
+ this.title = title;
+ this.msg = '';
+ }
+
+ ok() {
+ this.msg = 'OK!';
+ }
+}
+
+// #docregion templateUrl
+HeroTitleComponent.annotations = [
+ new Component({
+ selector: 'hero-title',
+ templateUrl: './hero-title.component.html'
+ })
+];
+// #enddocregion templateUrl
+
+HeroTitleComponent.parameters = [
+ [new Optional(), new Inject('titlePrefix')],
+ [new Attribute('title')]
+];
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-title.component.html b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-title.component.html
new file mode 100644
index 0000000000..164683cb7c
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero-title.component.html
@@ -0,0 +1,4 @@
+
+{{titlePrefix}} {{title}}
+OK
+{{ msg }}
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero.component.es6 b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero.component.es6
new file mode 100644
index 0000000000..350f946460
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6/src/app/hero.component.es6
@@ -0,0 +1,21 @@
+// #docplaster
+// #docregion
+// #docregion metadata
+import { Component } from '@angular/core';
+
+// #docregion appexport, class
+export class HeroComponent {
+ constructor() {
+ this.title = 'Hero Detail';
+ }
+ getName() {return 'Windstorm'; }
+}
+// #enddocregion appexport, class
+
+HeroComponent.annotations = [
+ new Component({
+ selector: 'hero-view',
+ template: '{{title}}: {{getName()}} '
+ })
+];
+// #enddocregion metadata
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6/src/index.html b/public/docs/_examples/cb-ts-to-js/js-es6/src/index.html
new file mode 100644
index 0000000000..2a94db38cc
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6/src/index.html
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+ TypeScript to JavaScript
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
diff --git a/public/docs/_examples/cb-ts-to-js/js-es6/src/main.es6 b/public/docs/_examples/cb-ts-to-js/js-es6/src/main.es6
new file mode 100644
index 0000000000..f22933ba8e
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js-es6/src/main.es6
@@ -0,0 +1,4 @@
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/cb-ts-to-js/js/example-config.json b/public/docs/_examples/cb-ts-to-js/js/example-config.json
new file mode 100644
index 0000000000..81f31aaf0d
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js/example-config.json
@@ -0,0 +1,3 @@
+{
+ "build": "build:babel"
+}
diff --git a/public/docs/_examples/cb-ts-to-js/js/plnkr.json b/public/docs/_examples/cb-ts-to-js/js/plnkr.json
new file mode 100644
index 0000000000..5e1eb188be
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js/plnkr.json
@@ -0,0 +1,8 @@
+{
+ "description": "TypeScript to JavaScript",
+ "basePath": "src/",
+ "files":[
+ "!**/karma*.*"
+ ],
+ "tags":["cookbook"]
+}
diff --git a/public/docs/_examples/cb-ts-to-js/js/src/app/app.component.html b/public/docs/_examples/cb-ts-to-js/js/src/app/app.component.html
new file mode 100644
index 0000000000..4ca26f2657
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js/src/app/app.component.html
@@ -0,0 +1,47 @@
+
+{{title}}
+Classes and Class Metadata
+Interfaces
+Input and Output Metadata
+Dependency Injection
+Host Metadata
+View and Child Metadata
+
+
+
+
+
+
+
+
+Interfaces
+
+Interfaces (DSL)
+
+
+
+
+
+
+
+
+
+Dependency Injection
+
+
+
+
+Dependency Injection (DSL)
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/public/docs/_examples/cb-ts-to-js/js/src/app/app.component.js b/public/docs/_examples/cb-ts-to-js/js/src/app/app.component.js
new file mode 100644
index 0000000000..b6d1ec29b0
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js/src/app/app.component.js
@@ -0,0 +1,20 @@
+(function(app) {
+
+app.AppComponent = AppComponent;
+function AppComponent() {
+ this.title = 'ES5 JavaScript';
+}
+
+AppComponent.annotations = [
+ new ng.core.Component({
+ selector: 'my-app',
+ templateUrl: 'app/app.component.html',
+ styles: [
+ // See hero-di-inject-additional.component
+ 'hero-host, hero-host-dsl { border: 1px dashed black; display: block; padding: 4px;}',
+ '.heading {font-style: italic}'
+ ]
+ })
+];
+
+})(window.app = window.app || {});
diff --git a/public/docs/_examples/cb-ts-to-js/js/src/app/app.module.js b/public/docs/_examples/cb-ts-to-js/js/src/app/app.module.js
new file mode 100644
index 0000000000..fc2300a89b
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js/src/app/app.module.js
@@ -0,0 +1,46 @@
+(function(app) {
+
+app.AppModule = AppModule;
+function AppModule() { }
+
+AppModule.annotations = [
+ new ng.core.NgModule({
+ imports: [ ng.platformBrowser.BrowserModule ],
+ declarations: [
+ app.AppComponent,
+ app.ConfirmComponent, app.ConfirmDslComponent,
+ app.HeroComponent, app.HeroDslComponent,
+ app.HeroDIComponent, app.HeroDIDslComponent,
+ app.HeroDIInjectComponent, app.HeroDIInjectDslComponent,
+ app.HeroDIInjectAdditionalComponent, app.HeroDIInjectAdditionalDslComponent,
+ app.HeroHostComponent, app.HeroHostDslComponent,
+ app.HeroIOComponent, app.HeroIODslComponent,
+ app.HeroLifecycleComponent, app.HeroLifecycleDslComponent,
+ app.heroQueries.HeroQueriesComponent, app.heroQueries.ViewChildComponent, app.heroQueries.ContentChildComponent,
+ app.HeroTitleComponent, app.HeroTitleDslComponent
+ ],
+ providers: [
+ app.DataService,
+ { provide: 'heroName', useValue: 'Windstorm' }
+ ],
+ bootstrap: [ app.AppComponent ],
+
+ // schemas: [ ng.core.NO_ERRORS_SCHEMA ] // helpful for debugging!
+ })
+]
+
+})(window.app = window.app || {});
+
+
+///// For documentation only /////
+(function () {
+ // #docregion appimport
+ var HeroComponent = app.HeroComponent;
+ // #enddocregion appimport
+
+ // #docregion ng2import
+ var platformBrowserDynamic = ng.platformBrowserDynamic.platformBrowserDynamic;
+ var LocationStrategy = ng.common.LocationStrategy;
+ var HashLocationStrategy = ng.common.HashLocationStrategy;
+ // #enddocregion ng2import
+})
diff --git a/public/docs/_examples/cb-ts-to-js/js/src/app/confirm.component.html b/public/docs/_examples/cb-ts-to-js/js/src/app/confirm.component.html
new file mode 100644
index 0000000000..45275d218a
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js/src/app/confirm.component.html
@@ -0,0 +1,6 @@
+
+ {{okMsg}}
+
+
+ {{notOkMsg}}
+
diff --git a/public/docs/_examples/cb-ts-to-js/js/src/app/confirm.component.js b/public/docs/_examples/cb-ts-to-js/js/src/app/confirm.component.js
new file mode 100644
index 0000000000..b76d3f54aa
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js/src/app/confirm.component.js
@@ -0,0 +1,75 @@
+(function(app) {
+
+ // #docregion
+ app.ConfirmComponent = ConfirmComponent;
+
+ ConfirmComponent.annotations = [
+ new ng.core.Component({
+ selector: 'app-confirm',
+ templateUrl: 'app/confirm.component.html',
+ inputs: [
+ 'okMsg',
+ 'notOkMsg: cancelMsg'
+ ],
+ outputs: [
+ 'ok',
+ 'notOk: cancel'
+ ]
+ })
+ ];
+
+ function ConfirmComponent() {
+ this.ok = new ng.core.EventEmitter();
+ this.notOk = new ng.core.EventEmitter();
+ }
+
+ ConfirmComponent.prototype.onOkClick = function() {
+ this.ok.emit(true);
+ }
+
+ ConfirmComponent.prototype.onNotOkClick = function() {
+ this.notOk.emit(true);
+ }
+ // #enddocregion
+
+})(window.app = window.app || {});
+
+/////// DSL version ////////
+
+(function(app) {
+
+ var old = app.ConfirmComponent;
+
+ // #docregion dsl
+ app.ConfirmComponent = ng.core.Component({
+ selector: 'app-confirm-dsl',
+ templateUrl: 'app/confirm.component.html',
+ inputs: [
+ 'okMsg',
+ 'notOkMsg: cancelMsg'
+ ],
+ outputs: [
+ 'ok',
+ 'notOk: cancel'
+ ]
+ })
+ .Class({
+ constructor: function ConfirmComponent() {
+ this.ok = new ng.core.EventEmitter();
+ this.notOk = new ng.core.EventEmitter();
+ },
+
+ onOkClick: function() {
+ this.ok.emit(true);
+ },
+
+ onNotOkClick: function() {
+ this.notOk.emit(true);
+ }
+ });
+ // #enddocregion dsl
+
+ app.ConfirmDslComponent = app.ConfirmComponent;
+ app.ConfirmComponent = old;
+
+})(window.app = window.app || {});
diff --git a/public/docs/_examples/cb-ts-to-js/js/src/app/data.service.js b/public/docs/_examples/cb-ts-to-js/js/src/app/data.service.js
new file mode 100644
index 0000000000..643bb57dca
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js/src/app/data.service.js
@@ -0,0 +1,10 @@
+(function(app) {
+
+ app.DataService = DataService;
+ function DataService() { }
+
+ DataService.prototype.getHeroName = function() {
+ return 'Windstorm';
+ };
+
+})(window.app = window.app || {});
diff --git a/public/docs/_examples/cb-ts-to-js/js/src/app/hero-di-inject-additional.component.js b/public/docs/_examples/cb-ts-to-js/js/src/app/hero-di-inject-additional.component.js
new file mode 100644
index 0000000000..450cc53847
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js/src/app/hero-di-inject-additional.component.js
@@ -0,0 +1,36 @@
+(function(app) {
+
+ var old = app.HeroComponent;
+
+ app.HeroComponent = HeroComponent;
+
+ HeroComponent.annotations = [
+ new ng.core.Component({
+ selector: 'hero-di-inject-additional',
+ template: ' '
+ })
+ ];
+
+ function HeroComponent() {}
+
+ app.HeroDIInjectAdditionalComponent = app.HeroComponent;
+ app.HeroComponent = old;
+
+})(window.app = window.app || {});
+
+////// DSL Version /////////
+(function(app) {
+
+ var old = app.HeroComponent;
+
+ app.HeroComponent = ng.core.Component({
+ selector: 'hero-di-inject-additional-dsl',
+ template: ' '
+ }).Class({
+ constructor: function HeroComponent() { }
+ });
+
+ app.HeroDIInjectAdditionalDslComponent = app.HeroComponent;
+ app.HeroComponent = old;
+
+})(window.app = window.app || {});
diff --git a/public/docs/_examples/cb-ts-to-js/js/src/app/hero-di-inject.component.js b/public/docs/_examples/cb-ts-to-js/js/src/app/hero-di-inject.component.js
new file mode 100644
index 0000000000..879365208c
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js/src/app/hero-di-inject.component.js
@@ -0,0 +1,51 @@
+(function(app) {
+
+ var old = app.HeroComponent;
+
+ // #docregion
+ app.HeroComponent = HeroComponent;
+
+ HeroComponent.annotations = [
+ new ng.core.Component({
+ selector: 'hero-di-inject',
+ template: 'Hero: {{name}} '
+ })
+ ];
+
+ HeroComponent.parameters = [ 'heroName' ];
+
+ function HeroComponent(name) {
+ this.name = name;
+ }
+ // #enddocregion
+
+ app.HeroDIInjectComponent = app.HeroComponent;
+ app.HeroComponent = old;
+
+})(window.app = window.app || {});
+
+/////// DSL version ////////
+
+(function(app) {
+
+ var old = app.HeroComponent;
+
+ // #docregion dsl
+ app.HeroComponent = ng.core.Component({
+ selector: 'hero-di-inject-dsl',
+ template: 'Hero: {{name}} '
+ })
+ .Class({
+ constructor: [
+ new ng.core.Inject('heroName'),
+ function HeroComponent(name) {
+ this.name = name;
+ }
+ ]
+ });
+ // #enddocregion dsl
+
+ app.HeroDIInjectDslComponent = app.HeroComponent;
+ app.HeroComponent = old;
+
+})(window.app = window.app || {});
diff --git a/public/docs/_examples/cb-ts-to-js/js/src/app/hero-di.component.js b/public/docs/_examples/cb-ts-to-js/js/src/app/hero-di.component.js
new file mode 100644
index 0000000000..2f49a85079
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js/src/app/hero-di.component.js
@@ -0,0 +1,51 @@
+(function(app) {
+
+ var old = app.HeroComponent;
+
+ // #docregion
+ app.HeroComponent = HeroComponent;
+
+ HeroComponent.annotations = [
+ new ng.core.Component({
+ selector: 'hero-di',
+ template: 'Hero: {{name}} '
+ })
+ ];
+
+ HeroComponent.parameters = [ app.DataService ];
+
+ function HeroComponent(dataService) {
+ this.name = dataService.getHeroName();
+ }
+ // #enddocregion
+
+ app.HeroDIComponent = app.HeroComponent;
+ app.HeroComponent = old;
+
+})(window.app = window.app || {});
+
+////// DSL Version /////
+
+(function(app) {
+
+ var old = app.HeroComponent;
+
+ // #docregion dsl
+ app.HeroComponent = ng.core.Component({
+ selector: 'hero-di-dsl',
+ template: 'Hero: {{name}} '
+ })
+ .Class({
+ constructor: [
+ app.DataService,
+ function HeroComponent(service) {
+ this.name = service.getHeroName();
+ }
+ ]
+ });
+ // #enddocregion dsl
+
+ app.HeroDIDslComponent = app.HeroComponent;
+ app.HeroComponent = old;
+
+})(window.app = window.app || {});
diff --git a/public/docs/_examples/cb-ts-to-js/js/src/app/hero-host.component.js b/public/docs/_examples/cb-ts-to-js/js/src/app/hero-host.component.js
new file mode 100644
index 0000000000..b73e50aae0
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js/src/app/hero-host.component.js
@@ -0,0 +1,107 @@
+(function(app) {
+
+ var old = app.HeroComponent
+
+ // #docregion
+ app.HeroComponent = HeroComponent;
+
+ HeroComponent.annotations = [
+ new ng.core.Component({
+ selector: 'hero-host',
+ template:
+ 'Hero Host ' +
+ 'Heading clicks: {{clicks}}
',
+ host: {
+ // HostBindings to the element
+ '[title]': 'title',
+ '[class.heading]': 'headingClass',
+ '(click)': 'clicked()',
+
+ // HostListeners on the entire element
+ '(mouseenter)': 'enter($event)',
+ '(mouseleave)': 'leave($event)'
+ },
+ // Styles within (but excluding) the element
+ styles: ['.active {background-color: yellow;}']
+ })
+ ];
+
+ function HeroComponent() {
+ this.clicks = 0;
+ this.headingClass = true;
+ this.title = 'Hero Host Tooltip content';
+ }
+
+ HeroComponent.prototype.clicked = function() {
+ this.clicks += 1;
+ }
+
+ HeroComponent.prototype.enter = function(event) {
+ this.active = true;
+ this.headingClass = false;
+ }
+
+ HeroComponent.prototype.leave = function(event) {
+ this.active = false;
+ this.headingClass = true;
+ }
+ // #enddocregion
+
+ app.HeroHostComponent = app.HeroComponent;
+ app.HeroComponent = old;
+
+})(window.app = window.app || {});
+
+//// DSL Version ////
+
+(function(app) {
+
+ var old = app.HeroComponent;
+
+ // #docregion dsl
+ app.HeroComponent = ng.core.Component({
+ selector: 'hero-host-dsl',
+ template: `
+ Hero Host (DSL)
+ Heading clicks: {{clicks}}
+ `,
+ host: {
+ // HostBindings to the element
+ '[title]': 'title',
+ '[class.heading]': 'headingClass',
+ '(click)': 'clicked()',
+
+ // HostListeners on the entire element
+ '(mouseenter)': 'enter($event)',
+ '(mouseleave)': 'leave($event)'
+ },
+ // Styles within (but excluding) the element
+ styles: ['.active {background-color: coral;}']
+ })
+ .Class({
+ constructor: function HeroComponent() {
+ this.clicks = 0;
+ this.headingClass = true;
+ this.title = 'Hero Host Tooltip DSL content';
+ },
+
+ clicked() {
+ this.clicks += 1;
+ },
+
+ enter(event) {
+ this.active = true;
+ this.headingClass = false;
+ },
+
+ leave(event) {
+ this.active = false;
+ this.headingClass = true;
+ }
+ });
+ // #enddocregion dsl
+
+ app.HeroHostDslComponent = app.HeroComponent;
+ app.HeroComponent = old;
+
+})(window.app = window.app || {});
diff --git a/public/docs/_examples/cb-ts-to-js/js/src/app/hero-io-dsl.component.html b/public/docs/_examples/cb-ts-to-js/js/src/app/hero-io-dsl.component.html
new file mode 100644
index 0000000000..c8023ccb45
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js/src/app/hero-io-dsl.component.html
@@ -0,0 +1,7 @@
+
+
+OK clicked
+Cancel clicked
diff --git a/public/docs/_examples/cb-ts-to-js/js/src/app/hero-io.component.html b/public/docs/_examples/cb-ts-to-js/js/src/app/hero-io.component.html
new file mode 100644
index 0000000000..215ddccf92
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js/src/app/hero-io.component.html
@@ -0,0 +1,7 @@
+
+
+OK clicked
+Cancel clicked
diff --git a/public/docs/_examples/cb-ts-to-js/js/src/app/hero-io.component.js b/public/docs/_examples/cb-ts-to-js/js/src/app/hero-io.component.js
new file mode 100644
index 0000000000..b09208ce68
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js/src/app/hero-io.component.js
@@ -0,0 +1,52 @@
+(function(app) {
+
+ var old = app.HeroComponent
+
+ app.HeroComponent = HeroComponent;
+
+ HeroComponent.annotations = [
+ new ng.core.Component({
+ selector: 'hero-io',
+ templateUrl: 'app/hero-io.component.html'
+ })
+ ];
+
+ function HeroComponent() { }
+
+ HeroComponent.prototype.onOk = function() {
+ this.okClicked = true;
+ }
+
+ HeroComponent.prototype.onCancel = function() {
+ this.cancelClicked = true;
+ }
+
+ app.HeroIOComponent = app.HeroComponent;
+ app.HeroComponent = old;
+
+})(window.app = window.app || {});
+
+///// DSL Version ////
+
+(function(app) {
+
+ var old = app.HeroComponent
+
+ app.HeroComponent = ng.core.Component({
+ selector: 'hero-io-dsl',
+ templateUrl: 'app/hero-io-dsl.component.html'
+ })
+ .Class({
+ constructor: function HeroComponent() { },
+ onOk: function() {
+ this.okClicked = true;
+ },
+ onCancel: function() {
+ this.cancelClicked = true;
+ }
+ });
+
+ app.HeroIODslComponent = app.HeroComponent;
+ app.HeroComponent = old;
+
+})(window.app = window.app || {});
diff --git a/public/docs/_examples/cb-ts-to-js/js/src/app/hero-lifecycle.component.js b/public/docs/_examples/cb-ts-to-js/js/src/app/hero-lifecycle.component.js
new file mode 100644
index 0000000000..2a68288f92
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js/src/app/hero-lifecycle.component.js
@@ -0,0 +1,52 @@
+// #docplaster
+(function(app) {
+
+ var old = app.HeroComponent;
+
+ // #docregion
+ app.HeroComponent = HeroComponent;
+
+ HeroComponent.annotations = [
+ new ng.core.Component({
+ selector: 'hero-lifecycle',
+ template: 'Hero: {{name}} '
+ })
+ ];
+
+ function HeroComponent() { }
+
+ HeroComponent.prototype.ngOnInit = function() {
+ // todo: fetch from server async
+ setTimeout(() => this.name = 'Windstorm', 0);
+ };
+ // #enddocregion
+
+ app.HeroLifecycleComponent = app.HeroComponent;
+ app.HeroComponent = old;
+
+})(window.app = window.app || {});
+
+/////// DSL version ////
+
+(function(app) {
+
+ var old = app.HeroComponent;
+
+ // #docregion dsl
+ app.HeroComponent = ng.core.Component({
+ selector: 'hero-lifecycle-dsl',
+ template: 'Hero: {{name}} '
+ })
+ .Class({
+ constructor: function HeroComponent() { },
+ ngOnInit: function() {
+ // todo: fetch from server async
+ setTimeout(() => this.name = 'Windstorm', 0);
+ }
+ });
+ // #enddocregion dsl
+
+ app.HeroLifecycleDslComponent = app.HeroComponent;
+ app.HeroComponent = old;
+
+})(window.app = window.app || {});
diff --git a/public/docs/_examples/cb-ts-to-js/js/src/app/hero-queries.component.js b/public/docs/_examples/cb-ts-to-js/js/src/app/hero-queries.component.js
new file mode 100644
index 0000000000..5e8de58d41
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js/src/app/hero-queries.component.js
@@ -0,0 +1,92 @@
+(function(app) {
+
+ app.heroQueries = app.heroQueries || {};
+
+ app.heroQueries.ContentChildComponent = ng.core.Component({
+ selector: 'content-child',
+ template:
+ '' +
+ 'Active' +
+ ' '
+ }).Class({
+ constructor: function ContentChildComponent() {
+ this.active = false;
+ },
+
+ activate: function() {
+ this.active = !this.active;
+ }
+ });
+
+ ////////////////////
+
+ // #docregion content
+ app.heroQueries.ViewChildComponent = ng.core.Component({
+ selector: 'view-child',
+ template:
+ '' +
+ '{{hero.name}} ' +
+ ' ' +
+ ' ',
+ styles: ['.active {font-weight: bold; background-color: skyblue;}'],
+ inputs: ['hero'],
+ queries: {
+ content: new ng.core.ContentChild(app.heroQueries.ContentChildComponent)
+ }
+ })
+ .Class({
+ constructor: function HeroQueriesHeroComponent() {
+ this.active = false;
+ },
+
+ activate: function() {
+ this.active = !this.active;
+ this.content.activate();
+ }
+ });
+ // #enddocregion content
+
+ ////////////////////
+
+ // #docregion view
+ app.heroQueries.HeroQueriesComponent = ng.core.Component({
+ selector: 'hero-queries',
+ template:
+ '' +
+ ' ' +
+ ' ' +
+ '{{buttonLabel}} All ',
+ queries: {
+ views: new ng.core.ViewChildren(app.heroQueries.ViewChildComponent)
+ }
+ })
+ .Class({
+ constructor: function HeroQueriesComponent() {
+ this.active = false;
+ this.heroData = [
+ {id: 1, name: 'Windstorm'},
+ {id: 2, name: 'LaughingGas'}
+ ];
+ },
+
+ activate: function() {
+ this.active = !this.active;
+ this.views.forEach(function(view) {
+ view.activate();
+ });
+ },
+ });
+
+ // #docregion defined-property
+ // add prototype property w/ getter outside the DSL
+ var proto = app.heroQueries.HeroQueriesComponent.prototype;
+ Object.defineProperty(proto, "buttonLabel", {
+ get: function () {
+ return this.active ? 'Deactivate' : 'Activate';
+ },
+ enumerable: true
+ });
+ // #enddocregion defined-property
+ // #enddocregion view
+
+})(window.app = window.app || {});
diff --git a/public/docs/_examples/cb-ts-to-js/js/src/app/hero-title.component.html b/public/docs/_examples/cb-ts-to-js/js/src/app/hero-title.component.html
new file mode 100644
index 0000000000..164683cb7c
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js/src/app/hero-title.component.html
@@ -0,0 +1,4 @@
+
+{{titlePrefix}} {{title}}
+OK
+{{ msg }}
diff --git a/public/docs/_examples/cb-ts-to-js/js/src/app/hero-title.component.js b/public/docs/_examples/cb-ts-to-js/js/src/app/hero-title.component.js
new file mode 100644
index 0000000000..f0770e1228
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js/src/app/hero-title.component.js
@@ -0,0 +1,64 @@
+(function(app) {
+
+ // #docregion
+ app.HeroTitleComponent = HeroTitleComponent;
+
+ // #docregion templateUrl
+ HeroTitleComponent.annotations = [
+ new ng.core.Component({
+ selector: 'hero-title',
+ templateUrl: 'app/hero-title.component.html'
+ })
+ ];
+ // #enddocregion templateUrl
+
+ function HeroTitleComponent(titlePrefix, title) {
+ this.titlePrefix = titlePrefix;
+ this.title = title;
+ this.msg = '';
+ }
+
+ HeroTitleComponent.prototype.ok = function() {
+ this.msg = 'OK!';
+ }
+
+ HeroTitleComponent.parameters = [
+ [new ng.core.Optional(), new ng.core.Inject('titlePrefix')],
+ [new ng.core.Attribute('title')]
+ ];
+ // #enddocregion
+
+})(window.app = window.app || {});
+
+////////// DSL version ////////////
+
+(function(app) {
+
+ var old = app.HeroTitleComponent;
+
+ // #docregion dsl
+ app.HeroTitleComponent = ng.core.Component({
+ selector: 'hero-title-dsl',
+ templateUrl: 'app/hero-title.component.html'
+ })
+ .Class({
+ constructor: [
+ [ new ng.core.Optional(), new ng.core.Inject('titlePrefix') ],
+ new ng.core.Attribute('title'),
+ function HeroTitleComponent(titlePrefix, title) {
+ this.titlePrefix = titlePrefix;
+ this.title = title;
+ this.msg = '';
+ }
+ ],
+
+ ok: function() {
+ this.msg = 'OK!';
+ }
+ });
+ // #enddocregion dsl
+
+ app.HeroTitleDslComponent = app.HeroTitleComponent;
+ app.HeroTitleComponent = old;
+
+})(window.app = window.app || {});
diff --git a/public/docs/_examples/cb-ts-to-js/js/src/app/hero.component.js b/public/docs/_examples/cb-ts-to-js/js/src/app/hero.component.js
new file mode 100644
index 0000000000..e1407b2635
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js/src/app/hero.component.js
@@ -0,0 +1,53 @@
+// #docplaster
+(function(app) {
+
+// #docregion
+// #docregion appexport
+// #docregion metadata
+app.HeroComponent = HeroComponent; // "export"
+
+HeroComponent.annotations = [
+ new ng.core.Component({
+ selector: 'hero-view',
+ template: '{{title}}: {{getName()}} '
+ })
+];
+
+// #docregion constructorproto
+function HeroComponent() {
+ this.title = "Hero Detail";
+}
+
+HeroComponent.prototype.getName = function() { return 'Windstorm'; };
+// #enddocregion constructorproto
+
+// #enddocregion metadata
+// #enddocregion appexport
+// #enddocregion
+
+})(window.app = window.app || {});
+
+//////////// DSL version ///////////
+
+(function(app) {
+
+ var old = app.HeroComponent;
+
+ // #docregion dsl
+ app.HeroComponent = ng.core.Component({
+ selector: 'hero-view-dsl',
+ template: '{{title}}: {{getName()}} ',
+ })
+ .Class({
+ constructor: function HeroComponent() {
+ this.title = "Hero Detail";
+ },
+
+ getName: function() { return 'Windstorm'; }
+ });
+ // #enddocregion dsl
+
+ app.HeroDslComponent = app.HeroComponent;
+ app.HeroComponent = old;
+
+})(window.app = window.app || {});
diff --git a/public/docs/_examples/cb-ts-to-js/js/src/index.html b/public/docs/_examples/cb-ts-to-js/js/src/index.html
new file mode 100644
index 0000000000..00338aa55a
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js/src/index.html
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+ TypeScript to JavaScript
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
diff --git a/public/docs/_examples/cb-ts-to-js/js/src/main.js b/public/docs/_examples/cb-ts-to-js/js/src/main.js
new file mode 100644
index 0000000000..fd3e737c9e
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/js/src/main.js
@@ -0,0 +1,9 @@
+(function(app) {
+
+var platformBrowserDynamic = ng.platformBrowserDynamic.platformBrowserDynamic;
+
+document.addEventListener('DOMContentLoaded', function() {
+ platformBrowserDynamic().bootstrapModule(app.AppModule);
+});
+
+})(window.app = window.app || {});
diff --git a/public/docs/_examples/upgrade/ts/ng2_final/app/img/.gitkeep b/public/docs/_examples/cb-ts-to-js/ts/example-config.json
similarity index 100%
rename from public/docs/_examples/upgrade/ts/ng2_final/app/img/.gitkeep
rename to public/docs/_examples/cb-ts-to-js/ts/example-config.json
diff --git a/public/docs/_examples/cb-ts-to-js/ts/plnkr.json b/public/docs/_examples/cb-ts-to-js/ts/plnkr.json
new file mode 100644
index 0000000000..447fc5f605
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/ts/plnkr.json
@@ -0,0 +1,9 @@
+{
+ "description": "TypeScript to JavaScript",
+ "basePath": "src/",
+ "files":[
+ "!**/*.d.ts",
+ "!**/*.js"
+ ],
+ "tags":["cookbook"]
+}
diff --git a/public/docs/_examples/cb-ts-to-js/ts/src/app/app.component.html b/public/docs/_examples/cb-ts-to-js/ts/src/app/app.component.html
new file mode 100644
index 0000000000..995645073a
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/ts/src/app/app.component.html
@@ -0,0 +1,31 @@
+
+{{title}}
+Classes and Class Metadata
+Input and Output Decorators
+Dependency Injection
+Host Metadata
+View and Child Metadata
+
+
+
+
+
+
+
+
+
+
+
+Dependency Injection
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/public/docs/_examples/cb-ts-to-js/ts/src/app/app.component.ts b/public/docs/_examples/cb-ts-to-js/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..912c9e1a80
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/ts/src/app/app.component.ts
@@ -0,0 +1,14 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ templateUrl: './app.component.html',
+ styles: [
+ // See hero-di-inject-additional.component
+ 'hero-host, hero-host-meta { border: 1px dashed black; display: block; padding: 4px;}',
+ '.heading {font-style: italic}'
+ ]
+})
+export class AppComponent {
+ title = 'TypeScript';
+}
diff --git a/public/docs/_examples/cb-ts-to-js/ts/src/app/app.module.ts b/public/docs/_examples/cb-ts-to-js/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..992c3c3514
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/ts/src/app/app.module.ts
@@ -0,0 +1,56 @@
+/* tslint:disable-next-line:no-unused-variable */
+import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+import { AppComponent } from './app.component';
+import { ConfirmComponent } from './confirm.component';
+// #docregion appimport
+import { HeroComponent } from './hero.component';
+// #enddocregion appimport
+import { HeroComponent as HeroDIComponent } from './hero-di.component';
+import { HeroComponent as HeroDIInjectComponent } from './hero-di-inject.component';
+import { HeroComponent as HeroDIInjectAdditionalComponent } from './hero-di-inject-additional.component';
+import { HeroHostComponent } from './hero-host.component';
+import { HeroHostMetaComponent } from './hero-host-meta.component';
+import { HeroIOComponent } from './hero-io.component';
+import { HeroComponent as HeroLifecycleComponent } from './hero-lifecycle.component';
+import { HeroQueriesComponent, ViewChildComponent, ContentChildComponent } from './hero-queries.component';
+import { HeroTitleComponent } from './hero-title.component';
+
+import { DataService } from './data.service';
+
+@NgModule({
+ imports: [
+ BrowserModule
+ ],
+ declarations: [
+ AppComponent,
+ ConfirmComponent,
+ HeroComponent,
+ HeroDIComponent,
+ HeroDIInjectComponent,
+ HeroDIInjectAdditionalComponent,
+ HeroHostComponent, HeroHostMetaComponent,
+ HeroIOComponent,
+ HeroLifecycleComponent,
+ HeroQueriesComponent, ViewChildComponent, ContentChildComponent,
+ HeroTitleComponent
+ ],
+ providers: [
+ DataService,
+ { provide: 'heroName', useValue: 'Windstorm' }
+ ],
+ bootstrap: [ AppComponent ],
+
+ // schemas: [ NO_ERRORS_SCHEMA ] // helpful for debugging!
+})
+export class AppModule { }
+
+/* tslint:disable no-unused-variable */
+// #docregion ng2import
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import {
+ LocationStrategy,
+ HashLocationStrategy
+} from '@angular/common';
+// #enddocregion ng2import
diff --git a/public/docs/_examples/cb-ts-to-js/ts/src/app/confirm.component.html b/public/docs/_examples/cb-ts-to-js/ts/src/app/confirm.component.html
new file mode 100644
index 0000000000..45275d218a
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/ts/src/app/confirm.component.html
@@ -0,0 +1,6 @@
+
+ {{okMsg}}
+
+
+ {{notOkMsg}}
+
diff --git a/public/docs/_examples/cb-ts-to-js/ts/src/app/confirm.component.ts b/public/docs/_examples/cb-ts-to-js/ts/src/app/confirm.component.ts
new file mode 100644
index 0000000000..f01fa4de40
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/ts/src/app/confirm.component.ts
@@ -0,0 +1,21 @@
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+
+// #docregion
+@Component({
+ selector: 'app-confirm',
+ templateUrl: './confirm.component.html'
+})
+export class ConfirmComponent {
+ @Input() okMsg = '';
+ @Input('cancelMsg') notOkMsg = '';
+ @Output() ok = new EventEmitter();
+ @Output('cancel') notOk = new EventEmitter();
+
+ onOkClick() {
+ this.ok.emit(true);
+ }
+ onNotOkClick() {
+ this.notOk.emit(true);
+ }
+}
+// #enddocregion
diff --git a/public/docs/_examples/cb-ts-to-js/ts/src/app/data.service.ts b/public/docs/_examples/cb-ts-to-js/ts/src/app/data.service.ts
new file mode 100644
index 0000000000..cd7f9e1aae
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/ts/src/app/data.service.ts
@@ -0,0 +1,10 @@
+import { Injectable } from '@angular/core';
+
+@Injectable()
+export class DataService {
+ constructor() { }
+
+ getHeroName() {
+ return 'Windstorm';
+ }
+}
diff --git a/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-di-inject-additional.component.ts b/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-di-inject-additional.component.ts
new file mode 100644
index 0000000000..ec460a9dbc
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-di-inject-additional.component.ts
@@ -0,0 +1,7 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'hero-di-inject-additional',
+ template: ` `
+})
+export class HeroComponent { }
diff --git a/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-di-inject.component.ts b/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-di-inject.component.ts
new file mode 100644
index 0000000000..c583a1b0f6
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-di-inject.component.ts
@@ -0,0 +1,11 @@
+import { Component, Inject } from '@angular/core';
+
+// #docregion
+@Component({
+ selector: 'hero-di-inject',
+ template: `Hero: {{name}} `
+})
+export class HeroComponent {
+ constructor(@Inject('heroName') private name: string) { }
+}
+// #enddocregion
diff --git a/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-di.component.ts b/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-di.component.ts
new file mode 100644
index 0000000000..3a17abd281
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-di.component.ts
@@ -0,0 +1,15 @@
+// #docregion
+import { Component } from '@angular/core';
+import { DataService } from './data.service';
+
+@Component({
+ selector: 'hero-di',
+ template: `Hero: {{name}} `
+})
+export class HeroComponent {
+ name = '';
+ constructor(dataService: DataService) {
+ this.name = dataService.getHeroName();
+ }
+}
+// #enddocregion
diff --git a/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-host-meta.component.ts b/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-host-meta.component.ts
new file mode 100644
index 0000000000..fefe4a5470
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-host-meta.component.ts
@@ -0,0 +1,44 @@
+import { Component } from '@angular/core';
+
+// #docregion
+@Component({
+ selector: 'hero-host-meta',
+ template: `
+ Hero Host in Metadata
+ Heading clicks: {{clicks}}
+ `,
+ host: {
+ // HostBindings to the element
+ '[title]': 'title',
+ '[class.heading]': 'headingClass',
+
+ // HostListeners on the entire element
+ '(click)': 'clicked()',
+ '(mouseenter)': 'enter($event)',
+ '(mouseleave)': 'leave($event)'
+ },
+ // Styles within (but excluding) the element
+ styles: ['.active {background-color: coral;}']
+})
+export class HeroHostMetaComponent {
+ title = 'Hero Host in Metadata Tooltip';
+ headingClass = true;
+
+ active = false;
+ clicks = 0;
+
+ clicked() {
+ this.clicks += 1;
+ }
+
+ enter(event: Event) {
+ this.active = true;
+ this.headingClass = false;
+ }
+
+ leave(event: Event) {
+ this.active = false;
+ this.headingClass = true;
+ }
+}
+// #enddocregion
diff --git a/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-host.component.ts b/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-host.component.ts
new file mode 100644
index 0000000000..e8d72233c8
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-host.component.ts
@@ -0,0 +1,39 @@
+import { Component, HostBinding, HostListener } from '@angular/core';
+
+// #docregion
+@Component({
+ selector: 'hero-host',
+ template: `
+ Hero Host in Decorators
+ Heading clicks: {{clicks}}
+ `,
+ // Styles within (but excluding) the element
+ styles: ['.active {background-color: yellow;}']
+})
+export class HeroHostComponent {
+ // HostBindings to the element
+ @HostBinding() title = 'Hero Host in Decorators Tooltip';
+ @HostBinding('class.heading') headingClass = true;
+
+ active = false;
+ clicks = 0;
+
+ // HostListeners on the entire element
+ @HostListener('click')
+ clicked() {
+ this.clicks += 1;
+ }
+
+ @HostListener('mouseenter', ['$event'])
+ enter(event: Event) {
+ this.active = true;
+ this.headingClass = false;
+ }
+
+ @HostListener('mouseleave', ['$event'])
+ leave(event: Event) {
+ this.active = false;
+ this.headingClass = true;
+ }
+}
+// #enddocregion
diff --git a/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-io.component.ts b/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-io.component.ts
new file mode 100644
index 0000000000..4b36411e78
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-io.component.ts
@@ -0,0 +1,26 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'hero-io',
+ template: `
+
+
+ OK clicked
+ Cancel clicked
+ `
+})
+export class HeroIOComponent {
+ okClicked = false;
+ cancelClicked = false;
+
+ onOk() {
+ this.okClicked = true;
+ }
+
+ onCancel() {
+ this.cancelClicked = true;
+ }
+}
diff --git a/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-lifecycle.component.ts b/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-lifecycle.component.ts
new file mode 100644
index 0000000000..2629c85a1a
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-lifecycle.component.ts
@@ -0,0 +1,14 @@
+// #docregion
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'hero-lifecycle',
+ template: `Hero: {{name}} `
+})
+export class HeroComponent implements OnInit {
+ name: string;
+ ngOnInit() {
+ // todo: fetch from server async
+ setTimeout(() => this.name = 'Windstorm', 0);
+ }
+}
diff --git a/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-queries.component.ts b/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-queries.component.ts
new file mode 100644
index 0000000000..8b2d91ea85
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-queries.component.ts
@@ -0,0 +1,83 @@
+import {
+ Component,
+ ContentChild,
+ Input,
+ QueryList,
+ ViewChildren
+} from '@angular/core';
+
+@Component({
+ selector: 'content-child',
+ template: `
+
+ Active
+ `
+})
+export class ContentChildComponent {
+ active = false;
+
+ activate() {
+ this.active = !this.active;
+ }
+}
+
+////////////////////
+
+// #docregion content
+@Component({
+ selector: 'view-child',
+ template: `
+
+ {{hero.name}}
+
+ `,
+ styles: ['.active {font-weight: bold; background-color: skyblue;}']
+})
+export class ViewChildComponent {
+ @Input() hero: any;
+ active = false;
+
+ @ContentChild(ContentChildComponent) content: ContentChildComponent;
+
+ activate() {
+ this.active = !this.active;
+ this.content.activate();
+ }
+}
+// #enddocregion content
+
+////////////////////
+
+// #docregion view
+@Component({
+ selector: 'hero-queries',
+ template: `
+
+
+
+ {{buttonLabel}} All
+ `
+})
+export class HeroQueriesComponent {
+ active = false;
+ heroData = [
+ {id: 1, name: 'Windstorm'},
+ {id: 2, name: 'LaughingGas'}
+ ];
+
+ @ViewChildren(ViewChildComponent) views: QueryList;
+
+ activate() {
+ this.active = !this.active;
+ this.views.forEach(
+ view => view.activate()
+ );
+ }
+
+ // #docregion defined-property
+ get buttonLabel() {
+ return this.active ? 'Deactivate' : 'Activate';
+ }
+ // #enddocregion defined-property
+}
+// #enddocregion view
diff --git a/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-title.component.html b/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-title.component.html
new file mode 100644
index 0000000000..164683cb7c
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-title.component.html
@@ -0,0 +1,4 @@
+
+{{titlePrefix}} {{title}}
+OK
+{{ msg }}
diff --git a/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-title.component.ts b/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-title.component.ts
new file mode 100644
index 0000000000..48aaae7d44
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/ts/src/app/hero-title.component.ts
@@ -0,0 +1,21 @@
+import { Attribute, Component, Inject, Optional } from '@angular/core';
+
+// #docregion
+// #docregion templateUrl
+@Component({
+ selector: 'hero-title',
+ templateUrl: './hero-title.component.html'
+})
+// #enddocregion templateUrl
+export class HeroTitleComponent {
+ msg: string = '';
+ constructor(
+ @Inject('titlePrefix') @Optional() private titlePrefix: string,
+ @Attribute('title') private title: string
+ ) { }
+
+ ok() {
+ this.msg = 'OK!';
+ }
+}
+// #enddocregion
diff --git a/public/docs/_examples/cb-ts-to-js/ts/src/app/hero.component.ts b/public/docs/_examples/cb-ts-to-js/ts/src/app/hero.component.ts
new file mode 100644
index 0000000000..2976ec605e
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/ts/src/app/hero.component.ts
@@ -0,0 +1,15 @@
+// #docregion
+// #docregion metadata
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'hero-view',
+ template: '{{title}}: {{getName()}} '
+})
+// #docregion appexport, class
+export class HeroComponent {
+ title = 'Hero Detail';
+ getName() {return 'Windstorm'; }
+}
+// #enddocregion appexport, class
+// #enddocregion metadata
diff --git a/public/docs/_examples/cb-ts-to-js/ts/src/index.html b/public/docs/_examples/cb-ts-to-js/ts/src/index.html
new file mode 100644
index 0000000000..d9ad1f7aef
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/ts/src/index.html
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+ TypeScript to JavaScript
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
diff --git a/public/docs/_examples/cb-ts-to-js/ts/src/main.ts b/public/docs/_examples/cb-ts-to-js/ts/src/main.ts
new file mode 100644
index 0000000000..f22933ba8e
--- /dev/null
+++ b/public/docs/_examples/cb-ts-to-js/ts/src/main.ts
@@ -0,0 +1,4 @@
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/cb-visual-studio-2015/ts/.gitignore b/public/docs/_examples/cb-visual-studio-2015/ts/.gitignore
new file mode 100644
index 0000000000..ca3f2dbd5e
--- /dev/null
+++ b/public/docs/_examples/cb-visual-studio-2015/ts/.gitignore
@@ -0,0 +1 @@
+!tsconfig.json
diff --git a/public/docs/_examples/cb-visual-studio-2015/ts/tsconfig.json b/public/docs/_examples/cb-visual-studio-2015/ts/tsconfig.json
new file mode 100644
index 0000000000..2624488890
--- /dev/null
+++ b/public/docs/_examples/cb-visual-studio-2015/ts/tsconfig.json
@@ -0,0 +1,17 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "module": "commonjs",
+ "moduleResolution": "node",
+ "sourceMap": true,
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "removeComments": false,
+ "noImplicitAny": true,
+ "suppressImplicitAnyIndexErrors": true,
+ "typeRoots": [
+ "node_modules/@types"
+ ]
+ },
+ "compileOnSave": true
+}
diff --git a/public/docs/_examples/cli-quickstart/e2e-spec.ts b/public/docs/_examples/cli-quickstart/e2e-spec.ts
new file mode 100644
index 0000000000..59816e13c2
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/e2e-spec.ts
@@ -0,0 +1,14 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by } from 'protractor';
+
+describe('cli-quickstart App', () => {
+ beforeEach(() => {
+ return browser.get('/');
+ });
+
+ it('should display message saying app works', () => {
+ let pageTitle = element(by.css('app-root h1')).getText();
+ expect(pageTitle).toEqual('My First Angular App');
+ });
+});
diff --git a/public/docs/_examples/cli-quickstart/ts/.angular-cli.json b/public/docs/_examples/cli-quickstart/ts/.angular-cli.json
new file mode 100644
index 0000000000..49a6b93bd0
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/.angular-cli.json
@@ -0,0 +1,57 @@
+{
+ "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
+ "project": {
+ "name": "master-project"
+ },
+ "apps": [
+ {
+ "root": "src",
+ "outDir": "dist",
+ "assets": [
+ "assets",
+ "favicon.ico"
+ ],
+ "index": "index.html",
+ "main": "main.ts",
+ "polyfills": "polyfills.ts",
+ "test": "test.ts",
+ "tsconfig": "tsconfig.app.json",
+ "testTsconfig": "tsconfig.spec.json",
+ "prefix": "app",
+ "styles": [
+ "styles.css"
+ ],
+ "scripts": [],
+ "environmentSource": "environments/environment.ts",
+ "environments": {
+ "dev": "environments/environment.ts",
+ "prod": "environments/environment.prod.ts"
+ }
+ }
+ ],
+ "e2e": {
+ "protractor": {
+ "config": "./protractor.conf.js"
+ }
+ },
+ "lint": [
+ {
+ "project": "src/tsconfig.app.json"
+ },
+ {
+ "project": "src/tsconfig.spec.json"
+ },
+ {
+ "project": "e2e/tsconfig.e2e.json"
+ }
+ ],
+ "test": {
+ "karma": {
+ "config": "./karma.conf.js"
+ }
+ },
+ "defaults": {
+ "styleExt": "css",
+ "component": {}
+ }
+}
diff --git a/public/docs/_examples/cli-quickstart/ts/.editorconfig b/public/docs/_examples/cli-quickstart/ts/.editorconfig
new file mode 100644
index 0000000000..6e87a003da
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/.editorconfig
@@ -0,0 +1,13 @@
+# Editor configuration, see http://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.md]
+max_line_length = off
+trim_trailing_whitespace = false
diff --git a/public/docs/_examples/cli-quickstart/ts/.gitignore b/public/docs/_examples/cli-quickstart/ts/.gitignore
new file mode 100644
index 0000000000..04a48dc643
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/.gitignore
@@ -0,0 +1,45 @@
+# See http://help.github.com/ignore-files/ for more about ignoring files.
+
+# compiled output
+/dist
+/tmp
+
+# dependencies
+/node_modules
+
+# IDEs and editors
+/.idea
+.project
+.classpath
+.c9/
+*.launch
+.settings/
+*.sublime-workspace
+
+# IDE - VSCode
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+
+# misc
+/.sass-cache
+/connect.lock
+/coverage/*
+/libpeerconnection.log
+npm-debug.log
+testem.log
+/typings
+
+# e2e
+/e2e/*.js
+/e2e/*.map
+
+#System Files
+.DS_Store
+Thumbs.db
+
+!src/styles.css
+!karma.conf.js
+!protractor.conf.js
diff --git a/public/docs/_examples/cli-quickstart/ts/README.md b/public/docs/_examples/cli-quickstart/ts/README.md
new file mode 100644
index 0000000000..efe9ec67ae
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/README.md
@@ -0,0 +1,27 @@
+# MasterProject
+
+This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.0.0-rc.0.
+
+## Development server
+Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
+
+## Code scaffolding
+
+Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive/pipe/service/class/module`.
+
+## Build
+
+Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build.
+
+## Running unit tests
+
+Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
+
+## Running end-to-end tests
+
+Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
+Before running the tests make sure you are serving the app via `ng serve`.
+
+## Further help
+
+To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
diff --git a/public/docs/_examples/cli-quickstart/ts/bs-config.cli.json b/public/docs/_examples/cli-quickstart/ts/bs-config.cli.json
new file mode 100644
index 0000000000..ac61d35f83
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/bs-config.cli.json
@@ -0,0 +1,11 @@
+{
+ "open": false,
+ "logLevel": "silent",
+ "port": 8080,
+ "server": {
+ "baseDir": "dist",
+ "middleware": {
+ "0": null
+ }
+ }
+}
diff --git a/public/docs/_examples/cli-quickstart/ts/e2e/app.e2e-spec.ts b/public/docs/_examples/cli-quickstart/ts/e2e/app.e2e-spec.ts
new file mode 100644
index 0000000000..4346d120c8
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/e2e/app.e2e-spec.ts
@@ -0,0 +1,14 @@
+import { MyAppPage } from './app.po';
+
+describe('my-app App', function() {
+ let page: MyAppPage;
+
+ beforeEach(() => {
+ page = new MyAppPage();
+ });
+
+ it('should display message saying app works', () => {
+ page.navigateTo();
+ expect(page.getParagraphText()).toEqual('app works!');
+ });
+});
diff --git a/public/docs/_examples/cli-quickstart/ts/e2e/app.po.ts b/public/docs/_examples/cli-quickstart/ts/e2e/app.po.ts
new file mode 100644
index 0000000000..5d82157326
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/e2e/app.po.ts
@@ -0,0 +1,11 @@
+import { browser, element, by } from 'protractor';
+
+export class MyAppPage {
+ navigateTo() {
+ return browser.get('/');
+ }
+
+ getParagraphText() {
+ return element(by.css('app-root h1')).getText();
+ }
+}
diff --git a/public/docs/_examples/cli-quickstart/ts/e2e/tsconfig.e2e.json b/public/docs/_examples/cli-quickstart/ts/e2e/tsconfig.e2e.json
new file mode 100644
index 0000000000..74c2bca131
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/e2e/tsconfig.e2e.json
@@ -0,0 +1,19 @@
+{
+ "compilerOptions": {
+ "sourceMap": true,
+ "declaration": false,
+ "moduleResolution": "node",
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "lib": [
+ "es2016"
+ ],
+ "outDir": "../dist/out-tsc-e2e",
+ "module": "commonjs",
+ "target": "es6",
+ "types":[
+ "jasmine",
+ "node"
+ ]
+ }
+}
diff --git a/public/docs/_examples/cli-quickstart/ts/example-config.json b/public/docs/_examples/cli-quickstart/ts/example-config.json
new file mode 100644
index 0000000000..313764c3c6
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/example-config.json
@@ -0,0 +1,4 @@
+{
+ "build": "build:cli",
+ "run": "serve:cli"
+}
diff --git a/public/docs/_examples/cli-quickstart/ts/karma.conf.js b/public/docs/_examples/cli-quickstart/ts/karma.conf.js
new file mode 100644
index 0000000000..84b4cd5aca
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/karma.conf.js
@@ -0,0 +1,44 @@
+// Karma configuration file, see link for more information
+// https://karma-runner.github.io/0.13/config/configuration-file.html
+
+module.exports = function (config) {
+ config.set({
+ basePath: '',
+ frameworks: ['jasmine', '@angular/cli'],
+ plugins: [
+ require('karma-jasmine'),
+ require('karma-chrome-launcher'),
+ require('karma-jasmine-html-reporter'),
+ require('karma-coverage-istanbul-reporter'),
+ require('@angular/cli/plugins/karma')
+ ],
+ client:{
+ clearContext: false // leave Jasmine Spec Runner output visible in browser
+ },
+ files: [
+ { pattern: './src/test.ts', watched: false }
+ ],
+ preprocessors: {
+ './src/test.ts': ['@angular/cli']
+ },
+ mime: {
+ 'text/x-typescript': ['ts','tsx']
+ },
+ coverageIstanbulReporter: {
+ reports: [ 'html', 'lcovonly' ],
+ fixWebpackSourcePaths: true
+ },
+ angularCli: {
+ environment: 'dev'
+ },
+ reporters: config.angularCli && config.angularCli.codeCoverage
+ ? ['progress', 'coverage-istanbul']
+ : ['progress', 'kjhtml'],
+ port: 9876,
+ colors: true,
+ logLevel: config.LOG_INFO,
+ autoWatch: true,
+ browsers: ['Chrome'],
+ singleRun: false
+ });
+};
diff --git a/public/docs/_examples/cli-quickstart/ts/protractor.conf.js b/public/docs/_examples/cli-quickstart/ts/protractor.conf.js
new file mode 100644
index 0000000000..2cbc329391
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/protractor.conf.js
@@ -0,0 +1,31 @@
+// Protractor configuration file, see link for more information
+// https://github.com/angular/protractor/blob/master/lib/config.ts
+
+/*global jasmine */
+const { SpecReporter } = require('jasmine-spec-reporter');
+
+exports.config = {
+ allScriptsTimeout: 11000,
+ specs: [
+ './e2e/**/*.e2e-spec.ts'
+ ],
+ capabilities: {
+ 'browserName': 'chrome'
+ },
+ directConnect: true,
+ baseUrl: 'http://localhost:4200/',
+ framework: 'jasmine',
+ jasmineNodeOpts: {
+ showColors: true,
+ defaultTimeoutInterval: 30000,
+ print: function() {}
+ },
+ beforeLaunch: function() {
+ require('ts-node').register({
+ project: 'e2e/tsconfig.e2e.json'
+ });
+ },
+ onPrepare() {
+ jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
+ }
+};
diff --git a/public/docs/_examples/cli-quickstart/ts/src/app/app.component.css b/public/docs/_examples/cli-quickstart/ts/src/app/app.component.css
new file mode 100644
index 0000000000..a2b21fae82
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/src/app/app.component.css
@@ -0,0 +1,6 @@
+/* #docregion */
+h1 {
+ color: #369;
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 250%;
+}
diff --git a/public/docs/_examples/cli-quickstart/ts/src/app/app.component.html b/public/docs/_examples/cli-quickstart/ts/src/app/app.component.html
new file mode 100644
index 0000000000..b6931b538a
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/src/app/app.component.html
@@ -0,0 +1,3 @@
+
+ {{title}}
+
diff --git a/public/docs/_examples/cli-quickstart/ts/src/app/app.component.spec.ts b/public/docs/_examples/cli-quickstart/ts/src/app/app.component.spec.ts
new file mode 100644
index 0000000000..c740bcd745
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/src/app/app.component.spec.ts
@@ -0,0 +1,32 @@
+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 'app works!'`, async(() => {
+ const fixture = TestBed.createComponent(AppComponent);
+ const app = fixture.debugElement.componentInstance;
+ expect(app.title).toEqual('app works!');
+ }));
+
+ it('should render title in a h1 tag', async(() => {
+ const fixture = TestBed.createComponent(AppComponent);
+ fixture.detectChanges();
+ const compiled = fixture.debugElement.nativeElement;
+ expect(compiled.querySelector('h1').textContent).toContain('app works!');
+ }));
+});
diff --git a/public/docs/_examples/cli-quickstart/ts/src/app/app.component.ts b/public/docs/_examples/cli-quickstart/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..4c1b4a9bf7
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/src/app/app.component.ts
@@ -0,0 +1,16 @@
+// #docregion import
+import { Component } from '@angular/core';
+// #enddocregion import
+
+// #docregion metadata
+@Component({
+ selector: 'app-root',
+ templateUrl: './app.component.html',
+ styleUrls: ['./app.component.css']
+})
+// #enddocregion metadata
+// #docregion title, class
+export class AppComponent {
+ title = 'My First Angular App';
+}
+// #enddocregion title, class
diff --git a/public/docs/_examples/cli-quickstart/ts/src/app/app.module.ts b/public/docs/_examples/cli-quickstart/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..67ae49119b
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/src/app/app.module.ts
@@ -0,0 +1,20 @@
+import { BrowserModule } from '@angular/platform-browser';
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+import { HttpModule } from '@angular/http';
+
+import { AppComponent } from './app.component';
+
+@NgModule({
+ declarations: [
+ AppComponent
+ ],
+ imports: [
+ BrowserModule,
+ FormsModule,
+ HttpModule
+ ],
+ providers: [],
+ bootstrap: [AppComponent]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/upgrade/ts/ng2_initial/app/css/.gitkeep b/public/docs/_examples/cli-quickstart/ts/src/assets/.gitkeep
similarity index 100%
rename from public/docs/_examples/upgrade/ts/ng2_initial/app/css/.gitkeep
rename to public/docs/_examples/cli-quickstart/ts/src/assets/.gitkeep
diff --git a/public/docs/_examples/cli-quickstart/ts/src/environments/environment.prod.ts b/public/docs/_examples/cli-quickstart/ts/src/environments/environment.prod.ts
new file mode 100644
index 0000000000..3612073bc3
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/src/environments/environment.prod.ts
@@ -0,0 +1,3 @@
+export const environment = {
+ production: true
+};
diff --git a/public/docs/_examples/cli-quickstart/ts/src/environments/environment.ts b/public/docs/_examples/cli-quickstart/ts/src/environments/environment.ts
new file mode 100644
index 0000000000..b7f639aeca
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/src/environments/environment.ts
@@ -0,0 +1,8 @@
+// The file contents for the current environment will overwrite these during build.
+// The build system defaults to the dev environment which uses `environment.ts`, but if you do
+// `ng build --env=prod` then `environment.prod.ts` will be used instead.
+// The list of which env maps to which file can be found in `.angular-cli.json`.
+
+export const environment = {
+ production: false
+};
diff --git a/public/docs/_examples/cli-quickstart/ts/src/favicon.ico b/public/docs/_examples/cli-quickstart/ts/src/favicon.ico
new file mode 100644
index 0000000000..8081c7ceaf
Binary files /dev/null and b/public/docs/_examples/cli-quickstart/ts/src/favicon.ico differ
diff --git a/public/docs/_examples/cli-quickstart/ts/src/index.html b/public/docs/_examples/cli-quickstart/ts/src/index.html
new file mode 100644
index 0000000000..8a1a7b32b3
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/src/index.html
@@ -0,0 +1,14 @@
+
+
+
+
+ MyApp
+
+
+
+
+
+
+ Loading...
+
+
diff --git a/public/docs/_examples/cli-quickstart/ts/src/main.ts b/public/docs/_examples/cli-quickstart/ts/src/main.ts
new file mode 100644
index 0000000000..a9ca1caf8c
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/src/main.ts
@@ -0,0 +1,11 @@
+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);
diff --git a/public/docs/_examples/cli-quickstart/ts/src/polyfills.ts b/public/docs/_examples/cli-quickstart/ts/src/polyfills.ts
new file mode 100644
index 0000000000..53bdaf1b86
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/src/polyfills.ts
@@ -0,0 +1,68 @@
+/**
+ * This file includes polyfills needed by Angular and is loaded before the app.
+ * You can add your own extra polyfills to this file.
+ *
+ * This file is divided into 2 sections:
+ * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
+ * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
+ * file.
+ *
+ * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
+ * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
+ * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
+ *
+ * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
+ */
+
+/***************************************************************************************************
+ * BROWSER POLYFILLS
+ */
+
+/** IE9, IE10 and IE11 requires all of the following polyfills. **/
+// import 'core-js/es6/symbol';
+// import 'core-js/es6/object';
+// import 'core-js/es6/function';
+// import 'core-js/es6/parse-int';
+// import 'core-js/es6/parse-float';
+// import 'core-js/es6/number';
+// import 'core-js/es6/math';
+// import 'core-js/es6/string';
+// import 'core-js/es6/date';
+// import 'core-js/es6/array';
+// import 'core-js/es6/regexp';
+// import 'core-js/es6/map';
+// import 'core-js/es6/set';
+
+/** IE10 and IE11 requires the following for NgClass support on SVG elements */
+// import 'classlist.js'; // Run `npm install --save classlist.js`.
+
+/** IE10 and IE11 requires the following to support `@angular/animation`. */
+// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
+
+
+/** Evergreen browsers require these. **/
+import 'core-js/es6/reflect';
+import 'core-js/es7/reflect';
+
+
+/** ALL Firefox browsers require the following to support `@angular/animation`. **/
+// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
+
+
+
+/***************************************************************************************************
+ * Zone JS is required by Angular itself.
+ */
+import 'zone.js/dist/zone'; // Included with Angular CLI.
+
+
+
+/***************************************************************************************************
+ * APPLICATION IMPORTS
+ */
+
+/**
+ * Date, currency, decimal and percent pipes.
+ * Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10
+ */
+// import 'intl'; // Run `npm install --save intl`.
diff --git a/public/docs/_examples/cli-quickstart/ts/src/styles.css b/public/docs/_examples/cli-quickstart/ts/src/styles.css
new file mode 100644
index 0000000000..d81835d0cd
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/src/styles.css
@@ -0,0 +1,116 @@
+/* #docregion , quickstart, toh */
+/* Master Styles */
+h1 {
+ color: #369;
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 250%;
+}
+h2, h3 {
+ color: #444;
+ font-family: Arial, Helvetica, sans-serif;
+ font-weight: lighter;
+}
+body {
+ margin: 2em;
+}
+/* #enddocregion quickstart */
+body, input[text], button {
+ color: #888;
+ font-family: Cambria, Georgia;
+}
+/* #enddocregion toh */
+a {
+ cursor: pointer;
+ cursor: hand;
+}
+button {
+ font-family: Arial;
+ background-color: #eee;
+ border: none;
+ padding: 5px 10px;
+ border-radius: 4px;
+ cursor: pointer;
+ cursor: hand;
+}
+button:hover {
+ background-color: #cfd8dc;
+}
+button:disabled {
+ background-color: #eee;
+ color: #aaa;
+ cursor: auto;
+}
+
+/* Navigation link styles */
+nav a {
+ padding: 5px 10px;
+ text-decoration: none;
+ margin-right: 10px;
+ margin-top: 10px;
+ display: inline-block;
+ background-color: #eee;
+ border-radius: 4px;
+}
+nav a:visited, a:link {
+ color: #607D8B;
+}
+nav a:hover {
+ color: #039be5;
+ background-color: #CFD8DC;
+}
+nav a.active {
+ color: #039be5;
+}
+
+/* items class */
+.items {
+ margin: 0 0 2em 0;
+ list-style-type: none;
+ padding: 0;
+ width: 24em;
+}
+.items li {
+ cursor: pointer;
+ position: relative;
+ left: 0;
+ background-color: #EEE;
+ margin: .5em;
+ padding: .3em 0;
+ height: 1.6em;
+ border-radius: 4px;
+}
+.items li:hover {
+ color: #607D8B;
+ background-color: #DDD;
+ left: .1em;
+}
+.items li.selected {
+ background-color: #CFD8DC;
+ color: white;
+}
+.items li.selected:hover {
+ background-color: #BBD8DC;
+}
+.items .text {
+ position: relative;
+ top: -3px;
+}
+.items .badge {
+ display: inline-block;
+ font-size: small;
+ color: white;
+ padding: 0.8em 0.7em 0 0.7em;
+ background-color: #607D8B;
+ line-height: 1em;
+ position: relative;
+ left: -1px;
+ top: -4px;
+ height: 1.8em;
+ margin-right: .8em;
+ border-radius: 4px 0 0 4px;
+}
+/* #docregion toh */
+/* everywhere else */
+* {
+ font-family: Arial, Helvetica, sans-serif;
+}
diff --git a/public/docs/_examples/cli-quickstart/ts/src/test.ts b/public/docs/_examples/cli-quickstart/ts/src/test.ts
new file mode 100644
index 0000000000..9bf72267e9
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/src/test.ts
@@ -0,0 +1,32 @@
+// This file is required by karma.conf.js and loads recursively all the .spec and framework files
+
+import 'zone.js/dist/long-stack-trace-zone';
+import 'zone.js/dist/proxy.js';
+import 'zone.js/dist/sync-test';
+import 'zone.js/dist/jasmine-patch';
+import 'zone.js/dist/async-test';
+import 'zone.js/dist/fake-async-test';
+import { getTestBed } from '@angular/core/testing';
+import {
+ BrowserDynamicTestingModule,
+ platformBrowserDynamicTesting
+} from '@angular/platform-browser-dynamic/testing';
+
+// Unfortunately there's no typing for the `__karma__` variable. Just declare it as any.
+declare var __karma__: any;
+declare var require: any;
+
+// Prevent Karma from running prematurely.
+__karma__.loaded = function () {};
+
+// First, initialize the Angular testing environment.
+getTestBed().initTestEnvironment(
+ BrowserDynamicTestingModule,
+ platformBrowserDynamicTesting()
+);
+// Then we find all the tests.
+const context = require.context('./', true, /\.spec\.ts$/);
+// And load the modules.
+context.keys().map(context);
+// Finally, start Karma to run the tests.
+__karma__.start();
diff --git a/public/docs/_examples/cli-quickstart/ts/src/tsconfig.app.json b/public/docs/_examples/cli-quickstart/ts/src/tsconfig.app.json
new file mode 100644
index 0000000000..9f12c4b849
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/src/tsconfig.app.json
@@ -0,0 +1,22 @@
+{
+ "compilerOptions": {
+ "sourceMap": true,
+ "declaration": false,
+ "moduleResolution": "node",
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "lib": [
+ "es2016",
+ "dom"
+ ],
+ "outDir": "../out-tsc/app",
+ "target": "es5",
+ "module": "es2015",
+ "baseUrl": "",
+ "types": []
+ },
+ "exclude": [
+ "test.ts",
+ "**/*.spec.ts"
+ ]
+}
diff --git a/public/docs/_examples/cli-quickstart/ts/src/tsconfig.spec.json b/public/docs/_examples/cli-quickstart/ts/src/tsconfig.spec.json
new file mode 100644
index 0000000000..6c5160e12e
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/src/tsconfig.spec.json
@@ -0,0 +1,26 @@
+{
+ "compilerOptions": {
+ "sourceMap": true,
+ "declaration": false,
+ "moduleResolution": "node",
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "lib": [
+ "es2016"
+ ],
+ "outDir": "../out-tsc/spec",
+ "module": "commonjs",
+ "target": "es6",
+ "baseUrl": "",
+ "types": [
+ "jasmine",
+ "node"
+ ]
+ },
+ "files": [
+ "test.ts"
+ ],
+ "include": [
+ "**/*.spec.ts"
+ ]
+}
diff --git a/public/docs/_examples/cli-quickstart/ts/tsconfig.json b/public/docs/_examples/cli-quickstart/ts/tsconfig.json
new file mode 100644
index 0000000000..cde5e35054
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/tsconfig.json
@@ -0,0 +1,14 @@
+{
+ "compileOnSave": false,
+ "compilerOptions": {
+ "outDir": "./dist/out-tsc",
+ "sourceMap": true,
+ "declaration": false,
+ "moduleResolution": "node",
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "lib": [
+ "es2016"
+ ]
+ }
+}
diff --git a/public/docs/_examples/cli-quickstart/ts/zipper.json b/public/docs/_examples/cli-quickstart/ts/zipper.json
new file mode 100644
index 0000000000..70bf41659e
--- /dev/null
+++ b/public/docs/_examples/cli-quickstart/ts/zipper.json
@@ -0,0 +1,11 @@
+{
+ "files":[
+ "!**/*.d.ts",
+ "!**/*.js",
+ "!**/*.[0-9].*",
+ ".angular-cli.json",
+ "protractor.conf.js"
+ ],
+ "removeSystemJsConfig": true,
+ "type": "cli"
+}
diff --git a/public/docs/_examples/component-styles/e2e-spec.ts b/public/docs/_examples/component-styles/e2e-spec.ts
new file mode 100644
index 0000000000..32bd30832c
--- /dev/null
+++ b/public/docs/_examples/component-styles/e2e-spec.ts
@@ -0,0 +1,68 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by } from 'protractor';
+
+describe('Component Style Tests', function () {
+
+ beforeAll(function () {
+ browser.get('');
+ });
+
+ it('scopes component styles to component view', function() {
+ let componentH1 = element(by.css('hero-app > h1'));
+ let externalH1 = element(by.css('body > h1'));
+
+ expect(componentH1.getCssValue('fontWeight')).toEqual('normal');
+ expect(externalH1.getCssValue('fontWeight')).not.toEqual('normal');
+ });
+
+
+ it('allows styling :host element', function() {
+ let host = element(by.css('hero-details'));
+
+ expect(host.getCssValue('borderWidth')).toEqual('1px');
+ });
+
+ it('supports :host() in function form', function() {
+ let host = element(by.css('hero-details'));
+
+ host.element(by.buttonText('Activate')).click();
+ expect(host.getCssValue('borderWidth')).toEqual('3px');
+ });
+
+ it('allows conditional :host-context() styling', function() {
+ let h2 = element(by.css('hero-details h2'));
+
+ expect(h2.getCssValue('backgroundColor')).toEqual('rgba(238, 238, 255, 1)'); // #eeeeff
+ });
+
+ it('styles both view and content children with /deep/', function() {
+ let viewH3 = element(by.css('hero-team h3'));
+ let contentH3 = element(by.css('hero-controls h3'));
+
+ expect(viewH3.getCssValue('fontStyle')).toEqual('italic');
+ expect(contentH3.getCssValue('fontStyle')).toEqual('italic');
+ });
+
+ it('includes styles loaded with CSS @import', function() {
+ let host = element(by.css('hero-details'));
+
+ expect(host.getCssValue('padding')).toEqual('10px');
+ });
+
+ it('processes template inline styles', function() {
+ let button = element(by.css('hero-controls button'));
+ let externalButton = element(by.css('body > button'));
+ expect(button.getCssValue('backgroundColor')).toEqual('rgba(255, 255, 255, 1)'); // #ffffff
+ expect(externalButton.getCssValue('backgroundColor')).not.toEqual('rgba(255, 255, 255, 1)');
+ });
+
+ it('processes template s', function() {
+ let li = element(by.css('hero-team li:first-child'));
+ let externalLi = element(by.css('body > ul li'));
+
+ expect(li.getCssValue('listStyleType')).toEqual('square');
+ expect(externalLi.getCssValue('listStyleType')).not.toEqual('square');
+ });
+
+});
diff --git a/public/docs/_examples/upgrade/ts/ng2_initial/app/img/.gitkeep b/public/docs/_examples/component-styles/ts/example-config.json
similarity index 100%
rename from public/docs/_examples/upgrade/ts/ng2_initial/app/img/.gitkeep
rename to public/docs/_examples/component-styles/ts/example-config.json
diff --git a/public/docs/_examples/component-styles/ts/plnkr.json b/public/docs/_examples/component-styles/ts/plnkr.json
new file mode 100644
index 0000000000..e045ebcb38
--- /dev/null
+++ b/public/docs/_examples/component-styles/ts/plnkr.json
@@ -0,0 +1,10 @@
+{
+ "description": "Component Styles",
+ "basePath": "src/",
+ "files": [
+ "!**/*.d.ts",
+ "!**/*.js",
+ "!**/*.native.*"
+ ],
+ "tags": ["CSS"]
+}
diff --git a/public/docs/_examples/component-styles/ts/src/app/app.module.ts b/public/docs/_examples/component-styles/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..31c72cbbf2
--- /dev/null
+++ b/public/docs/_examples/component-styles/ts/src/app/app.module.ts
@@ -0,0 +1,23 @@
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+import { HeroAppComponent } from './hero-app.component';
+import { HeroAppMainComponent } from './hero-app-main.component';
+import { HeroDetailsComponent } from './hero-details.component';
+import { HeroControlsComponent } from './hero-controls.component';
+import { QuestSummaryComponent } from './quest-summary.component';
+import { HeroTeamComponent } from './hero-team.component';
+
+@NgModule({
+ imports: [ BrowserModule ],
+ declarations: [
+ HeroAppComponent,
+ HeroAppMainComponent,
+ HeroDetailsComponent,
+ HeroControlsComponent,
+ QuestSummaryComponent,
+ HeroTeamComponent
+ ],
+ bootstrap: [ HeroAppComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/component-styles/ts/src/app/hero-app-main.component.ts b/public/docs/_examples/component-styles/ts/src/app/hero-app-main.component.ts
new file mode 100644
index 0000000000..aebb1f729e
--- /dev/null
+++ b/public/docs/_examples/component-styles/ts/src/app/hero-app-main.component.ts
@@ -0,0 +1,16 @@
+import { Component, Input } from '@angular/core';
+
+import { Hero } from './hero';
+
+@Component({
+ selector: 'hero-app-main',
+ template: `
+
+
+
+
+ `
+})
+export class HeroAppMainComponent {
+ @Input() hero: Hero;
+}
diff --git a/public/docs/_examples/component-styles/ts/src/app/hero-app.component.ts b/public/docs/_examples/component-styles/ts/src/app/hero-app.component.ts
new file mode 100644
index 0000000000..5f1923e6f3
--- /dev/null
+++ b/public/docs/_examples/component-styles/ts/src/app/hero-app.component.ts
@@ -0,0 +1,24 @@
+import { Component, HostBinding } from '@angular/core';
+import { Hero } from './hero';
+
+// #docregion
+@Component({
+ selector: 'hero-app',
+ template: `
+ Tour of Heroes
+ `,
+ styles: ['h1 { font-weight: normal; }']
+})
+export class HeroAppComponent {
+// #enddocregion
+ hero = new Hero(
+ 'Human Torch',
+ ['Mister Fantastic', 'Invisible Woman', 'Thing']
+ );
+
+ @HostBinding('class') get themeClass() {
+ return 'theme-light';
+ }
+// #docregion
+}
+// #enddocregion
diff --git a/public/docs/_examples/component-styles/ts/src/app/hero-controls.component.ts b/public/docs/_examples/component-styles/ts/src/app/hero-controls.component.ts
new file mode 100644
index 0000000000..5d293596d2
--- /dev/null
+++ b/public/docs/_examples/component-styles/ts/src/app/hero-controls.component.ts
@@ -0,0 +1,25 @@
+import { Component, Input } from '@angular/core';
+import { Hero } from './hero';
+
+// #docregion inlinestyles
+@Component({
+ selector: 'hero-controls',
+ template: `
+
+ Controls
+ Activate
+ `
+})
+// #enddocregion inlinestyles
+export class HeroControlsComponent {
+ @Input() hero: Hero;
+
+ activate() {
+ this.hero.active = true;
+ }
+}
diff --git a/public/docs/_examples/component-styles/ts/src/app/hero-details-box.css b/public/docs/_examples/component-styles/ts/src/app/hero-details-box.css
new file mode 100644
index 0000000000..f240073005
--- /dev/null
+++ b/public/docs/_examples/component-styles/ts/src/app/hero-details-box.css
@@ -0,0 +1,3 @@
+:host {
+ padding: 10px;
+}
diff --git a/public/docs/_examples/component-styles/ts/src/app/hero-details.component.css b/public/docs/_examples/component-styles/ts/src/app/hero-details.component.css
new file mode 100644
index 0000000000..fd938ca55c
--- /dev/null
+++ b/public/docs/_examples/component-styles/ts/src/app/hero-details.component.css
@@ -0,0 +1,28 @@
+/* #docregion import */
+@import 'hero-details-box.css';
+/* #enddocregion import */
+
+/* #docregion host */
+:host {
+ display: block;
+ border: 1px solid black;
+}
+/* #enddocregion host */
+
+/* #docregion hostfunction */
+:host(.active) {
+ border-width: 3px;
+}
+/* #enddocregion hostfunction */
+
+/* #docregion hostcontext */
+:host-context(.theme-light) h2 {
+ background-color: #eef;
+}
+/* #enddocregion hostcontext */
+
+/* #docregion deep */
+:host /deep/ h3 {
+ font-style: italic;
+}
+/* #enddocregion deep */
diff --git a/public/docs/_examples/component-styles/ts/src/app/hero-details.component.ts b/public/docs/_examples/component-styles/ts/src/app/hero-details.component.ts
new file mode 100644
index 0000000000..bd86a63e04
--- /dev/null
+++ b/public/docs/_examples/component-styles/ts/src/app/hero-details.component.ts
@@ -0,0 +1,18 @@
+import { Component, Input } from '@angular/core';
+import { Hero } from './hero';
+
+// #docregion styleurls
+@Component({
+ selector: 'hero-details',
+ template: `
+ {{hero.name}}
+
+
+ `,
+ styleUrls: ['app/hero-details.component.css']
+})
+export class HeroDetailsComponent {
+ // #enddocregion styleurls
+ @Input() hero: Hero;
+ // #docregion styleurls
+}
diff --git a/public/docs/_examples/component-styles/ts/src/app/hero-team.component.css b/public/docs/_examples/component-styles/ts/src/app/hero-team.component.css
new file mode 100644
index 0000000000..b87679886b
--- /dev/null
+++ b/public/docs/_examples/component-styles/ts/src/app/hero-team.component.css
@@ -0,0 +1,3 @@
+li {
+ list-style-type: square;
+}
diff --git a/public/docs/_examples/component-styles/ts/src/app/hero-team.component.ts b/public/docs/_examples/component-styles/ts/src/app/hero-team.component.ts
new file mode 100644
index 0000000000..4f092d2827
--- /dev/null
+++ b/public/docs/_examples/component-styles/ts/src/app/hero-team.component.ts
@@ -0,0 +1,19 @@
+import { Component, Input } from '@angular/core';
+import { Hero } from './hero';
+
+// #docregion stylelink
+@Component({
+ selector: 'hero-team',
+ template: `
+
+ Team
+ `
+})
+// #enddocregion stylelink
+export class HeroTeamComponent {
+ @Input() hero: Hero;
+}
diff --git a/public/docs/_examples/component-styles/ts/src/app/hero.ts b/public/docs/_examples/component-styles/ts/src/app/hero.ts
new file mode 100644
index 0000000000..7f8969e682
--- /dev/null
+++ b/public/docs/_examples/component-styles/ts/src/app/hero.ts
@@ -0,0 +1,7 @@
+export class Hero {
+ active: boolean;
+
+ constructor(public name: string,
+ public team: string[]) {
+ }
+}
diff --git a/public/docs/_examples/component-styles/ts/src/app/quest-summary.component.css b/public/docs/_examples/component-styles/ts/src/app/quest-summary.component.css
new file mode 100644
index 0000000000..207fa981dd
--- /dev/null
+++ b/public/docs/_examples/component-styles/ts/src/app/quest-summary.component.css
@@ -0,0 +1,5 @@
+:host {
+ display: block;
+ background-color: green;
+ color: white;
+}
diff --git a/public/docs/_examples/component-styles/ts/src/app/quest-summary.component.html b/public/docs/_examples/component-styles/ts/src/app/quest-summary.component.html
new file mode 100644
index 0000000000..ace27d2a1c
--- /dev/null
+++ b/public/docs/_examples/component-styles/ts/src/app/quest-summary.component.html
@@ -0,0 +1 @@
+No quests in progress
diff --git a/public/docs/_examples/component-styles/ts/src/app/quest-summary.component.ts b/public/docs/_examples/component-styles/ts/src/app/quest-summary.component.ts
new file mode 100644
index 0000000000..2a2dc65fe0
--- /dev/null
+++ b/public/docs/_examples/component-styles/ts/src/app/quest-summary.component.ts
@@ -0,0 +1,20 @@
+/* tslint:disable:no-unused-variable */
+// #docplaster
+import { Component, ViewEncapsulation } from '@angular/core';
+
+// #docregion
+@Component({
+ selector: 'quest-summary',
+ // #docregion urls
+ templateUrl: './quest-summary.component.html',
+ styleUrls: ['./quest-summary.component.css']
+ // #enddocregion urls
+})
+export class QuestSummaryComponent { }
+// #enddocregion
+/*
+ // #docregion encapsulation.native
+ // warning: few browsers support shadow DOM encapsulation at this time
+ encapsulation: ViewEncapsulation.Native
+ // #enddocregion encapsulation.native
+*/
diff --git a/public/docs/_examples/component-styles/ts/src/index.html b/public/docs/_examples/component-styles/ts/src/index.html
new file mode 100644
index 0000000000..6e9dc51b32
--- /dev/null
+++ b/public/docs/_examples/component-styles/ts/src/index.html
@@ -0,0 +1,31 @@
+
+
+
+
+ Component Styles
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ External H1 Title for E2E test
+
+ External button for E2E test
+
+ External list for E2E test
+
+
+
+
diff --git a/public/docs/_examples/component-styles/ts/src/main.ts b/public/docs/_examples/component-styles/ts/src/main.ts
new file mode 100644
index 0000000000..6b6532d428
--- /dev/null
+++ b/public/docs/_examples/component-styles/ts/src/main.ts
@@ -0,0 +1,5 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/dependency-injection/dart/lib/app_component.dart b/public/docs/_examples/dependency-injection/dart/lib/app_component.dart
deleted file mode 100644
index 4e01554a42..0000000000
--- a/public/docs/_examples/dependency-injection/dart/lib/app_component.dart
+++ /dev/null
@@ -1,63 +0,0 @@
-// #docplaster
-
-// #docregion
-
-// #docregion imports
-import 'package:angular2/core.dart';
-import 'car/car_component.dart';
-import 'heroes/heroes_component.dart';
-import 'app_config.dart';
-import 'logger_service.dart';
-import 'user_service.dart';
-
-// #enddocregion imports
-import 'injector_component.dart';
-import 'providers_component.dart';
-
-@Component(
- selector: 'my-app',
- template: '''
- {{title}}
-
-
-
- User
-
- {{userInfo}}
- Next User
-
-
-
- ''',
- directives: const [CarComponent, HeroesComponent, InjectorComponent, ProvidersComponent],
-// #docregion providers
- providers: const [Logger, UserService, const Provider(Config, useValue: CONFIG)]
-// #enddocregion providers
- )
-class AppComponent {
- UserService _userService;
- String title;
-
- //#docregion ctor
- AppComponent(Config config, this._userService) {
- title = config.title;
- }
-
- // #enddocregion ctor
- bool get isAuthorized {
- return user.isAuthorized;
- }
-
- void nextUser() {
- _userService.getNewUser();
- }
-
- User get user {
- return _userService.user;
- }
-
- String get userInfo {
- return 'Current user, ${user.name}, is ${isAuthorized ? "" : "not"} authorized. ';
- }
-}
-// #enddocregion
diff --git a/public/docs/_examples/dependency-injection/dart/lib/app_component_1.dart b/public/docs/_examples/dependency-injection/dart/lib/app_component_1.dart
deleted file mode 100644
index 7c3b7b9808..0000000000
--- a/public/docs/_examples/dependency-injection/dart/lib/app_component_1.dart
+++ /dev/null
@@ -1,28 +0,0 @@
-// Early versions
-
-// #docregion
-import 'package:angular2/core.dart';
-import 'car/car_component.dart';
-import 'heroes/heroes_component_1.dart';
-
-@Component(
- selector: 'my-app',
- template: '''
-
{{title}}
-
-
- ''',
- directives: const [CarComponent, HeroesComponent])
-class AppComponent {
- var title = 'Dependency Injection';
-}
-// #enddocregion
-
-/*
-//#docregion ctor-di-fail
-// FAIL! Injectable `config` is not a class!
-AppComponent(HeroService heroService, Map config) {
- title = config['title'];
-}
-//#enddocregion ctor-di-fail
-*/
diff --git a/public/docs/_examples/dependency-injection/dart/lib/app_component_2.dart b/public/docs/_examples/dependency-injection/dart/lib/app_component_2.dart
deleted file mode 100644
index 7bf4249ee2..0000000000
--- a/public/docs/_examples/dependency-injection/dart/lib/app_component_2.dart
+++ /dev/null
@@ -1,35 +0,0 @@
-// #docregion
-
-// #docregion imports
-import 'package:angular2/core.dart';
-import 'car/car_component.dart';
-import 'heroes/heroes_component_1.dart';
-import 'app_config.dart';
-import 'logger_service.dart';
-
-// #enddocregion imports
-@Component(
- selector: 'my-app',
- template: '''
- {{title}}
-
-
- ''',
- directives: const [
- CarComponent,
- HeroesComponent
- ],
- providers: const [
- Logger,
- // #docregion provider-config
- const Provider('app.config', useValue: CONFIG)
- ])
-class AppComponent {
- String title;
-
- // #docregion ctor
- AppComponent(@Inject('app.config') Config config) {
- title = config.title;
- }
-}
-// #enddocregion
diff --git a/public/docs/_examples/dependency-injection/dart/lib/app_config.dart b/public/docs/_examples/dependency-injection/dart/lib/app_config.dart
deleted file mode 100644
index 8fc877f188..0000000000
--- a/public/docs/_examples/dependency-injection/dart/lib/app_config.dart
+++ /dev/null
@@ -1,29 +0,0 @@
-//#docregion
-
-// #docregion token
-import 'package:angular2/core.dart';
-
-const APP_CONFIG = const OpaqueToken('app.config');
-// #enddocregion token
-
-//#docregion config
-abstract class Config {
- final String apiEndpoint;
- final String title;
-
- const Config({this.apiEndpoint, this.title});
-}
-
-class ConfigImpl implements Config {
- final String apiEndpoint;
- final String title;
-
- const ConfigImpl({this.apiEndpoint, this.title});
-}
-
-const CONFIG = const ConfigImpl(apiEndpoint: 'api.heroes.com', title: 'Dependency Injection');
-//#enddocregion config
-
-//#docregion config-hash
-const CONFIG_HASH = const {'apiEndpoint': 'api.heroes.com', 'title': 'Dependency Injection'};
-//#enddocregion config-hash
diff --git a/public/docs/_examples/dependency-injection/dart/lib/car/car.dart b/public/docs/_examples/dependency-injection/dart/lib/car/car.dart
deleted file mode 100644
index 4c8d1025e7..0000000000
--- a/public/docs/_examples/dependency-injection/dart/lib/car/car.dart
+++ /dev/null
@@ -1,32 +0,0 @@
-// #docregion
-
-import 'package:angular2/core.dart';
-
-// #docregion engine
-class Engine {
- int cylinders = 4;
-}
-// #enddocregion engine
-
-// #docregion tires
-class Tires {
- String make = 'Flintstone';
- String model = 'Square';
-}
-
-// #enddocregion tires
-@Injectable()
-class Car {
- //#docregion car-ctor
- Engine engine;
- Tires tires;
- String description = 'DI';
-
- Car(this.engine, this.tires);
-
- // #enddocregion car-ctor
-
- // Method using the engine and tires
- String drive() => '$description car with ${engine.cylinders} cylinders and ${tires.make} tires.';
-}
-// #enddocregion car
diff --git a/public/docs/_examples/dependency-injection/dart/lib/car/car_component.dart b/public/docs/_examples/dependency-injection/dart/lib/car/car_component.dart
deleted file mode 100644
index e8e3ccc0e0..0000000000
--- a/public/docs/_examples/dependency-injection/dart/lib/car/car_component.dart
+++ /dev/null
@@ -1,33 +0,0 @@
-// #docregion
-
-import 'package:angular2/core.dart';
-import 'car.dart';
-import 'car_no_di.dart' as carNoDi;
-import 'car_factory.dart';
-import 'car_creations.dart' as carCreations;
-import 'car_injector.dart';
-
-@Component(
- selector: 'my-car',
- template: '''
- Cars
- {{car.drive()}}
- {{noDiCar.drive()}}
- {{injectorCar.drive()}}
- {{factoryCar.drive()}}
- {{simpleCar.drive()}}
- {{superCar.drive()}}
- {{testCar.drive()}}
- ''',
- providers: const [Car, Engine, Tires])
-class CarComponent {
- Car car;
-
- CarComponent(this.car) {}
- Car factoryCar = (new CarFactory()).createCar();
- Car injectorCar = useInjector();
- carNoDi.Car noDiCar = new carNoDi.Car();
- Car simpleCar = carCreations.simpleCar();
- Car superCar = carCreations.superCar();
- Car testCar = carCreations.testCar();
-}
diff --git a/public/docs/_examples/dependency-injection/dart/lib/car/car_creations.dart b/public/docs/_examples/dependency-injection/dart/lib/car/car_creations.dart
deleted file mode 100644
index 33dfa05828..0000000000
--- a/public/docs/_examples/dependency-injection/dart/lib/car/car_creations.dart
+++ /dev/null
@@ -1,56 +0,0 @@
-// Examples with car and engine variations
-
-// #docplaster
-import 'car.dart';
-
-///////// example 1 ////////////
-Car simpleCar() {
- //#docregion car-ctor-instantiation
-
- // Simple car with 4 cylinders and Flintstone tires.
- var car = new Car(new Engine(), new Tires());
- //#enddocregion car-ctor-instantiation
- car.description = 'Simple';
- return car;
-}
-///////// example 2 ////////////
-
-//#docregion car-ctor-instantiation-with-param
-class Engine2 implements Engine {
- int cylinders;
-
- Engine2(this.cylinders);
-}
-
-//#enddocregion car-ctor-instantiation-with-param
-Car superCar() {
- //#docregion car-ctor-instantiation-with-param
-
- // Super car with 12 cylinders and Flintstone tires.
- var bigCylinders = 12;
- var car = new Car(new Engine2(bigCylinders), new Tires());
- //#enddocregion car-ctor-instantiation-with-param
- car.description = 'Super';
- return car;
-}
-/////////// example 3 //////////
-
-//#docregion car-ctor-instantiation-with-mocks
-class MockEngine extends Engine {
- int cylinders = 8;
-}
-
-class MockTires extends Tires {
- String make = 'YokoGoodStone';
-}
-
-//#enddocregion car-ctor-instantiation-with-mocks
-Car testCar() {
- //#docregion car-ctor-instantiation-with-mocks
-
- // Test car with 8 cylinders and YokoGoodStone tires.
- var car = new Car(new MockEngine(), new MockTires());
- //#enddocregion car-ctor-instantiation-with-mocks
- car.description = 'Test';
- return car;
-}
diff --git a/public/docs/_examples/dependency-injection/dart/lib/car/car_factory.dart b/public/docs/_examples/dependency-injection/dart/lib/car/car_factory.dart
deleted file mode 100644
index 76b8a4cc63..0000000000
--- a/public/docs/_examples/dependency-injection/dart/lib/car/car_factory.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// #docregion
-
-import 'car.dart';
-
-class CarFactory {
- Car createCar() {
- var car = new Car(createEngine(), createTires());
- car.description = 'Factory';
- return car;
- }
-
- Engine createEngine() => new Engine();
-
- Tires createTires() => new Tires();
-}
diff --git a/public/docs/_examples/dependency-injection/dart/lib/car/car_injector.dart b/public/docs/_examples/dependency-injection/dart/lib/car/car_injector.dart
deleted file mode 100644
index 1dbadd9fab..0000000000
--- a/public/docs/_examples/dependency-injection/dart/lib/car/car_injector.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-// #docplaster
-
-//#docregion
-import 'package:angular2/core.dart';
-import 'car.dart';
-import '../logger_service.dart';
-
-//#docregion injector
-Car useInjector() {
- Injector injector;
- //#enddocregion injector
-
- /*
-//#docregion injector-no-new
- // Cannot 'new' an Injector like this!
- var injector = new Injector([Car, Engine, Tires, Logger]);
-//#enddocregion injector-no-new
-*/
-
- //#docregion injector
-
- //#docregion injector-create-and-call
- injector = Injector.resolveAndCreate([Car, Engine, Tires, Logger]);
- //#docregion injector-call
- var car = injector.get(Car);
- //#enddocregion injector-call
-
- //#enddocregion injector-create-and-call
- car.description = 'Injector';
- var logger = injector.get(Logger);
- logger.log('Injector car.drive() said: ' + car.drive());
- return car;
-}
-//#enddocregion injector
-
-//#enddocregion
diff --git a/public/docs/_examples/dependency-injection/dart/lib/car/car_no_di.dart b/public/docs/_examples/dependency-injection/dart/lib/car/car_no_di.dart
deleted file mode 100644
index 32972c3dc1..0000000000
--- a/public/docs/_examples/dependency-injection/dart/lib/car/car_no_di.dart
+++ /dev/null
@@ -1,22 +0,0 @@
-// Car without DI
-
-import 'car.dart';
-
-//#docregion car
-class Car {
- //#docregion car-ctor
- Engine engine;
- Tires tires;
- var description = 'No DI';
-
- Car() {
- engine = new Engine();
- tires = new Tires();
- }
-
- //#enddocregion car-ctor
-
- // Method using the engine and tires
- drive() => '$description car with ${engine.cylinders} cylinders and ${tires.make} tires.';
-}
-//#enddocregion car
diff --git a/public/docs/_examples/dependency-injection/dart/lib/heroes/hero.dart b/public/docs/_examples/dependency-injection/dart/lib/heroes/hero.dart
deleted file mode 100644
index ea10276b7c..0000000000
--- a/public/docs/_examples/dependency-injection/dart/lib/heroes/hero.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-// #docregion
-
-class Hero {
- num id;
- String name;
- bool isSecret = false;
-}
diff --git a/public/docs/_examples/dependency-injection/dart/lib/heroes/hero_list_component.dart b/public/docs/_examples/dependency-injection/dart/lib/heroes/hero_list_component.dart
deleted file mode 100644
index c4eeb14f1b..0000000000
--- a/public/docs/_examples/dependency-injection/dart/lib/heroes/hero_list_component.dart
+++ /dev/null
@@ -1,21 +0,0 @@
-// #docregion
-
-import 'package:angular2/core.dart';
-import 'hero.dart';
-import 'hero_service.dart';
-
-@Component(
- selector: 'hero-list',
- template: '''
-
- {{hero.id}} - {{hero.name}}
- ({{hero.isSecret ? \'secret\' : \'public\'}})
-
- ''')
-class HeroListComponent {
- List heroes;
-
-//#docregion ctor-signature
- HeroListComponent(HeroService heroService) : heroes = heroService.getHeroes();
-//#enddocregion ctor-signature
-}
diff --git a/public/docs/_examples/dependency-injection/dart/lib/heroes/hero_list_component_1.dart b/public/docs/_examples/dependency-injection/dart/lib/heroes/hero_list_component_1.dart
deleted file mode 100644
index 3aeef5aefb..0000000000
--- a/public/docs/_examples/dependency-injection/dart/lib/heroes/hero_list_component_1.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// #docregion
-
-import 'package:angular2/core.dart';
-import 'hero.dart';
-import 'mock_heroes.dart';
-
-@Component(
- selector: 'hero-list',
- template: '''
-
- {{hero.id}} - {{hero.name}}
-
- ''')
-class HeroListComponent {
- List heroes = HEROES;
-}
diff --git a/public/docs/_examples/dependency-injection/dart/lib/heroes/hero_list_component_2.dart b/public/docs/_examples/dependency-injection/dart/lib/heroes/hero_list_component_2.dart
deleted file mode 100644
index 2b76419505..0000000000
--- a/public/docs/_examples/dependency-injection/dart/lib/heroes/hero_list_component_2.dart
+++ /dev/null
@@ -1,20 +0,0 @@
-// #docregion
-
-import 'package:angular2/core.dart';
-import 'hero.dart';
-import 'hero_service.dart';
-
-@Component(
- selector: 'hero-list',
- template: '''
-
- {{hero.id}} - {{hero.name}}
-
- ''')
-class HeroListComponent {
- List heroes;
-
-//#docregion ctor
- HeroListComponent(HeroService heroService) : heroes = heroService.getHeroes();
-//#enddocregion ctor
-}
diff --git a/public/docs/_examples/dependency-injection/dart/lib/heroes/hero_service.dart b/public/docs/_examples/dependency-injection/dart/lib/heroes/hero_service.dart
deleted file mode 100644
index 2dda48cb70..0000000000
--- a/public/docs/_examples/dependency-injection/dart/lib/heroes/hero_service.dart
+++ /dev/null
@@ -1,22 +0,0 @@
-// #docregion
-
-import 'package:angular2/core.dart';
-import 'hero.dart';
-import 'mock_heroes.dart';
-import '../logger_service.dart';
-
-@Injectable()
-class HeroService {
- // #docregion internals
- Logger _logger;
- bool _isAuthorized;
-
- HeroService(this._logger, this._isAuthorized);
-
- List getHeroes() {
- var auth = _isAuthorized ? 'authorized' : 'unauthorized';
- _logger.log('Getting heroes for ${auth} user.');
- return HEROES.where((hero) => _isAuthorized || !hero.isSecret).toList();
- }
-// #enddocregion internals
-}
diff --git a/public/docs/_examples/dependency-injection/dart/lib/heroes/hero_service_1.dart b/public/docs/_examples/dependency-injection/dart/lib/heroes/hero_service_1.dart
deleted file mode 100644
index 7ee6a642b4..0000000000
--- a/public/docs/_examples/dependency-injection/dart/lib/heroes/hero_service_1.dart
+++ /dev/null
@@ -1,8 +0,0 @@
-// #docregion
-
-import 'hero.dart';
-import 'mock_heroes.dart';
-
-class HeroService {
- List getHeroes() => HEROES;
-}
diff --git a/public/docs/_examples/dependency-injection/dart/lib/heroes/hero_service_2.dart b/public/docs/_examples/dependency-injection/dart/lib/heroes/hero_service_2.dart
deleted file mode 100644
index 25146a76f9..0000000000
--- a/public/docs/_examples/dependency-injection/dart/lib/heroes/hero_service_2.dart
+++ /dev/null
@@ -1,20 +0,0 @@
-// #docregion
-
-import 'package:angular2/core.dart';
-import 'hero.dart';
-import 'mock_heroes.dart';
-import '../logger_service.dart';
-
-@Injectable()
-class HeroService {
- Logger _logger;
-
- //#docregion ctor
- HeroService(this._logger);
-
- //#enddocregion ctor
- List getHeroes() {
- _logger.log('Getting heroes ...');
- return HEROES;
- }
-}
diff --git a/public/docs/_examples/dependency-injection/dart/lib/heroes/hero_service_provider.dart b/public/docs/_examples/dependency-injection/dart/lib/heroes/hero_service_provider.dart
deleted file mode 100644
index b783f0edc5..0000000000
--- a/public/docs/_examples/dependency-injection/dart/lib/heroes/hero_service_provider.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// #docregion
-
-import 'package:angular2/core.dart';
-import 'hero_service.dart';
-import '../logger_service.dart';
-import '../user_service.dart';
-
-// #docregion factory
-heroServiceFactory(Logger logger, UserService userService) =>
- new HeroService(logger, userService.user.isAuthorized);
-// #enddocregion factory
-
-// #docregion provider
-const heroServiceProvider =
- const Provider(HeroService, useFactory: heroServiceFactory, deps: const [Logger, UserService]);
-// #enddocregion provider
diff --git a/public/docs/_examples/dependency-injection/dart/lib/heroes/heroes_component.dart b/public/docs/_examples/dependency-injection/dart/lib/heroes/heroes_component.dart
deleted file mode 100644
index 45e310cd30..0000000000
--- a/public/docs/_examples/dependency-injection/dart/lib/heroes/heroes_component.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// #docregion
-
-import 'package:angular2/core.dart';
-import 'hero_list_component.dart';
-import 'hero_service_provider.dart';
-
-@Component(
- selector: 'my-heroes',
- template: '''
- Heroes
-
- ''',
- providers: const [heroServiceProvider],
- directives: const [HeroListComponent])
-class HeroesComponent {}
diff --git a/public/docs/_examples/dependency-injection/dart/lib/heroes/heroes_component_1.dart b/public/docs/_examples/dependency-injection/dart/lib/heroes/heroes_component_1.dart
deleted file mode 100644
index 80d7ad8f2e..0000000000
--- a/public/docs/_examples/dependency-injection/dart/lib/heroes/heroes_component_1.dart
+++ /dev/null
@@ -1,25 +0,0 @@
-// #docplaster
-
-// #docregion
-// #docregion v1
-import 'package:angular2/core.dart';
-import 'hero_list_component.dart';
-
-// #enddocregion v1
-import 'hero_service.dart';
-
-// #docregion v1
-@Component(
- selector: 'my-heroes',
- template: '''
- Heroes
-
- ''',
-// #enddocregion v1
-// #docregion providers
- providers: const [HeroService],
-// #enddocregion providers
-// #docregion v1
- directives: const [HeroListComponent])
-class HeroesComponent {}
-// #enddocregion v1
diff --git a/public/docs/_examples/dependency-injection/dart/lib/heroes/mock_heroes.dart b/public/docs/_examples/dependency-injection/dart/lib/heroes/mock_heroes.dart
deleted file mode 100644
index 9f49bf208c..0000000000
--- a/public/docs/_examples/dependency-injection/dart/lib/heroes/mock_heroes.dart
+++ /dev/null
@@ -1,46 +0,0 @@
-// #docregion
-
-import 'hero.dart';
-
-List HEROES = [
- new Hero()
- ..id = 11
- ..isSecret = false
- ..name = 'Mr. Nice',
- new Hero()
- ..id = 12
- ..isSecret = false
- ..name = 'Narco',
- new Hero()
- ..id = 13
- ..isSecret = false
- ..name = 'Bombasto',
- new Hero()
- ..id = 14
- ..isSecret = false
- ..name = 'Celeritas',
- new Hero()
- ..id = 15
- ..isSecret = false
- ..name = 'Magneta',
- new Hero()
- ..id = 16
- ..isSecret = false
- ..name = 'RubberMan',
- new Hero()
- ..id = 17
- ..isSecret = false
- ..name = 'Dynama',
- new Hero()
- ..id = 18
- ..isSecret = true
- ..name = 'Dr IQ',
- new Hero()
- ..id = 19
- ..isSecret = true
- ..name = 'Magma',
- new Hero()
- ..id = 20
- ..isSecret = true
- ..name = 'Tornado'
-];
diff --git a/public/docs/_examples/dependency-injection/dart/lib/injector_component.dart b/public/docs/_examples/dependency-injection/dart/lib/injector_component.dart
deleted file mode 100644
index 24e1598f13..0000000000
--- a/public/docs/_examples/dependency-injection/dart/lib/injector_component.dart
+++ /dev/null
@@ -1,58 +0,0 @@
-// #docplaster
-
-//#docregion
-import 'package:angular2/core.dart';
-import 'car/car.dart';
-import 'heroes/hero_service.dart';
-import 'heroes/hero_service_provider.dart';
-import 'logger_service.dart';
-import 'package:dependency_injection/heroes/hero.dart';
-
-//#docregion injector
-@Component(
- selector: 'my-injectors',
- template: '''
- Other Injections
- {{car.drive()}}
- {{hero.name}}
- {{rodent}}
- ''',
- providers: const [
- Car,
- Engine,
- Tires,
- const Provider(HeroService, useFactory: heroServiceFactory),
- Logger
- ])
-class InjectorComponent {
- Injector _injector;
-
- InjectorComponent(this._injector) {
- car = _injector.get(Car);
- heroService = _injector.get(HeroService);
- hero = heroService.getHeroes()[0];
- }
-
- Car car;
-
- //#docregion get-hero-service
- HeroService heroService;
-
- //#enddocregion get-hero-service
- Hero hero;
-
- String get rodent {
- var rous = _injector.getOptional(ROUS);
- if (rous != null) {
- throw new Exception('Aaaargh!');
- }
- return "R.O.U.S.'s? I don't think they exist!";
- }
-}
-//#enddocregion injector
-
-/**
- * R.O.U.S. - Rodents Of Unusual Size
- * // https://www.youtube.com/watch?v=BOv5ZjAOpC8
- */
-class ROUS {}
diff --git a/public/docs/_examples/dependency-injection/dart/lib/logger_service.dart b/public/docs/_examples/dependency-injection/dart/lib/logger_service.dart
deleted file mode 100644
index 452daefd22..0000000000
--- a/public/docs/_examples/dependency-injection/dart/lib/logger_service.dart
+++ /dev/null
@@ -1,13 +0,0 @@
-// #docregion
-
-import 'package:angular2/core.dart';
-
-@Injectable()
-class Logger {
- List logs = [];
-
- void log(String message) {
- logs.add(message);
- print(message);
- }
-}
diff --git a/public/docs/_examples/dependency-injection/dart/lib/providers_component.dart b/public/docs/_examples/dependency-injection/dart/lib/providers_component.dart
deleted file mode 100644
index 83d461deb2..0000000000
--- a/public/docs/_examples/dependency-injection/dart/lib/providers_component.dart
+++ /dev/null
@@ -1,360 +0,0 @@
-// Examples of provider arrays
-
-//#docplaster
-import 'package:angular2/core.dart';
-import 'app_config.dart';
-import 'heroes/hero_service_provider.dart';
-import 'heroes/hero_service.dart';
-import 'logger_service.dart';
-import 'user_service.dart';
-
-// #docregion import-optional
-import 'package:angular2/core.dart' show Optional;
-// #enddocregion import-optional
-
-const template = '{{log}}';
-
-//////////////////////////////////////////
-@Component(selector: 'provider-1', template: '{{log}}', providers:
-//#docregion providers-1
-const [Logger]
-//#enddocregion providers-1
-)
-class ProviderComponent1 {
- String log;
-
- ProviderComponent1(Logger logger) {
- logger.log('Hello from logger provided with Logger class');
- log = logger.logs[0];
- }
-}
-
-//////////////////////////////////////////
-@Component(selector: 'provider-2', template: '{{log}}', providers:
-//#docregion providers-2
-const [const Provider(Logger, useClass: Logger)]
-//#enddocregion providers-2
-)
-class ProviderComponent2 {
- String log;
-
- ProviderComponent2(Logger logger) {
- logger.log('Hello from logger provided with Provider class and useClass');
- log = logger.logs[0];
- }
-}
-
-//////////////////////////////////////////
-@Component(
- selector: 'provider-3',
- template: '{{log}}',
- providers: const [const Provider(Logger, useClass: Logger)]
-/*
-//#docregion providers-3
- const [provide(Logger, useClass: Logger)]
-//#enddocregion providers-3
-*/
-)
-class ProviderComponent3 {
- String log;
-
- ProviderComponent3(Logger logger) {
- logger.log('Hello from logger provided with useClass');
- log = logger.logs[0];
- }
-}
-
-//////////////////////////////////////////
-class BetterLogger extends Logger {}
-
-@Component(selector: 'provider-4', template: '{{log}}', providers:
-//#docregion providers-4
-const [const Provider(Logger, useClass: BetterLogger)]
-//#enddocregion providers-4
-)
-class ProviderComponent4 {
- String log;
-
- ProviderComponent4(Logger logger) {
- logger.log('Hello from logger provided with useClass:BetterLogger');
- log = logger.logs[0];
- }
-}
-//////////////////////////////////////////
-
-// #docregion EvenBetterLogger
-@Injectable()
-class EvenBetterLogger implements Logger {
- UserService _userService;
-
- List logs = [];
-
- EvenBetterLogger(this._userService);
-
- log(String message) {
- message = 'Message to ${ _userService.user.name}: ${ message}.';
- print(message);
- logs.add(message);
- }
-}
-
-// #enddocregion EvenBetterLogger
-@Component(selector: 'provider-5', template: '{{log}}', providers:
-//#docregion providers-5
-const [UserService, const Provider(Logger, useClass: EvenBetterLogger)]
-//#enddocregion providers-5
-)
-class ProviderComponent5 {
- String log;
-
- ProviderComponent5(Logger logger) {
- logger.log('Hello from EvenBetterlogger');
- log = logger.logs[0];
- }
-}
-
-//////////////////////////////////////////
-class NewLogger extends Logger implements OldLogger {}
-
-class OldLogger {
- List logs = [];
-
- log(String message) {
- throw new Exception('Should not call the old logger!');
- }
-}
-
-@Component(selector: 'provider-6a', template: '{{log}}', providers:
-//#docregion providers-6a
-const [
- NewLogger,
-// Not aliased! Creates two instances of `NewLogger`
- const Provider(OldLogger, useClass: NewLogger)
-]
-//#enddocregion providers-6a
-)
-class ProviderComponent6a {
- String log;
-
- ProviderComponent6a(NewLogger newLogger, OldLogger oldLogger) {
- if (identical(newLogger, oldLogger)) {
- throw new Exception('expected the two loggers to be different instances');
- }
- oldLogger.log('Hello OldLogger (but we want NewLogger)');
- // The newLogger wasn't called so no logs[]
-
- // display the logs of the oldLogger.
- log = newLogger.logs == null || newLogger.logs.isEmpty ? oldLogger.logs[0] : newLogger.logs[0];
- }
-}
-
-@Component(selector: 'provider-6b', template: '{{log}}', providers:
-//#docregion providers-6b
-const [
- NewLogger,
-// Alias OldLogger w/ reference to NewLogger
- const Provider(OldLogger, useExisting: NewLogger)
-//#enddocregion providers-6b
-])
-class ProviderComponent6b {
- String log;
-
- ProviderComponent6b(NewLogger newLogger, OldLogger oldLogger) {
- if (!identical(newLogger, oldLogger)) {
- throw new Exception('expected the two loggers to be the same instance');
- }
- oldLogger.log('Hello from NewLogger (via aliased OldLogger)');
- log = newLogger.logs[0];
- }
-}
-//////////////////////////////////////////
-
-// #docregion silent-logger
-
-// An object in the shape of the logger service
-class SilentLogger /*implements Logger*/ {
- const SilentLogger({this.logs});
-
- final List logs;
-
- log(String message) {}
-}
-
-const silentLogger = const SilentLogger(
- logs: const ['Silent logger says "Shhhhh!". Provided via "useValue"']);
-// #enddocregion silent-logger
-
-@Component(selector: 'provider-7', template: '{{log}}', providers:
-//#docregion providers-7
-const [const Provider(SilentLogger, useValue: silentLogger)]
-//#enddocregion providers-7
-/*
-//#docregion providers-7-unchecked
-const [const Provider(Logger, useValue: silentLogger)]
-//#enddocregion providers-7-unchecked
- */
-)
-class ProviderComponent7 {
- String log;
-
- ProviderComponent7(SilentLogger logger) {
- logger.log('Hello from logger provided with useValue');
- log = logger.logs[0];
- }
-}
-
-/////////////////
-@Component(selector: 'provider-8', template: '{{log}}', providers: const [
- const Provider(HeroService, useFactory: heroServiceFactory),
- Logger,
- UserService
-])
-class ProviderComponent8 {
- // #docregion provider-8-ctor
- ProviderComponent8(HeroService heroService);
-
- // #enddocregion provider-8-ctor
-
- // must be true else this component would have blown up at runtime
- var log = 'Hero service injected successfully';
-}
-
-/////////////////
-@Component(selector: 'provider-9a', template: '{{log}}', providers:
-/*
- // #docregion providers-9a-interface
- // WOKRKS! Can use abstract class as provider token
- [provide(Config, {useValue: CONFIG})]
- // #enddocregion providers-9a-interface
- */
-
-// #docregion providers-9a
-// Use string as provider token
-const [const Provider('app.config', useValue: CONFIG_HASH)]
-//#enddocregion providers-9a
-)
-class ProviderComponent9a implements OnInit {
- Config _config;
-
- String log;
-
- /*
- // #docregion provider-9a-ctor-interface
- // WORKS! Can inject using the abstract class as the parameter type
- Config _config;
-
- ProviderComponent9a(this._config);
- // #enddocregion provider-9a-ctor-interface
- */
-
- // #docregion provider-9a-ctor
-
- // @Inject(token) to inject the dependency
- ProviderComponent9a(@Inject('app.config') Map config) {
- _config = new ConfigImpl(apiEndpoint: config['apiEndpoint'], title: config['title']);
- }
-
- // #enddocregion provider-9a-ctor
- ngOnInit() {
- log = '\'app.config\' Application title is ' + _config.title;
- }
-}
-
-@Component(selector: 'provider-9b', template: '{{log}}', providers:
-// #docregion providers-9b
-const [const Provider(APP_CONFIG, useValue: CONFIG_HASH)]) // #enddocregion providers-9b
-class ProviderComponent9b
- implements OnInit {
- Config _config;
-
- String log;
-
- // #docregion provider-9b-ctor
- ProviderComponent9b(@Inject(APP_CONFIG) Map config) {
- _config = new ConfigImpl(apiEndpoint: config['apiEndpoint'], title: config['title']);
- }
-
- // #enddocregion provider-9b-ctor
- ngOnInit() {
- log = 'APP_CONFIG Application title is ' + _config.title;
- }
-}
-//////////////////////////////////////////
-
-// Normal required logger
-@Component(selector: 'provider-10a', template: '{{log}}',
-//#docregion providers-logger
- providers: const [Logger]
-//#enddocregion providers-logger
-)
-class ProviderComponent10a {
- String log;
-
- ProviderComponent10a(Logger logger) {
- logger.log('Hello from the required logger.');
- log = logger.logs[0];
- }
-}
-
-// Optional logger
-@Component(selector: 'provider-10b', template: '{{log}}')
-class ProviderComponent10b implements OnInit {
- Logger _logger;
-
- // #docregion provider-10-ctor
- String log;
-
- ProviderComponent10b(@Optional() this._logger);
-
- // #enddocregion provider-10-ctor
- ngOnInit() {
- // #docregion provider-10-logger
-
- // No logger? Make one!
- if (_logger == null) {
- _logger = new Logger();
- // #enddocregion provider-10-logger
- _logger.log('Optional logger was not available.');
- } else {
- _logger.log('Hello from the injected logger.');
- log = _logger.logs[0];
- }
- log = _logger.logs[0];
- }
-}
-
-/////////////////
-@Component(
- selector: 'my-providers',
- template: '''
- Provider variations
-
-
-
-
-
-
-
-
-
-
-
-
-
- ''',
- directives: const [
- ProviderComponent1,
- ProviderComponent2,
- ProviderComponent3,
- ProviderComponent4,
- ProviderComponent5,
- ProviderComponent6a,
- ProviderComponent6b,
- ProviderComponent7,
- ProviderComponent8,
- ProviderComponent9a,
- ProviderComponent9b,
- ProviderComponent10a,
- ProviderComponent10b
- ])
-class ProvidersComponent {}
diff --git a/public/docs/_examples/dependency-injection/dart/lib/user_service.dart b/public/docs/_examples/dependency-injection/dart/lib/user_service.dart
deleted file mode 100644
index 682a42b967..0000000000
--- a/public/docs/_examples/dependency-injection/dart/lib/user_service.dart
+++ /dev/null
@@ -1,27 +0,0 @@
-// #docregion
-
-import 'package:angular2/core.dart';
-
-@Injectable()
-class UserService {
- UserService() {
- user = _bob;
- }
-
- // Todo: get the user; don't 'new' it.
- User _alice = new User('Alice', true);
- User _bob = new User('Bob', false);
-
- // initial user is Bob
- User user;
-
- // swaps users
- User getNewUser() => user = user == _bob ? _alice : _bob;
-}
-
-class User {
- String name;
- bool isAuthorized;
-
- User(this.name, [this.isAuthorized = false]);
-}
diff --git a/public/docs/_examples/dependency-injection/dart/pubspec.yaml b/public/docs/_examples/dependency-injection/dart/pubspec.yaml
deleted file mode 100644
index fce5b7f954..0000000000
--- a/public/docs/_examples/dependency-injection/dart/pubspec.yaml
+++ /dev/null
@@ -1,18 +0,0 @@
-# #docregion
-name: dependency_injection
-description: Dependency injection sample
-version: 0.0.1
-environment:
- sdk: '>=1.13.0 <2.0.0'
-dependencies:
- angular2: 2.0.0-beta.8
- browser: ^0.10.0
- dart_to_js_script_rewriter: ^0.1.0
-transformers:
-- angular2:
- platform_directives: 'package:angular2/common.dart#COMMON_DIRECTIVES'
- platform_pipes: 'package:angular2/common.dart#COMMON_PIPES'
- entry_points: web/main.dart
-- dart_to_js_script_rewriter
-dev_dependencies:
- test: any
diff --git a/public/docs/_examples/dependency-injection/dart/test/hero_list_component_test.dart b/public/docs/_examples/dependency-injection/dart/test/hero_list_component_test.dart
deleted file mode 100644
index 0dd76b4f15..0000000000
--- a/public/docs/_examples/dependency-injection/dart/test/hero_list_component_test.dart
+++ /dev/null
@@ -1,34 +0,0 @@
-// A simple test
-// More details will be in the testing chapter.
-import 'package:angular2/angular2.dart';
-import 'package:dependency_injection/heroes/hero.dart';
-import 'package:dependency_injection/heroes/hero_list_component.dart';
-import 'package:dependency_injection/heroes/hero_service.dart';
-import 'package:test/test.dart';
-
-///////////////////////////////////////
-////#docregion spec
-List expectedHeroes = [
- new Hero()
- ..id = 1
- ..name = 'hero1',
- new Hero()
- ..id = 2
- ..name = 'hero2'
- ..isSecret = true
-];
-
-class HeroServiceMock implements HeroService {
- @override
- List getHeroes() => expectedHeroes;
-}
-
-var mockService = new HeroServiceMock();
-
-void main() {
- test('should have heroes when HeroListComponent created', () {
- var hlc = new HeroListComponent(mockService);
- expect(hlc.heroes.length, expectedHeroes.length);
- });
-}
-//#enddocregion spec
\ No newline at end of file
diff --git a/public/docs/_examples/dependency-injection/dart/web/index.html b/public/docs/_examples/dependency-injection/dart/web/index.html
deleted file mode 100644
index dd40fd6c61..0000000000
--- a/public/docs/_examples/dependency-injection/dart/web/index.html
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
- Dependency Injection
-
-
-
-
-
-Loading my-app ...
-Loading my-providers ...
-
-
-
diff --git a/public/docs/_examples/dependency-injection/dart/web/main.dart b/public/docs/_examples/dependency-injection/dart/web/main.dart
deleted file mode 100644
index 8e908cc892..0000000000
--- a/public/docs/_examples/dependency-injection/dart/web/main.dart
+++ /dev/null
@@ -1,12 +0,0 @@
-//#docregion
-
-import 'package:angular2/platform/browser.dart';
-import 'package:dependency_injection/app_component.dart';
-import 'package:dependency_injection/providers_component.dart';
-
-main() {
- //#docregion bootstrap
- bootstrap(AppComponent);
- //#enddocregion bootstrap
- bootstrap(ProvidersComponent);
-}
\ No newline at end of file
diff --git a/public/docs/_examples/dependency-injection/dart/web/main_1.dart b/public/docs/_examples/dependency-injection/dart/web/main_1.dart
deleted file mode 100644
index ff9166ccf1..0000000000
--- a/public/docs/_examples/dependency-injection/dart/web/main_1.dart
+++ /dev/null
@@ -1,10 +0,0 @@
-import 'package:angular2/platform/browser.dart';
-import 'package:dependency_injection/app_component.dart';
-import 'package:dependency_injection/heroes/hero_service.dart';
-//#docregion bootstrap
-
-main() {
-// Injecting services in bootstrap works but is discouraged
- bootstrap(AppComponent, [HeroService]);
-//#enddocregion bootstrap
-}
\ No newline at end of file
diff --git a/public/docs/_examples/dependency-injection/e2e-spec.js b/public/docs/_examples/dependency-injection/e2e-spec.js
deleted file mode 100644
index e5e146c158..0000000000
--- a/public/docs/_examples/dependency-injection/e2e-spec.js
+++ /dev/null
@@ -1,213 +0,0 @@
-
-describe('Dependency Injection Tests', function () {
-
-
- var expectedMsg;
-
- beforeAll(function () {
- browser.get('');
- });
-
- describe('Cars:', function() {
-
- it('DI car displays as expected', function () {
- expectedMsg = 'DI car with 4 cylinders and Flintstone tires.';
- expect(element(by.css('#di')).getText()).toEqual(expectedMsg);
- });
-
- it('No DI car displays as expected', function () {
- expectedMsg = 'No DI car with 4 cylinders and Flintstone tires.';
- expect(element(by.css('#nodi')).getText()).toEqual(expectedMsg);
- });
-
- it('Injector car displays as expected', function () {
- expectedMsg = 'Injector car with 4 cylinders and Flintstone tires.';
- expect(element(by.css('#injector')).getText()).toEqual(expectedMsg);
- });
-
- it('Factory car displays as expected', function () {
- expectedMsg = 'Factory car with 4 cylinders and Flintstone tires.';
- expect(element(by.css('#factory')).getText()).toEqual(expectedMsg);
- });
-
- it('Simple car displays as expected', function () {
- expectedMsg = 'Simple car with 4 cylinders and Flintstone tires.';
- expect(element(by.css('#simple')).getText()).toEqual(expectedMsg);
- });
-
- it('Super car displays as expected', function () {
- expectedMsg = 'Super car with 12 cylinders and Flintstone tires.';
- expect(element(by.css('#super')).getText()).toEqual(expectedMsg);
- });
-
- it('Test car displays as expected', function () {
- expectedMsg = 'Test car with 8 cylinders and YokoGoodStone tires.';
- expect(element(by.css('#test')).getText()).toEqual(expectedMsg);
- });
- });
-
- describe('Other Injections:', function() {
- it('DI car displays as expected', function () {
- expectedMsg = 'DI car with 4 cylinders and Flintstone tires.';
- expect(element(by.css('#car')).getText()).toEqual(expectedMsg);
- });
-
- it('Hero displays as expected', function () {
- expectedMsg = 'Mr. Nice';
- expect(element(by.css('#hero')).getText()).toEqual(expectedMsg);
- });
-
- it('Optional injection displays as expected', function () {
- expectedMsg = 'R.O.U.S.\'s? I don\'t think they exist!';
- expect(element(by.css('#rodent')).getText()).toEqual(expectedMsg);
- });
- });
-
- describe('Tests:', function() {
-
- it('Tests display as expected', function () {
- expectedMsg = /Tests passed/;
- expect(element(by.css('#tests')).getText()).toMatch(expectedMsg);
- });
-
- });
-
- describe('Provider variations:', function() {
-
- it('P1 (class) displays as expected', function () {
- expectedMsg = 'Hello from logger provided with Logger class';
- expect(element(by.css('#p1')).getText()).toEqual(expectedMsg);
- });
-
- it('P2 (Provider) displays as expected', function () {
- expectedMsg = 'Hello from logger provided with Provider class and useClass';
- expect(element(by.css('#p2')).getText()).toEqual(expectedMsg);
- });
-
- it('P3 (provide) displays as expected', function () {
- expectedMsg = 'Hello from logger provided with useClass';
- expect(element(by.css('#p3')).getText()).toEqual(expectedMsg);
- });
-
- it('P4 (useClass:BetterLogger) displays as expected', function () {
- expectedMsg = 'Hello from logger provided with useClass:BetterLogger';
- expect(element(by.css('#p4')).getText()).toEqual(expectedMsg);
- });
-
- it('P5 (useClass:EvenBetterLogger - dependency) displays as expected', function () {
- expectedMsg = 'Message to Bob: Hello from EvenBetterlogger.';
- expect(element(by.css('#p5')).getText()).toEqual(expectedMsg);
- });
-
- it('P6a (no alias) displays as expected', function () {
- expectedMsg = 'Hello OldLogger (but we want NewLogger)';
- expect(element(by.css('#p6a')).getText()).toEqual(expectedMsg);
- });
-
- it('P6b (alias) displays as expected', function () {
- expectedMsg = 'Hello from NewLogger (via aliased OldLogger)';
- expect(element(by.css('#p6b')).getText()).toEqual(expectedMsg);
- });
-
- it('P7 (useValue) displays as expected', function () {
- expectedMsg = 'Silent logger says "Shhhhh!". Provided via "useValue"';
- expect(element(by.css('#p7')).getText()).toEqual(expectedMsg);
- });
-
- it('P8 (useFactory) displays as expected', function () {
- expectedMsg = 'Hero service injected successfully';
- expect(element(by.css('#p8')).getText()).toEqual(expectedMsg);
- });
-
- it('P9a (string token) displays as expected', function () {
- expectedMsg = '"app.config" Application title is Dependency Injection';
- expect(element(by.css('#p9a')).getText()).toEqual(expectedMsg);
- });
-
- it('P9b (OpaqueToken) displays as expected', function () {
- expectedMsg = 'APP_CONFIG Application title is Dependency Injection';
- expect(element(by.css('#p9b')).getText()).toEqual(expectedMsg);
- });
-
- it('P10a (required dependency) displays as expected', function () {
- expectedMsg = 'Hello from the required logger.';
- expect(element(by.css('#p10a')).getText()).toEqual(expectedMsg);
- });
-
- it('P10b (optional dependency) displays as expected', function () {
- expectedMsg = 'Optional logger was not available.';
- expect(element(by.css('#p10b')).getText()).toEqual(expectedMsg);
- })
- });
-
- describe('User/Heroes:', function() {
- it('User is Bob - unauthorized', function () {
- expectedMsg = /Bob, is not authorized/;
- expect(element(by.css('#user')).getText()).toMatch(expectedMsg);
- });
-
- it('should have button', function () {
- expect(element.all(by.cssContainingText('button','Next User'))
- .get(0).isDisplayed()).toBe(true, "'Next User' button should be displayed");
- });
-
- it('unauthorized user should have multiple unauthorized heroes', function () {
- var heroes = element.all(by.css('#unauthorized hero-list div'));
- expect(heroes.count()).toBeGreaterThan(0);
- });
-
- it('unauthorized user should have no secret heroes', function () {
- var heroes = element.all(by.css('#unauthorized hero-list div'));
- expect(heroes.count()).toBeGreaterThan(0);
-
- heroes.filter(function(elem, index){
- return elem.getText().then(function(text) {
- return /secret/.test(text);
- });
- }).then(function(filteredElements) {
- //console.log("******Secret heroes count: "+filteredElements.length);
- expect(filteredElements.length).toEqual(0);
- });
- });
-
- it('unauthorized user should have no authorized heros listed', function () {
- expect(element.all(by.css('#authorized hero-list div')).count()).toEqual(0);
- });
-
- describe('after button click', function() {
-
- beforeAll(function (done) {
- var buttonEle = element.all(by.cssContainingText('button','Next User')).get(0);
- buttonEle.click().then(done,done);
- });
-
- it('User is Alice - authorized', function () {
- expectedMsg = /Alice, is authorized/;
- expect(element(by.css('#user')).getText()).toMatch(expectedMsg);
- });
-
- it('authorized user should have multiple authorized heroes ', function () {
- var heroes = element.all(by.css('#authorized hero-list div'));
- expect(heroes.count()).toBeGreaterThan(0);
- });
-
- it('authorized user should have secret heroes', function () {
- var heroes = element.all(by.css('#authorized hero-list div'));
- expect(heroes.count()).toBeGreaterThan(0);
-
- heroes.filter(function(elem, index){
- return elem.getText().then(function(text) {
- return /secret/.test(text);
- });
- }).then(function(filteredElements) {
- //console.log("******Secret heroes count: "+filteredElements.length);
- expect(filteredElements.length).toBeGreaterThan(0);
- });
- });
-
- it('authorized user should have no unauthorized heros listed', function () {
- expect(element.all(by.css('#unauthorized hero-list div')).count()).toEqual(0);
- });
- });
- });
-});
diff --git a/public/docs/_examples/dependency-injection/e2e-spec.ts b/public/docs/_examples/dependency-injection/e2e-spec.ts
new file mode 100644
index 0000000000..5b46dd77d9
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/e2e-spec.ts
@@ -0,0 +1,199 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by, ElementFinder } from 'protractor';
+
+describe('Dependency Injection Tests', function () {
+
+ let expectedMsg: string;
+ let expectedMsgRx: RegExp;
+
+ beforeAll(function () {
+ browser.get('');
+ });
+
+ describe('Cars:', function() {
+
+ it('DI car displays as expected', function () {
+ expectedMsg = 'DI car with 4 cylinders and Flintstone tires.';
+ expect(element(by.css('#di')).getText()).toEqual(expectedMsg);
+ });
+
+ it('No DI car displays as expected', function () {
+ expectedMsg = 'No DI car with 4 cylinders and Flintstone tires.';
+ expect(element(by.css('#nodi')).getText()).toEqual(expectedMsg);
+ });
+
+ it('Injector car displays as expected', function () {
+ expectedMsg = 'Injector car with 4 cylinders and Flintstone tires.';
+ expect(element(by.css('#injector')).getText()).toEqual(expectedMsg);
+ });
+
+ it('Factory car displays as expected', function () {
+ expectedMsg = 'Factory car with 4 cylinders and Flintstone tires.';
+ expect(element(by.css('#factory')).getText()).toEqual(expectedMsg);
+ });
+
+ it('Simple car displays as expected', function () {
+ expectedMsg = 'Simple car with 4 cylinders and Flintstone tires.';
+ expect(element(by.css('#simple')).getText()).toEqual(expectedMsg);
+ });
+
+ it('Super car displays as expected', function () {
+ expectedMsg = 'Super car with 12 cylinders and Flintstone tires.';
+ expect(element(by.css('#super')).getText()).toEqual(expectedMsg);
+ });
+
+ it('Test car displays as expected', function () {
+ expectedMsg = 'Test car with 8 cylinders and YokoGoodStone tires.';
+ expect(element(by.css('#test')).getText()).toEqual(expectedMsg);
+ });
+ });
+
+ describe('Other Injections:', function() {
+ it('DI car displays as expected', function () {
+ expectedMsg = 'DI car with 4 cylinders and Flintstone tires.';
+ expect(element(by.css('#car')).getText()).toEqual(expectedMsg);
+ });
+
+ it('Hero displays as expected', function () {
+ expectedMsg = 'Mr. Nice';
+ expect(element(by.css('#hero')).getText()).toEqual(expectedMsg);
+ });
+
+ it('Optional injection displays as expected', function () {
+ expectedMsg = 'R.O.U.S.\'s? I don\'t think they exist!';
+ expect(element(by.css('#rodent')).getText()).toEqual(expectedMsg);
+ });
+ });
+
+ describe('Tests:', function() {
+
+ it('Tests display as expected', function () {
+ expectedMsgRx = /Tests passed/;
+ expect(element(by.css('#tests')).getText()).toMatch(expectedMsgRx);
+ });
+
+ });
+
+ describe('Provider variations:', function() {
+
+ it('P1 (class) displays as expected', function () {
+ expectedMsg = 'Hello from logger provided with Logger class';
+ expect(element(by.css('#p1')).getText()).toEqual(expectedMsg);
+ });
+
+ it('P3 (provide) displays as expected', function () {
+ expectedMsg = 'Hello from logger provided with useClass:Logger';
+ expect(element(by.css('#p3')).getText()).toEqual(expectedMsg);
+ });
+
+ it('P4 (useClass:BetterLogger) displays as expected', function () {
+ expectedMsg = 'Hello from logger provided with useClass:BetterLogger';
+ expect(element(by.css('#p4')).getText()).toEqual(expectedMsg);
+ });
+
+ it('P5 (useClass:EvenBetterLogger - dependency) displays as expected', function () {
+ expectedMsg = 'Message to Bob: Hello from EvenBetterlogger';
+ expect(element(by.css('#p5')).getText()).toEqual(expectedMsg);
+ });
+
+ it('P6a (no alias) displays as expected', function () {
+ expectedMsg = 'Hello OldLogger (but we want NewLogger)';
+ expect(element(by.css('#p6a')).getText()).toEqual(expectedMsg);
+ });
+
+ it('P6b (alias) displays as expected', function () {
+ expectedMsg = 'Hello from NewLogger (via aliased OldLogger)';
+ expect(element(by.css('#p6b')).getText()).toEqual(expectedMsg);
+ });
+
+ it('P7 (useValue) displays as expected', function () {
+ expectedMsg = 'Silent logger says "Shhhhh!". Provided via "useValue"';
+ expect(element(by.css('#p7')).getText()).toEqual(expectedMsg);
+ });
+
+ it('P8 (useFactory) displays as expected', function () {
+ expectedMsg = 'Hero service injected successfully via heroServiceProvider';
+ expect(element(by.css('#p8')).getText()).toEqual(expectedMsg);
+ });
+
+ it('P9 (OpaqueToken) displays as expected', function () {
+ expectedMsg = 'APP_CONFIG Application title is Dependency Injection';
+ expect(element(by.css('#p9')).getText()).toEqual(expectedMsg);
+ });
+
+ it('P10 (optional dependency) displays as expected', function () {
+ expectedMsg = 'Optional logger was not available';
+ expect(element(by.css('#p10')).getText()).toEqual(expectedMsg);
+ });
+ });
+
+ describe('User/Heroes:', function() {
+ it('User is Bob - unauthorized', function () {
+ expectedMsgRx = /Bob, is not authorized/;
+ expect(element(by.css('#user')).getText()).toMatch(expectedMsgRx);
+ });
+
+ it('should have button', function () {
+ expect(element.all(by.cssContainingText('button', 'Next User'))
+ .get(0).isDisplayed()).toBe(true, '\'Next User\' button should be displayed');
+ });
+
+ it('unauthorized user should have multiple unauthorized heroes', function () {
+ let heroes = element.all(by.css('#unauthorized hero-list div'));
+ expect(heroes.count()).toBeGreaterThan(0);
+ });
+
+ it('unauthorized user should have no secret heroes', function () {
+ let heroes = element.all(by.css('#unauthorized hero-list div'));
+ expect(heroes.count()).toBeGreaterThan(0);
+
+ let filteredHeroes = heroes.filter((elem: ElementFinder, index: number) => {
+ return elem.getText().then((text: string) => {
+ return /secret/.test(text);
+ });
+ });
+
+ expect(filteredHeroes.count()).toEqual(0);
+ });
+
+ it('unauthorized user should have no authorized heroes listed', function () {
+ expect(element.all(by.css('#authorized hero-list div')).count()).toEqual(0);
+ });
+
+ describe('after button click', function() {
+
+ beforeAll(function (done: any) {
+ let buttonEle = element.all(by.cssContainingText('button', 'Next User')).get(0);
+ buttonEle.click().then(done, done);
+ });
+
+ it('User is Alice - authorized', function () {
+ expectedMsgRx = /Alice, is authorized/;
+ expect(element(by.css('#user')).getText()).toMatch(expectedMsgRx);
+ });
+
+ it('authorized user should have multiple authorized heroes ', function () {
+ let heroes = element.all(by.css('#authorized hero-list div'));
+ expect(heroes.count()).toBeGreaterThan(0);
+ });
+
+ it('authorized user should have secret heroes', function () {
+ let heroes = element.all(by.css('#authorized hero-list div'));
+ expect(heroes.count()).toBeGreaterThan(0);
+
+ let filteredHeroes = heroes.filter(function(elem: ElementFinder, index: number){
+ return elem.getText().then(function(text: string) {
+ return /secret/.test(text);
+ });
+ });
+
+ expect(filteredHeroes.count()).toBeGreaterThan(0);
+ });
+
+ it('authorized user should have no unauthorized heroes listed', function () {
+ expect(element.all(by.css('#unauthorized hero-list div')).count()).toEqual(0);
+ });
+ });
+ });
+});
diff --git a/public/docs/_examples/dependency-injection/ts/.gitignore b/public/docs/_examples/dependency-injection/ts/.gitignore
deleted file mode 100644
index 2cb7d2a2e9..0000000000
--- a/public/docs/_examples/dependency-injection/ts/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-**/*.js
diff --git a/public/docs/_examples/dependency-injection/ts/app/app.component.1.ts b/public/docs/_examples/dependency-injection/ts/app/app.component.1.ts
deleted file mode 100644
index 480765e870..0000000000
--- a/public/docs/_examples/dependency-injection/ts/app/app.component.1.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-// Early versions
-
-// #docregion
-import {Component} from 'angular2/core';
-import {CarComponent} from './car/car.component';
-import {HeroesComponent} from './heroes/heroes.component.1';
-
-@Component({
- selector: 'my-app',
- template: `
- {{title}}
-
-
- `,
- directives:[CarComponent, HeroesComponent]
-})
-
-export class AppComponent {
- title = 'Dependency Injection';
-}
-// #enddocregion
-
-
-/*
-//#docregion ctor-di-fail
-// FAIL! Injectable `config` is not a class!
-constructor(heroService: HeroService, config: config) {
- this.title = config.title;
-}
-//#enddocregion ctor-di-fail
-*/
diff --git a/public/docs/_examples/dependency-injection/ts/app/app.component.2.ts b/public/docs/_examples/dependency-injection/ts/app/app.component.2.ts
deleted file mode 100644
index e935f4c6e1..0000000000
--- a/public/docs/_examples/dependency-injection/ts/app/app.component.2.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-// #docregion
-// #docregion imports
-import {Component} from 'angular2/core';
-import {CarComponent} from './car/car.component';
-import {HeroesComponent} from './heroes/heroes.component.1';
-
-import {provide, Inject} from 'angular2/core';
-import {Config, CONFIG} from './app.config';
-import {Logger} from './logger.service';
-// #enddocregion imports
-
-@Component({
- selector: 'my-app',
- template: `
- {{title}}
-
-
- `,
- directives:[CarComponent, HeroesComponent],
-// #docregion providers
- providers: [
- Logger,
- // #docregion provider-config
- provide('app.config', {useValue: CONFIG})
- // #enddocregion provider-config
- ]
-// #docregion providers
-})
-export class AppComponent {
- title:string;
-
- // #docregion ctor
- constructor(@Inject('app.config') config:Config) {
-
- this.title = config.title;
- }
- // #docregion ctor
-}
-// #enddocregion
diff --git a/public/docs/_examples/dependency-injection/ts/app/app.component.ts b/public/docs/_examples/dependency-injection/ts/app/app.component.ts
deleted file mode 100644
index ef81e0630c..0000000000
--- a/public/docs/_examples/dependency-injection/ts/app/app.component.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-// #docplaster
-// #docregion
-// #docregion imports
-import {Component, Inject, provide} from 'angular2/core';
-
-import {CarComponent} from './car/car.component';
-import {HeroesComponent} from './heroes/heroes.component';
-
-import {APP_CONFIG,
- Config, CONFIG} from './app.config';
-import {Logger} from './logger.service';
-
-import {User, UserService} from './user.service';
-// #enddocregion imports
-import {InjectorComponent} from './injector.component';
-import {TestComponent} from './test.component';
-import {ProvidersComponent} from './providers.component';
-
-@Component({
- selector: 'my-app',
- template: `
- {{title}}
-
-
-
- User
-
- {{userInfo}}
- Next User
-
-
-
- `,
- directives:[CarComponent, HeroesComponent,
- InjectorComponent, TestComponent, ProvidersComponent],
-// #docregion providers
- providers: [
- Logger,
- UserService,
- provide(APP_CONFIG, {useValue: CONFIG})
- ]
-// #enddocregion providers
-})
-export class AppComponent {
- title:string;
-
- //#docregion ctor
- constructor(
- @Inject(APP_CONFIG) config:Config,
- private _userService: UserService) {
-
- this.title = config.title;
- }
- // #enddocregion ctor
-
- get isAuthorized() { return this.user.isAuthorized;}
- nextUser() { this._userService.getNewUser(); }
- get user() { return this._userService.user; }
-
- get userInfo() {
- return `Current user, ${this.user.name}, is `+
- `${this.isAuthorized ? '' : 'not'} authorized. `;
- }
-}
-// #enddocregion
diff --git a/public/docs/_examples/dependency-injection/ts/app/app.config.ts b/public/docs/_examples/dependency-injection/ts/app/app.config.ts
deleted file mode 100644
index 39f304d31a..0000000000
--- a/public/docs/_examples/dependency-injection/ts/app/app.config.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-//#docregion
-// #docregion token
-import {OpaqueToken} from 'angular2/core';
-
-export let APP_CONFIG = new OpaqueToken('app.config');
-// #enddocregion token
-
-//#docregion config
-export interface Config {
- apiEndpoint: string,
- title: string
-}
-
-export const CONFIG:Config = {
- apiEndpoint: 'api.heroes.com',
- title: 'Dependency Injection'
-};
-//#enddocregion config
\ No newline at end of file
diff --git a/public/docs/_examples/dependency-injection/ts/app/car/car-creations.ts b/public/docs/_examples/dependency-injection/ts/app/car/car-creations.ts
deleted file mode 100644
index b6e56b85eb..0000000000
--- a/public/docs/_examples/dependency-injection/ts/app/car/car-creations.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-// Examples with car and engine variations
-
-// #docplaster
-import {Car, Engine, Tires} from './car';
-
-///////// example 1 ////////////
-export function simpleCar() {
- //#docregion car-ctor-instantiation
- // Simple car with 4 cylinders and Flintstone tires.
- var car = new Car(new Engine(), new Tires());
- //#enddocregion car-ctor-instantiation
- car.description = 'Simple';
- return car;
-}
-
-
-///////// example 2 ////////////
-//#docregion car-ctor-instantiation-with-param
- class Engine2 {
- constructor(public cylinders: number) { }
- }
-//#enddocregion car-ctor-instantiation-with-param
-export function superCar() {
-//#docregion car-ctor-instantiation-with-param
- // Super car with 12 cylinders and Flintstone tires.
- var bigCylinders = 12;
- var car = new Car(new Engine2(bigCylinders), new Tires());
-//#enddocregion car-ctor-instantiation-with-param
- car.description = 'Super';
- return car;
-}
-
-/////////// example 3 //////////
- //#docregion car-ctor-instantiation-with-mocks
- class MockEngine extends Engine { cylinders = 8; }
- class MockTires extends Tires { make = "YokoGoodStone"; }
-
- //#enddocregion car-ctor-instantiation-with-mocks
-export function testCar() {
- //#docregion car-ctor-instantiation-with-mocks
- // Test car with 8 cylinders and YokoGoodStone tires.
- var car = new Car(new MockEngine(), new MockTires());
- //#enddocregion car-ctor-instantiation-with-mocks
- car.description = 'Test';
- return car;
-}
diff --git a/public/docs/_examples/dependency-injection/ts/app/car/car-injector.ts b/public/docs/_examples/dependency-injection/ts/app/car/car-injector.ts
deleted file mode 100644
index a94202585c..0000000000
--- a/public/docs/_examples/dependency-injection/ts/app/car/car-injector.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-// #docplaster
-//#docregion
-import { Injector } from 'angular2/core';
-
-import {Car, Engine, Tires} from './car';
-import {Logger} from '../logger.service';
-
-//#docregion injector
-export function useInjector() {
- var injector:Injector;
-
-//#enddocregion injector
-/*
-//#docregion injector-no-new
- // Cannot 'new' an Injector like this!
- var injector = new Injector([Car, Engine, Tires, Logger]);
-//#enddocregion injector-no-new
-*/
-
-//#docregion injector
- //#docregion injector-create-and-call
- injector = Injector.resolveAndCreate([Car, Engine, Tires, Logger]);
- //#docregion injector-call
- var car = injector.get(Car);
- //#enddocregion injector-call
- //#enddocregion injector-create-and-call
- car.description = 'Injector';
-
- var logger = injector.get(Logger);
- logger.log('Injector car.drive() said: '+car.drive());
-
- return car;
-}
-//#enddocregion injector
-
-
-//#enddocregion
diff --git a/public/docs/_examples/dependency-injection/ts/app/car/car-no-di.ts b/public/docs/_examples/dependency-injection/ts/app/car/car-no-di.ts
deleted file mode 100644
index 9556bffcab..0000000000
--- a/public/docs/_examples/dependency-injection/ts/app/car/car-no-di.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-// Car without DI
-import {Engine, Tires} from './car';
-
-//#docregion car
-export class Car {
-
- //#docregion car-ctor
- public engine: Engine;
- public tires: Tires;
- public description = 'No DI';
-
- constructor() {
- this.engine = new Engine();
- this.tires = new Tires();
- }
- //#enddocregion car-ctor
-
- // Method using the engine and tires
- drive() {
- return `${this.description} car with ` +
- `${this.engine.cylinders} cylinders and ${this.tires.make} tires.`
- }
-}
-//#enddocregion car
\ No newline at end of file
diff --git a/public/docs/_examples/dependency-injection/ts/app/car/car.ts b/public/docs/_examples/dependency-injection/ts/app/car/car.ts
deleted file mode 100644
index e80483ed55..0000000000
--- a/public/docs/_examples/dependency-injection/ts/app/car/car.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-// #docregion
-import {Injectable} from 'angular2/core';
-
-// #docregion engine
-export class Engine {
- public cylinders = 4; // default
-}
-// #enddocregion engine
-
-// #docregion tires
-export class Tires {
- public make = 'Flintstone';
- public model = 'Square';
-}
-// #enddocregion tires
-
-@Injectable()
-// #docregion car
-export class Car {
- //#docregion car-ctor
- public description = 'DI';
-
- constructor(public engine: Engine, public tires: Tires) { }
- // #enddocregion car-ctor
-
- // Method using the engine and tires
- drive() {
- return `${this.description} car with ` +
- `${this.engine.cylinders} cylinders and ${this.tires.make} tires.`
- }
-}
-// #enddocregion car
diff --git a/public/docs/_examples/dependency-injection/ts/app/heroes/hero-list.component.1.ts b/public/docs/_examples/dependency-injection/ts/app/heroes/hero-list.component.1.ts
deleted file mode 100644
index f82ced305d..0000000000
--- a/public/docs/_examples/dependency-injection/ts/app/heroes/hero-list.component.1.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-// #docregion
-import { Component } from 'angular2/core';
-import { Hero } from './hero';
-import { HEROES } from './mock-heroes';
-
-@Component({
- selector: 'hero-list',
- template: `
-
- {{hero.id}} - {{hero.name}}
-
- `,
-})
-export class HeroListComponent {
- heroes = HEROES;
-}
diff --git a/public/docs/_examples/dependency-injection/ts/app/heroes/hero-list.component.2.ts b/public/docs/_examples/dependency-injection/ts/app/heroes/hero-list.component.2.ts
deleted file mode 100644
index 4c78e6a190..0000000000
--- a/public/docs/_examples/dependency-injection/ts/app/heroes/hero-list.component.2.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-// #docregion
-import { Component } from 'angular2/core';
-import { Hero } from './hero';
-import { HeroService } from './hero.service';
-
-@Component({
- selector: 'hero-list',
- template: `
-
- {{hero.id}} - {{hero.name}}
-
- `,
-})
-export class HeroListComponent {
- heroes: Hero[];
-
- //#docregion ctor
- constructor(heroService: HeroService) {
- this.heroes = heroService.getHeroes();
- }
- //#enddocregion ctor
-}
diff --git a/public/docs/_examples/dependency-injection/ts/app/heroes/hero-list.component.ts b/public/docs/_examples/dependency-injection/ts/app/heroes/hero-list.component.ts
deleted file mode 100644
index b244d6d38c..0000000000
--- a/public/docs/_examples/dependency-injection/ts/app/heroes/hero-list.component.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-// #docregion
-import { Component } from 'angular2/core';
-import { Hero } from './hero';
-import { HeroService } from './hero.service';
-
-@Component({
- selector: 'hero-list',
- template: `
-
- {{hero.id}} - {{hero.name}}
- ({{hero.isSecret ? 'secret' : 'public'}})
-
- `,
-})
-export class HeroListComponent {
- heroes: Hero[];
-
- //#docregion ctor-signature
- constructor(heroService: HeroService) {
- //#enddocregion ctor-signature
- this.heroes = heroService.getHeroes();
- }
-}
diff --git a/public/docs/_examples/dependency-injection/ts/app/heroes/hero.service.1.ts b/public/docs/_examples/dependency-injection/ts/app/heroes/hero.service.1.ts
deleted file mode 100644
index ae962bd9b6..0000000000
--- a/public/docs/_examples/dependency-injection/ts/app/heroes/hero.service.1.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// #docregion
-import {Hero} from './hero';
-import {HEROES} from './mock-heroes';
-
-export class HeroService {
- getHeroes() { return HEROES; }
-}
diff --git a/public/docs/_examples/dependency-injection/ts/app/heroes/hero.service.2.ts b/public/docs/_examples/dependency-injection/ts/app/heroes/hero.service.2.ts
deleted file mode 100644
index d0737bb611..0000000000
--- a/public/docs/_examples/dependency-injection/ts/app/heroes/hero.service.2.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-// #docregion
-import {Injectable} from 'angular2/core';
-import {Hero} from './hero';
-import {HEROES} from './mock-heroes';
-import {Logger} from '../logger.service';
-
-@Injectable()
-export class HeroService {
-
- //#docregion ctor
- constructor(private _logger: Logger) { }
- //#enddocregion ctor
-
- getHeroes() {
- this._logger.log('Getting heroes ...')
- return HEROES;
- }
-}
diff --git a/public/docs/_examples/dependency-injection/ts/app/heroes/hero.service.provider.ts b/public/docs/_examples/dependency-injection/ts/app/heroes/hero.service.provider.ts
deleted file mode 100644
index 9f259df0da..0000000000
--- a/public/docs/_examples/dependency-injection/ts/app/heroes/hero.service.provider.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-// #docregion
-import {provide} from 'angular2/core';
-import {HeroService} from './hero.service';
-import {Logger} from '../logger.service';
-import {UserService} from '../user.service';
-
-// #docregion factory
-let heroServiceFactory = (logger: Logger, userService: UserService) => {
- return new HeroService(logger, userService.user.isAuthorized);
-}
-// #enddocregion factory
-
-// #docregion provider
-export let heroServiceProvider =
- provide(HeroService, {
- useFactory: heroServiceFactory,
- deps: [Logger, UserService]
- });
-// #enddocregion provider
diff --git a/public/docs/_examples/dependency-injection/ts/app/heroes/hero.service.ts b/public/docs/_examples/dependency-injection/ts/app/heroes/hero.service.ts
deleted file mode 100644
index 0eaf72848b..0000000000
--- a/public/docs/_examples/dependency-injection/ts/app/heroes/hero.service.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-// #docregion
-import {Injectable} from 'angular2/core';
-import {Hero} from './hero';
-import {HEROES} from './mock-heroes';
-import {Logger} from '../logger.service';
-
-@Injectable()
-export class HeroService {
- private _user:string;
-
- // #docregion internals
- constructor(
- private _logger: Logger,
- private _isAuthorized: boolean) { }
-
- getHeroes() {
- let auth = this._isAuthorized ? 'authorized ': 'unauthorized';
- this._logger.log(`Getting heroes for ${auth} user.`);
- return HEROES.filter(hero => this._isAuthorized || !hero.isSecret);
- }
- // #enddocregion internals
-}
diff --git a/public/docs/_examples/dependency-injection/ts/app/heroes/heroes.component.1.ts b/public/docs/_examples/dependency-injection/ts/app/heroes/heroes.component.1.ts
deleted file mode 100644
index 86b8520140..0000000000
--- a/public/docs/_examples/dependency-injection/ts/app/heroes/heroes.component.1.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-// #docplaster
-// #docregion
-// #docregion v1
-import { Component } from 'angular2/core';
-import { HeroListComponent } from './hero-list.component';
-// #enddocregion v1
-import { HeroService } from './hero.service';
-// #docregion v1
-
-@Component({
- selector: 'my-heroes',
- template: `
- Heroes
-
- `,
- // #enddocregion v1
- // #docregion providers
- providers:[HeroService],
- // #enddocregion providers
-// #docregion v1
- directives:[HeroListComponent]
-})
-export class HeroesComponent { }
-// #enddocregion v1
diff --git a/public/docs/_examples/dependency-injection/ts/app/heroes/heroes.component.ts b/public/docs/_examples/dependency-injection/ts/app/heroes/heroes.component.ts
deleted file mode 100644
index e7b1bd741d..0000000000
--- a/public/docs/_examples/dependency-injection/ts/app/heroes/heroes.component.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-// #docregion
-import { Component } from 'angular2/core';
-import { HeroListComponent } from './hero-list.component';
-import { heroServiceProvider} from './hero.service.provider';
-
-@Component({
- selector: 'my-heroes',
- template: `
- Heroes
-
- `,
- providers:[heroServiceProvider],
- directives:[HeroListComponent]
-})
-export class HeroesComponent { }
diff --git a/public/docs/_examples/dependency-injection/ts/app/heroes/mock-heroes.ts b/public/docs/_examples/dependency-injection/ts/app/heroes/mock-heroes.ts
deleted file mode 100644
index 83726eb2f3..0000000000
--- a/public/docs/_examples/dependency-injection/ts/app/heroes/mock-heroes.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-// #docregion
-import { Hero } from './hero';
-
-export var HEROES: Hero[] = [
- { "id": 11, isSecret: false, "name": "Mr. Nice" },
- { "id": 12, isSecret: false, "name": "Narco" },
- { "id": 13, isSecret: false, "name": "Bombasto" },
- { "id": 14, isSecret: false, "name": "Celeritas" },
- { "id": 15, isSecret: false, "name": "Magneta" },
- { "id": 16, isSecret: false, "name": "RubberMan" },
- { "id": 17, isSecret: false, "name": "Dynama" },
- { "id": 18, isSecret: true, "name": "Dr IQ" },
- { "id": 19, isSecret: true, "name": "Magma" },
- { "id": 20, isSecret: true, "name": "Tornado" }
-];
diff --git a/public/docs/_examples/dependency-injection/ts/app/injector.component.ts b/public/docs/_examples/dependency-injection/ts/app/injector.component.ts
deleted file mode 100644
index 300eaee9d3..0000000000
--- a/public/docs/_examples/dependency-injection/ts/app/injector.component.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-// #docplaster
-//#docregion
-import {Component, Injector} from 'angular2/core';
-
-import {Car, Engine, Tires} from './car/car';
-import {HeroService} from './heroes/hero.service';
-import {heroServiceProvider} from './heroes/hero.service.provider';
-import {Logger} from './logger.service';
-
-//#docregion injector
-@Component({
- selector: 'my-injectors',
- template: `
- Other Injections
- {{car.drive()}}
- {{hero.name}}
- {{rodent}}
- `,
- providers: [Car, Engine, Tires,
- heroServiceProvider, Logger]
-})
-export class InjectorComponent {
- constructor(private _injector: Injector) { }
-
- car:Car = this._injector.get(Car);
-
- //#docregion get-hero-service
- heroService:HeroService = this._injector.get(HeroService);
- //#enddocregion get-hero-service
- hero = this.heroService.getHeroes()[0];
-
- get rodent() {
- let rous = this._injector.getOptional(ROUS);
- if (rous) {
- throw new Error('Aaaargh!')
- }
- return "R.O.U.S.'s? I don't think they exist!";
- }
-}
-//#enddocregion injector
-
-/**
- * R.O.U.S. - Rodents Of Unusual Size
- * // https://www.youtube.com/watch?v=BOv5ZjAOpC8
- */
-class ROUS { }
diff --git a/public/docs/_examples/dependency-injection/ts/app/logger.service.ts b/public/docs/_examples/dependency-injection/ts/app/logger.service.ts
deleted file mode 100644
index 4afbd04017..0000000000
--- a/public/docs/_examples/dependency-injection/ts/app/logger.service.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-// #docregion
-import {Injectable} from 'angular2/core';
-
-@Injectable()
-export class Logger {
- logs:string[] = []; // capture logs for testing
- log(message: string){
- this.logs.push(message);
- console.log(message);
- }
-}
diff --git a/public/docs/_examples/dependency-injection/ts/app/main.1.ts b/public/docs/_examples/dependency-injection/ts/app/main.1.ts
deleted file mode 100644
index a3eaa1245c..0000000000
--- a/public/docs/_examples/dependency-injection/ts/app/main.1.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import {bootstrap} from 'angular2/platform/browser';
-import {AppComponent} from './app.component';
-import {HeroService} from './heroes/hero.service';
-
-//#docregion bootstrap
-bootstrap(AppComponent,
- [HeroService]); // DISCOURAGED (but works)
-//#enddocregion bootstrap
diff --git a/public/docs/_examples/dependency-injection/ts/app/main.ts b/public/docs/_examples/dependency-injection/ts/app/main.ts
deleted file mode 100644
index 8470a28175..0000000000
--- a/public/docs/_examples/dependency-injection/ts/app/main.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-//#docregion
-import {bootstrap} from 'angular2/platform/browser';
-import {AppComponent} from './app.component';
-import {ProvidersComponent} from './providers.component';
-
-//#docregion bootstrap
-bootstrap(AppComponent);
-//#enddocregion bootstrap
-bootstrap(ProvidersComponent);
\ No newline at end of file
diff --git a/public/docs/_examples/dependency-injection/ts/app/providers.component.ts b/public/docs/_examples/dependency-injection/ts/app/providers.component.ts
deleted file mode 100644
index de698f70e9..0000000000
--- a/public/docs/_examples/dependency-injection/ts/app/providers.component.ts
+++ /dev/null
@@ -1,352 +0,0 @@
-// Examples of provider arrays
-//#docplaster
-import { Component, Host, Inject, Injectable,
- provide, Provider} from 'angular2/core';
-
-import { APP_CONFIG,
- Config, CONFIG } from './app.config';
-
-import { HeroService} from './heroes/hero.service';
-import { heroServiceProvider } from './heroes/hero.service.provider';
-import { Logger } from './logger.service';
-import { User, UserService } from './user.service';
-
-let template = '{{log}}';
-
-//////////////////////////////////////////
-@Component({
- selector: 'provider-1',
- template: template,
- providers:
- //#docregion providers-1
- [Logger]
- //#enddocregion providers-1
-})
-export class ProviderComponent1 {
- log:string;
- constructor(logger: Logger) {
- logger.log('Hello from logger provided with Logger class');
- this.log = logger.logs[0];
- }
-}
-
-//////////////////////////////////////////
-@Component({
- selector: 'provider-2',
- template: template,
- providers:
- //#docregion providers-2
- [new Provider(Logger, {useClass: Logger})]
- //#enddocregion providers-2
-})
-export class ProviderComponent2 {
- log:string;
- constructor(logger: Logger) {
- logger.log('Hello from logger provided with Provider class and useClass');
- this.log = logger.logs[0];
- }
-}
-
-//////////////////////////////////////////
-@Component({
- selector: 'provider-3',
- template: template,
- providers:
- //#docregion providers-3
- [provide(Logger, {useClass: Logger})]
- //#enddocregion providers-3
-})
-export class ProviderComponent3 {
- log:string;
- constructor(logger: Logger) {
- logger.log('Hello from logger provided with useClass');
- this.log = logger.logs[0];
- }
-}
-
-//////////////////////////////////////////
-class BetterLogger extends Logger {}
-
-@Component({
- selector: 'provider-4',
- template: template,
- providers:
- //#docregion providers-4
- [provide(Logger, {useClass: BetterLogger})]
- //#enddocregion providers-4
-})
-export class ProviderComponent4 {
- log:string;
- constructor(logger: Logger) {
- logger.log('Hello from logger provided with useClass:BetterLogger');
- this.log = logger.logs[0];
- }
-}
-
-//////////////////////////////////////////
-// #docregion EvenBetterLogger
-@Injectable()
-class EvenBetterLogger {
- logs:string[] = [];
-
- constructor(private _userService: UserService) { }
-
- log(message:string){
- message = `Message to ${this._userService.user.name}: ${message}.`;
- console.log(message);
- this.logs.push(message);
- }
-}
-// #enddocregion EvenBetterLogger
-
-@Component({
- selector: 'provider-5',
- template: template,
- providers:
- //#docregion providers-5
- [ UserService,
- provide(Logger, {useClass: EvenBetterLogger}) ]
- //#enddocregion providers-5
-})
-export class ProviderComponent5 {
- log:string;
- constructor(logger: Logger) {
- logger.log('Hello from EvenBetterlogger');
- this.log = logger.logs[0];
- }
-}
-
-//////////////////////////////////////////
-class NewLogger extends Logger {}
-class OldLogger {
- logs:string[] = [];
- log(message:string) {
- throw new Error('Should not call the old logger!')
- };
-}
-
-@Component({
- selector: 'provider-6a',
- template: template,
- providers:
- //#docregion providers-6a
- [ NewLogger,
- // Not aliased! Creates two instances of `NewLogger`
- provide(OldLogger, {useClass:NewLogger}) ]
- //#enddocregion providers-6a
-})
-export class ProviderComponent6a {
- log:string;
- constructor(newLogger:NewLogger, oldLogger: OldLogger) {
- if (newLogger === oldLogger){
- throw new Error('expected the two loggers to be different instances');
- }
- oldLogger.log('Hello OldLogger (but we want NewLogger)');
- // The newLogger wasn't called so no logs[]
- // display the logs of the oldLogger.
- this.log = newLogger.logs[0] || oldLogger.logs[0];
- }
-}
-
-@Component({
- selector: 'provider-6b',
- template: template,
- providers:
- //#docregion providers-6b
- [ NewLogger,
- // Alias OldLogger w/ reference to NewLogger
- provide(OldLogger, {useExisting: NewLogger}) ]
- //#enddocregion providers-6b
-})
-export class ProviderComponent6b {
- log:string;
- constructor(newLogger:NewLogger, oldLogger: OldLogger) {
- if (newLogger !== oldLogger){
- throw new Error('expected the two loggers to be the same instance');
- }
- oldLogger.log('Hello from NewLogger (via aliased OldLogger)');
- this.log = newLogger.logs[0];
- }
-}
-
-//////////////////////////////////////////
-// #docregion silent-logger
-// An object in the shape of the logger service
-let silentLogger = {
- logs: ['Silent logger says "Shhhhh!". Provided via "useValue"'],
- log: () => {}
-}
-// #enddocregion silent-logger
-
-@Component({
- selector: 'provider-7',
- template: template,
- providers:
- //#docregion providers-7
- [provide(Logger, {useValue: silentLogger})]
- //#enddocregion providers-7
-})
-export class ProviderComponent7 {
- log:string;
- constructor(logger: Logger) {
- logger.log('Hello from logger provided with useValue');
- this.log = logger.logs[0];
- }
-}
-/////////////////
-
-@Component({
- selector: 'provider-8',
- template: template,
- providers:[heroServiceProvider, Logger, UserService]
-})
-export class ProviderComponent8{
- // #docregion provider-8-ctor
- constructor(heroService: HeroService){ }
- // #enddocregion provider-8-ctor
-
- // must be true else this component would have blown up at runtime
- log = 'Hero service injected successfully'
-}
-
-/////////////////
-@Component({
- selector: 'provider-9a',
- template: template,
- providers:
- /*
- // #docregion providers-9a-interface
- // FAIL! Can't use interface as provider token
- [provide(Config, {useValue: CONFIG})]
- // #enddocregion providers-9a-interface
- */
- // #docregion providers-9a
- // Use string as provider token
- [provide('app.config', {useValue: CONFIG})]
- // #enddocregion providers-9a
-})
-export class ProviderComponent9a {
- log: string;
- /*
- // #docregion provider-9a-ctor-interface
- // FAIL! Can't inject using the interface as the parameter type
- constructor(private _config: Config){ }
- // #enddocregion provider-9a-ctor-interface
- */
-
- // #docregion provider-9a-ctor
- // @Inject(token) to inject the dependency
- constructor(@Inject('app.config') private _config: Config){ }
- // #enddocregion provider-9a-ctor
-
- ngOnInit() {
- this.log = '"app.config" Application title is ' + this._config.title;
- }
-}
-
-@Component({
- selector: 'provider-9b',
- template: template,
- // #docregion providers-9b
- providers:[provide(APP_CONFIG, {useValue: CONFIG})]
- // #enddocregion providers-9b
-})
-export class ProviderComponent9b {
- log: string;
- // #docregion provider-9b-ctor
- constructor(@Inject(APP_CONFIG) private _config: Config){ }
- // #enddocregion provider-9b-ctor
-
- ngOnInit() {
- this.log = 'APP_CONFIG Application title is ' + this._config.title;
- }
-}
-//////////////////////////////////////////
-// Normal required logger
-@Component({
- selector: 'provider-10a',
- template: template,
- //#docregion providers-logger
- providers: [Logger]
- //#enddocregion providers-logger
-})
-export class ProviderComponent10a {
- log:string;
- constructor(logger: Logger) {
- logger.log('Hello from the required logger.');
- this.log = logger.logs[0];
- }
-}
-
-// Optional logger
-// #docregion import-optional
-import {Optional} from 'angular2/core';
-// #enddocregion import-optional
-
-@Component({
- selector: 'provider-10b',
- template: template
-})
-export class ProviderComponent10b {
- // #docregion provider-10-ctor
- log:string;
- constructor(@Optional() private _logger:Logger) { }
- // #enddocregion provider-10-ctor
-
- ngOnInit() {
- // #docregion provider-10-logger
- // No logger? Make one!
- if (!this._logger) {
- this._logger = {
- log: (msg:string)=> this._logger.logs.push(msg),
- logs: []
- }
- // #enddocregion provider-10-logger
- this._logger.log("Optional logger was not available.")
- // #docregion provider-10-logger
- }
- // #enddocregion provider-10-logger
- else {
- this._logger.log('Hello from the injected logger.')
- this.log = this._logger.logs[0];
- }
- this.log = this._logger.logs[0];
- }
-}
-
-/////////////////
-@Component({
- selector: 'my-providers',
- template: `
- Provider variations
-
-
-
-
-
-
-
-
-
-
-
-
-
- `,
- directives:[
- ProviderComponent1,
- ProviderComponent2,
- ProviderComponent3,
- ProviderComponent4,
- ProviderComponent5,
- ProviderComponent6a,
- ProviderComponent6b,
- ProviderComponent7,
- ProviderComponent8,
- ProviderComponent9a,
- ProviderComponent9b,
- ProviderComponent10a,
- ProviderComponent10b,
- ],
-})
-export class ProvidersComponent { }
\ No newline at end of file
diff --git a/public/docs/_examples/dependency-injection/ts/app/test.component.ts b/public/docs/_examples/dependency-injection/ts/app/test.component.ts
deleted file mode 100644
index 6499edec65..0000000000
--- a/public/docs/_examples/dependency-injection/ts/app/test.component.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-// Simulate a simple test
-// Reader should look to the testing chapter for the real thing
-
-import {Component} from 'angular2/core';
-import { HeroService } from './heroes/hero.service';
-import { HeroListComponent } from './heroes/hero-list.component';
-
-@Component({
- selector: 'my-tests',
- template: `
- Tests
- Tests {{results.pass}}: {{results.message}}
- `
-})
-export class TestComponent {
- results = runTests();
-}
-
-/////////////////////////////////////
-function runTests() {
-
- //#docregion spec
- let expectedHeroes = [{name: 'A'}, {name: 'B'}]
- let mockService = {getHeroes: () => expectedHeroes }
-
- it("should have heroes when HeroListComponent created", () => {
- let hlc = new HeroListComponent(mockService);
- expect(hlc.heroes.length).toEqual(expectedHeroes.length);
- })
- //#enddocregion spec
-
- return testResults;
-}
-
-//////////////////////////////////
-// Fake Jasmine infrastructure
-var testName:string;
-var testResults: {pass:string; message:string};
-
-function expect(actual:any) {
- return {
- toEqual: function(expected:any){
- testResults = actual === expected?
- {pass:'passed', message: `${testName}`} :
- {pass:'failed', message: `${testName}; expected ${actual} to equal ${expected}.`};
- }
- }
-}
-
-function it(label:string, test: () => void) {
- testName = label;
- test();
-}
\ No newline at end of file
diff --git a/public/docs/_examples/dependency-injection/ts/app/user.service.ts b/public/docs/_examples/dependency-injection/ts/app/user.service.ts
deleted file mode 100644
index 1fd5b46516..0000000000
--- a/public/docs/_examples/dependency-injection/ts/app/user.service.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-// #docregion
-import {Injectable} from 'angular2/core';
-
-@Injectable()
-export class UserService {
- // Todo: get the user; don't 'new' it.
- private _alice = new User('Alice', true);
- private _bob = new User('Bob', false);
-
- // initial user is Bob
- user = this._bob;
-
- // swaps users
- getNewUser() {
- return this.user = this.user === this._bob ? this._alice : this._bob;
- }
-}
-
-export class User {
- constructor(
- public name:string,
- public isAuthorized:boolean = false) { }
-}
diff --git a/public/docs/_examples/dependency-injection/ts/index.html b/public/docs/_examples/dependency-injection/ts/index.html
deleted file mode 100644
index 04cc28901d..0000000000
--- a/public/docs/_examples/dependency-injection/ts/index.html
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
-
- Dependency Injection
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Loading my-app ...
- Loading my-providers ...
-
-
-
diff --git a/public/docs/_examples/dependency-injection/ts/plnkr.json b/public/docs/_examples/dependency-injection/ts/plnkr.json
index dff3dc4110..e8d1ab24b2 100644
--- a/public/docs/_examples/dependency-injection/ts/plnkr.json
+++ b/public/docs/_examples/dependency-injection/ts/plnkr.json
@@ -1,9 +1,10 @@
{
"description": "Dependency Injection",
+ "basePath": "src/",
"files":[
"!**/*.d.ts",
"!**/*.js",
"!**/*.[1,2].*"
],
"tags": ["dependency", "di"]
-}
\ No newline at end of file
+}
diff --git a/public/docs/_examples/dependency-injection/ts/src/app/app.component.1.ts b/public/docs/_examples/dependency-injection/ts/src/app/app.component.1.ts
new file mode 100644
index 0000000000..b398ebeb57
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/app/app.component.1.ts
@@ -0,0 +1,17 @@
+// Early versions
+
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ template: `
+ {{title}}
+
+
+ `
+})
+
+export class AppComponent {
+ title = 'Dependency Injection';
+}
diff --git a/public/docs/_examples/dependency-injection/ts/src/app/app.component.2.ts b/public/docs/_examples/dependency-injection/ts/src/app/app.component.2.ts
new file mode 100644
index 0000000000..d24df5568c
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/app/app.component.2.ts
@@ -0,0 +1,25 @@
+// #docregion
+// #docregion imports
+import { Component } from '@angular/core';
+import { Inject } from '@angular/core';
+
+import { APP_CONFIG, AppConfig } from './app.config';
+// #enddocregion imports
+
+@Component({
+ selector: 'my-app',
+ template: `
+ {{title}}
+
+
+ `
+})
+export class AppComponent {
+ title: string;
+
+ // #docregion ctor
+ constructor(@Inject(APP_CONFIG) config: AppConfig) {
+ this.title = config.title;
+ }
+ // #enddocregion ctor
+}
diff --git a/public/docs/_examples/dependency-injection/ts/src/app/app.component.ts b/public/docs/_examples/dependency-injection/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..3563fdc070
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/app/app.component.ts
@@ -0,0 +1,48 @@
+// #docplaster
+// #docregion
+// #docregion imports
+import { Component, Inject } from '@angular/core';
+
+import { APP_CONFIG, AppConfig } from './app.config';
+import { Logger } from './logger.service';
+import { UserService } from './user.service';
+// #enddocregion imports
+
+@Component({
+ selector: 'my-app',
+ template: `
+ {{title}}
+
+
+
+ User
+
+ {{userInfo}}
+ Next User
+
+
+
+
+ `,
+ providers: [Logger]
+})
+export class AppComponent {
+ title: string;
+
+ // #docregion ctor
+ constructor(
+ @Inject(APP_CONFIG) config: AppConfig,
+ private userService: UserService) {
+ this.title = config.title;
+ }
+ // #enddocregion ctor
+
+ get isAuthorized() { return this.user.isAuthorized; }
+ nextUser() { this.userService.getNewUser(); }
+ get user() { return this.userService.user; }
+
+ get userInfo() {
+ return `Current user, ${this.user.name}, is ` +
+ `${this.isAuthorized ? '' : 'not'} authorized. `;
+ }
+}
diff --git a/public/docs/_examples/dependency-injection/ts/src/app/app.config.ts b/public/docs/_examples/dependency-injection/ts/src/app/app.config.ts
new file mode 100644
index 0000000000..f224e6e1ab
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/app/app.config.ts
@@ -0,0 +1,16 @@
+// #docregion token
+import { InjectionToken } from '@angular/core';
+
+export let APP_CONFIG = new InjectionToken('app.config');
+// #enddocregion token
+
+// #docregion config
+export interface AppConfig {
+ apiEndpoint: string;
+ title: string;
+}
+
+export const HERO_DI_CONFIG: AppConfig = {
+ apiEndpoint: 'api.heroes.com',
+ title: 'Dependency Injection'
+};
diff --git a/public/docs/_examples/dependency-injection/ts/src/app/app.module.ts b/public/docs/_examples/dependency-injection/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..67ae8ae913
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/app/app.module.ts
@@ -0,0 +1,60 @@
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+import { AppComponent } from './app.component';
+import { CarComponent } from './car/car.component';
+import { HeroesComponent } from './heroes/heroes.component';
+import { HeroListComponent } from './heroes/hero-list.component';
+import { InjectorComponent } from './injector.component';
+import { TestComponent } from './test.component';
+import { APP_CONFIG, HERO_DI_CONFIG } from './app.config';
+import { UserService } from './user.service';
+import {
+ ProvidersComponent,
+ Provider1Component,
+ Provider3Component,
+ Provider4Component,
+ Provider5Component,
+ Provider6aComponent,
+ Provider6bComponent,
+ Provider7Component,
+ Provider8Component,
+ Provider9Component,
+ Provider10Component,
+} from './providers.component';
+
+// #docregion ngmodule
+@NgModule({
+ imports: [
+ BrowserModule
+ ],
+ declarations: [
+ AppComponent,
+ CarComponent,
+ HeroesComponent,
+ // #enddocregion ngmodule
+ HeroListComponent,
+ InjectorComponent,
+ TestComponent,
+ ProvidersComponent,
+ Provider1Component,
+ Provider3Component,
+ Provider4Component,
+ Provider5Component,
+ Provider6aComponent,
+ Provider6bComponent,
+ Provider7Component,
+ Provider8Component,
+ Provider9Component,
+ Provider10Component,
+ // #docregion ngmodule
+ ],
+ // #docregion ngmodule-providers
+ providers: [
+ UserService,
+ { provide: APP_CONFIG, useValue: HERO_DI_CONFIG }
+ ],
+ // #enddocregion ngmodule-providers
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/dependency-injection/ts/src/app/car/car-creations.ts b/public/docs/_examples/dependency-injection/ts/src/app/car/car-creations.ts
new file mode 100644
index 0000000000..c758c72951
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/app/car/car-creations.ts
@@ -0,0 +1,46 @@
+// Examples with car and engine variations
+
+// #docplaster
+import { Car, Engine, Tires } from './car';
+
+///////// example 1 ////////////
+export function simpleCar() {
+ // #docregion car-ctor-instantiation
+ // Simple car with 4 cylinders and Flintstone tires.
+ let car = new Car(new Engine(), new Tires());
+ // #enddocregion car-ctor-instantiation
+ car.description = 'Simple';
+ return car;
+}
+
+
+///////// example 2 ////////////
+// #docregion car-ctor-instantiation-with-param
+ class Engine2 {
+ constructor(public cylinders: number) { }
+ }
+// #enddocregion car-ctor-instantiation-with-param
+export function superCar() {
+// #docregion car-ctor-instantiation-with-param
+ // Super car with 12 cylinders and Flintstone tires.
+ let bigCylinders = 12;
+ let car = new Car(new Engine2(bigCylinders), new Tires());
+// #enddocregion car-ctor-instantiation-with-param
+ car.description = 'Super';
+ return car;
+}
+
+/////////// example 3 //////////
+ // #docregion car-ctor-instantiation-with-mocks
+ class MockEngine extends Engine { cylinders = 8; }
+ class MockTires extends Tires { make = 'YokoGoodStone'; }
+
+ // #enddocregion car-ctor-instantiation-with-mocks
+export function testCar() {
+ // #docregion car-ctor-instantiation-with-mocks
+ // Test car with 8 cylinders and YokoGoodStone tires.
+ let car = new Car(new MockEngine(), new MockTires());
+ // #enddocregion car-ctor-instantiation-with-mocks
+ car.description = 'Test';
+ return car;
+}
diff --git a/public/docs/_examples/dependency-injection/ts/app/car/car-factory.ts b/public/docs/_examples/dependency-injection/ts/src/app/car/car-factory.ts
similarity index 86%
rename from public/docs/_examples/dependency-injection/ts/app/car/car-factory.ts
rename to public/docs/_examples/dependency-injection/ts/src/app/car/car-factory.ts
index 6d869b6ee3..06daafe63b 100644
--- a/public/docs/_examples/dependency-injection/ts/app/car/car-factory.ts
+++ b/public/docs/_examples/dependency-injection/ts/src/app/car/car-factory.ts
@@ -1,5 +1,5 @@
// #docregion
-import {Engine, Tires, Car} from './car';
+import { Engine, Tires, Car } from './car';
// BAD pattern!
export class CarFactory {
diff --git a/public/docs/_examples/dependency-injection/ts/src/app/car/car-injector.ts b/public/docs/_examples/dependency-injection/ts/src/app/car/car-injector.ts
new file mode 100644
index 0000000000..4f7498ee4e
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/app/car/car-injector.ts
@@ -0,0 +1,27 @@
+import { ReflectiveInjector } from '@angular/core';
+
+import { Car, Engine, Tires } from './car';
+import { Logger } from '../logger.service';
+
+// #docregion injector
+export function useInjector() {
+ let injector: ReflectiveInjector;
+ // #enddocregion injector
+ /*
+ // #docregion injector-no-new
+ // Cannot instantiate an ReflectiveInjector like this!
+ let injector = new ReflectiveInjector([Car, Engine, Tires]);
+ // #enddocregion injector-no-new
+ */
+ // #docregion injector, injector-create-and-call
+ injector = ReflectiveInjector.resolveAndCreate([Car, Engine, Tires]);
+ // #docregion injector-call
+ let car = injector.get(Car);
+ // #enddocregion injector-call, injector-create-and-call
+ car.description = 'Injector';
+
+ injector = ReflectiveInjector.resolveAndCreate([Logger]);
+ let logger = injector.get(Logger);
+ logger.log('Injector car.drive() said: ' + car.drive());
+ return car;
+}
diff --git a/public/docs/_examples/dependency-injection/ts/src/app/car/car-no-di.ts b/public/docs/_examples/dependency-injection/ts/src/app/car/car-no-di.ts
new file mode 100644
index 0000000000..9026edebc2
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/app/car/car-no-di.ts
@@ -0,0 +1,24 @@
+// Car without DI
+import { Engine, Tires } from './car';
+
+// #docregion car
+export class Car {
+
+ // #docregion car-ctor
+ public engine: Engine;
+ public tires: Tires;
+ public description = 'No DI';
+
+ constructor() {
+ this.engine = new Engine();
+ this.tires = new Tires();
+ }
+ // #enddocregion car-ctor
+
+ // Method using the engine and tires
+ drive() {
+ return `${this.description} car with ` +
+ `${this.engine.cylinders} cylinders and ${this.tires.make} tires.`;
+ }
+}
+// #enddocregion car
diff --git a/public/docs/_examples/dependency-injection/ts/app/car/car.component.ts b/public/docs/_examples/dependency-injection/ts/src/app/car/car.component.ts
similarity index 80%
rename from public/docs/_examples/dependency-injection/ts/app/car/car.component.ts
rename to public/docs/_examples/dependency-injection/ts/src/app/car/car.component.ts
index c66e0fbcce..9a835ef124 100644
--- a/public/docs/_examples/dependency-injection/ts/app/car/car.component.ts
+++ b/public/docs/_examples/dependency-injection/ts/src/app/car/car.component.ts
@@ -1,8 +1,9 @@
// #docregion
-import { Component, Injector} from 'angular2/core';
-import { Car, Engine, Tires } from './car';
-import { Car as CarNoDi } from './car-no-di';
-import { CarFactory} from './car-factory';
+import { Component } from '@angular/core';
+
+import { Car, Engine, Tires } from './car';
+import { Car as CarNoDi } from './car-no-di';
+import { CarFactory } from './car-factory';
import { testCar,
simpleCar,
@@ -26,12 +27,12 @@ import { useInjector } from './car-injector';
providers: [Car, Engine, Tires]
})
export class CarComponent {
- constructor(public car: Car) {}
-
factoryCar = (new CarFactory).createCar();
injectorCar = useInjector();
noDiCar = new CarNoDi;
simpleCar = simpleCar();
superCar = superCar();
testCar = testCar();
+
+ constructor(public car: Car) {}
}
diff --git a/public/docs/_examples/dependency-injection/ts/src/app/car/car.ts b/public/docs/_examples/dependency-injection/ts/src/app/car/car.ts
new file mode 100644
index 0000000000..37162c570b
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/app/car/car.ts
@@ -0,0 +1,25 @@
+import { Injectable } from '@angular/core';
+
+export class Engine {
+ public cylinders = 4;
+}
+
+export class Tires {
+ public make = 'Flintstone';
+ public model = 'Square';
+}
+
+@Injectable()
+export class Car {
+ // #docregion car-ctor
+ public description = 'DI';
+
+ constructor(public engine: Engine, public tires: Tires) { }
+ // #enddocregion car-ctor
+
+ // Method using the engine and tires
+ drive() {
+ return `${this.description} car with ` +
+ `${this.engine.cylinders} cylinders and ${this.tires.make} tires.`;
+ }
+}
diff --git a/public/docs/_examples/dependency-injection/ts/src/app/heroes/hero-list.component.1.ts b/public/docs/_examples/dependency-injection/ts/src/app/heroes/hero-list.component.1.ts
new file mode 100644
index 0000000000..ba32366aa9
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/app/heroes/hero-list.component.1.ts
@@ -0,0 +1,16 @@
+// #docregion
+import { Component } from '@angular/core';
+
+import { HEROES } from './mock-heroes';
+
+@Component({
+ selector: 'hero-list',
+ template: `
+
+ {{hero.id}} - {{hero.name}}
+
+ `
+})
+export class HeroListComponent {
+ heroes = HEROES;
+}
diff --git a/public/docs/_examples/dependency-injection/ts/src/app/heroes/hero-list.component.2.ts b/public/docs/_examples/dependency-injection/ts/src/app/heroes/hero-list.component.2.ts
new file mode 100644
index 0000000000..cb23d3257c
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/app/heroes/hero-list.component.2.ts
@@ -0,0 +1,31 @@
+// #docplaster
+// #docregion
+import { Component } from '@angular/core';
+
+import { Hero } from './hero';
+// #enddocregion
+import { HeroService } from './hero.service.1';
+/*
+// #docregion
+import { HeroService } from './hero.service';
+// #enddocregion
+*/
+// #docregion
+
+@Component({
+ selector: 'hero-list',
+ template: `
+
+ {{hero.id}} - {{hero.name}}
+
+ `
+})
+export class HeroListComponent {
+ heroes: Hero[];
+
+ // #docregion ctor
+ constructor(heroService: HeroService) {
+ this.heroes = heroService.getHeroes();
+ }
+ // #enddocregion ctor
+}
diff --git a/public/docs/_examples/dependency-injection/ts/src/app/heroes/hero-list.component.ts b/public/docs/_examples/dependency-injection/ts/src/app/heroes/hero-list.component.ts
new file mode 100644
index 0000000000..db3a325bdb
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/app/heroes/hero-list.component.ts
@@ -0,0 +1,26 @@
+/* tslint:disable:one-line */
+// #docregion
+import { Component } from '@angular/core';
+
+import { Hero } from './hero';
+import { HeroService } from './hero.service';
+
+@Component({
+ selector: 'hero-list',
+ template: `
+
+ {{hero.id}} - {{hero.name}}
+ ({{hero.isSecret ? 'secret' : 'public'}})
+
+ `,
+})
+export class HeroListComponent {
+ heroes: Hero[];
+
+ // #docregion ctor-signature
+ constructor(heroService: HeroService)
+ // #enddocregion ctor-signature
+ {
+ this.heroes = heroService.getHeroes();
+ }
+}
diff --git a/public/docs/_examples/dependency-injection/ts/src/app/heroes/hero.service.1.ts b/public/docs/_examples/dependency-injection/ts/src/app/heroes/hero.service.1.ts
new file mode 100644
index 0000000000..2e0e3ca734
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/app/heroes/hero.service.1.ts
@@ -0,0 +1,9 @@
+// #docregion
+import { Injectable } from '@angular/core';
+
+import { HEROES } from './mock-heroes';
+
+@Injectable()
+export class HeroService {
+ getHeroes() { return HEROES; }
+}
diff --git a/public/docs/_examples/dependency-injection/ts/src/app/heroes/hero.service.2.ts b/public/docs/_examples/dependency-injection/ts/src/app/heroes/hero.service.2.ts
new file mode 100644
index 0000000000..6b3a98306a
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/app/heroes/hero.service.2.ts
@@ -0,0 +1,18 @@
+// #docregion
+import { Injectable } from '@angular/core';
+
+import { HEROES } from './mock-heroes';
+import { Logger } from '../logger.service';
+
+@Injectable()
+export class HeroService {
+
+ // #docregion ctor
+ constructor(private logger: Logger) { }
+ // #enddocregion ctor
+
+ getHeroes() {
+ this.logger.log('Getting heroes ...');
+ return HEROES;
+ }
+}
diff --git a/public/docs/_examples/dependency-injection/ts/src/app/heroes/hero.service.provider.ts b/public/docs/_examples/dependency-injection/ts/src/app/heroes/hero.service.provider.ts
new file mode 100644
index 0000000000..6de4ebee90
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/app/heroes/hero.service.provider.ts
@@ -0,0 +1,19 @@
+/* tslint:disable:one-line */
+// #docregion
+import { HeroService } from './hero.service';
+import { Logger } from '../logger.service';
+import { UserService } from '../user.service';
+
+// #docregion factory
+let heroServiceFactory = (logger: Logger, userService: UserService) => {
+ return new HeroService(logger, userService.user.isAuthorized);
+};
+// #enddocregion factory
+
+// #docregion provider
+export let heroServiceProvider =
+ { provide: HeroService,
+ useFactory: heroServiceFactory,
+ deps: [Logger, UserService]
+ };
+// #enddocregion provider
diff --git a/public/docs/_examples/dependency-injection/ts/src/app/heroes/hero.service.ts b/public/docs/_examples/dependency-injection/ts/src/app/heroes/hero.service.ts
new file mode 100644
index 0000000000..fb03ec1de6
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/app/heroes/hero.service.ts
@@ -0,0 +1,20 @@
+// #docregion
+import { Injectable } from '@angular/core';
+
+import { HEROES } from './mock-heroes';
+import { Logger } from '../logger.service';
+
+@Injectable()
+export class HeroService {
+ // #docregion internals
+ constructor(
+ private logger: Logger,
+ private isAuthorized: boolean) { }
+
+ getHeroes() {
+ let auth = this.isAuthorized ? 'authorized ' : 'unauthorized';
+ this.logger.log(`Getting heroes for ${auth} user.`);
+ return HEROES.filter(hero => this.isAuthorized || !hero.isSecret);
+ }
+ // #enddocregion internals
+}
diff --git a/public/docs/_examples/dependency-injection/ts/app/heroes/hero.ts b/public/docs/_examples/dependency-injection/ts/src/app/heroes/hero.ts
similarity index 100%
rename from public/docs/_examples/dependency-injection/ts/app/heroes/hero.ts
rename to public/docs/_examples/dependency-injection/ts/src/app/heroes/hero.ts
diff --git a/public/docs/_examples/dependency-injection/ts/src/app/heroes/heroes.component.1.ts b/public/docs/_examples/dependency-injection/ts/src/app/heroes/heroes.component.1.ts
new file mode 100644
index 0000000000..e0e9deae08
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/app/heroes/heroes.component.1.ts
@@ -0,0 +1,21 @@
+// #docplaster
+// #docregion full, v1
+import { Component } from '@angular/core';
+// #enddocregion v1
+
+import { HeroService } from './hero.service';
+// #enddocregion full
+
+// #docregion full, v1
+
+@Component({
+ selector: 'my-heroes',
+ // #enddocregion v1
+ providers: [HeroService],
+ // #docregion v1
+ template: `
+ Heroes
+
+ `
+})
+export class HeroesComponent { }
diff --git a/public/docs/_examples/dependency-injection/ts/src/app/heroes/heroes.component.ts b/public/docs/_examples/dependency-injection/ts/src/app/heroes/heroes.component.ts
new file mode 100644
index 0000000000..5923f7590b
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/app/heroes/heroes.component.ts
@@ -0,0 +1,14 @@
+// #docregion
+import { Component } from '@angular/core';
+
+import { heroServiceProvider } from './hero.service.provider';
+
+@Component({
+ selector: 'my-heroes',
+ template: `
+ Heroes
+
+ `,
+ providers: [heroServiceProvider]
+})
+export class HeroesComponent { }
diff --git a/public/docs/_examples/dependency-injection/ts/src/app/heroes/mock-heroes.ts b/public/docs/_examples/dependency-injection/ts/src/app/heroes/mock-heroes.ts
new file mode 100644
index 0000000000..79a91dc03a
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/app/heroes/mock-heroes.ts
@@ -0,0 +1,15 @@
+// #docregion
+import { Hero } from './hero';
+
+export var HEROES: Hero[] = [
+ { id: 11, isSecret: false, name: 'Mr. Nice' },
+ { id: 12, isSecret: false, name: 'Narco' },
+ { id: 13, isSecret: false, name: 'Bombasto' },
+ { id: 14, isSecret: false, name: 'Celeritas' },
+ { id: 15, isSecret: false, name: 'Magneta' },
+ { id: 16, isSecret: false, name: 'RubberMan' },
+ { id: 17, isSecret: false, name: 'Dynama' },
+ { id: 18, isSecret: true, name: 'Dr IQ' },
+ { id: 19, isSecret: true, name: 'Magma' },
+ { id: 20, isSecret: true, name: 'Tornado' }
+];
diff --git a/public/docs/_examples/dependency-injection/ts/src/app/injector.component.ts b/public/docs/_examples/dependency-injection/ts/src/app/injector.component.ts
new file mode 100644
index 0000000000..1b1a065e4c
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/app/injector.component.ts
@@ -0,0 +1,49 @@
+// #docplaster
+// #docregion
+import { Component, Injector, OnInit } from '@angular/core';
+
+import { Car, Engine, Tires } from './car/car';
+import { Hero } from './heroes/hero';
+import { HeroService } from './heroes/hero.service';
+import { heroServiceProvider } from './heroes/hero.service.provider';
+import { Logger } from './logger.service';
+
+// #docregion injector
+@Component({
+ selector: 'my-injectors',
+ template: `
+ Other Injections
+ {{car.drive()}}
+ {{hero.name}}
+ {{rodent}}
+ `,
+ providers: [Car, Engine, Tires, heroServiceProvider, Logger]
+})
+export class InjectorComponent implements OnInit {
+ car: Car;
+
+ // #docregion get-hero-service
+ heroService: HeroService;
+ // #enddocregion get-hero-service
+ hero: Hero;
+
+ constructor(private injector: Injector) { }
+
+ ngOnInit() {
+ this.car = this.injector.get(Car);
+ this.heroService = this.injector.get(HeroService);
+ this.hero = this.heroService.getHeroes()[0];
+ }
+
+ get rodent() {
+ let rousDontExist = `R.O.U.S.'s? I don't think they exist!`;
+ return this.injector.get(ROUS, rousDontExist);
+ }
+}
+// #enddocregion injector
+
+/**
+ * R.O.U.S. - Rodents Of Unusual Size
+ * // https://www.youtube.com/watch?v=BOv5ZjAOpC8
+ */
+class ROUS { }
diff --git a/public/docs/_examples/dependency-injection/ts/src/app/logger.service.ts b/public/docs/_examples/dependency-injection/ts/src/app/logger.service.ts
new file mode 100644
index 0000000000..e943523ad2
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/app/logger.service.ts
@@ -0,0 +1,12 @@
+// #docregion
+import { Injectable } from '@angular/core';
+
+@Injectable()
+export class Logger {
+ logs: string[] = []; // capture logs for testing
+
+ log(message: string) {
+ this.logs.push(message);
+ console.log(message);
+ }
+}
diff --git a/public/docs/_examples/dependency-injection/ts/src/app/providers.component.ts b/public/docs/_examples/dependency-injection/ts/src/app/providers.component.ts
new file mode 100644
index 0000000000..a96bfce99e
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/app/providers.component.ts
@@ -0,0 +1,267 @@
+/* tslint:disable:one-line:check-open-brace*/
+// Examples of provider arrays
+// #docplaster
+import { Component, Inject, Injectable, OnInit } from '@angular/core';
+
+import { APP_CONFIG, AppConfig,
+ HERO_DI_CONFIG } from './app.config';
+
+import { HeroService } from './heroes/hero.service';
+import { heroServiceProvider } from './heroes/hero.service.provider';
+import { Logger } from './logger.service';
+import { UserService } from './user.service';
+
+let template = '{{log}}';
+
+//////////////////////////////////////////
+@Component({
+ selector: 'provider-1',
+ template: template,
+ // #docregion providers-1, providers-logger
+ providers: [Logger]
+ // #enddocregion providers-1, providers-logger
+})
+export class Provider1Component {
+ log: string;
+ constructor(logger: Logger) {
+ logger.log('Hello from logger provided with Logger class');
+ this.log = logger.logs[0];
+ }
+}
+
+//////////////////////////////////////////
+@Component({
+ selector: 'provider-3',
+ template: template,
+ providers:
+ // #docregion providers-3
+ [{ provide: Logger, useClass: Logger }]
+ // #enddocregion providers-3
+})
+export class Provider3Component {
+ log: string;
+ constructor(logger: Logger) {
+ logger.log('Hello from logger provided with useClass:Logger');
+ this.log = logger.logs[0];
+ }
+}
+
+//////////////////////////////////////////
+class BetterLogger extends Logger {}
+
+@Component({
+ selector: 'provider-4',
+ template: template,
+ providers:
+ // #docregion providers-4
+ [{ provide: Logger, useClass: BetterLogger }]
+ // #enddocregion providers-4
+})
+export class Provider4Component {
+ log: string;
+ constructor(logger: Logger) {
+ logger.log('Hello from logger provided with useClass:BetterLogger');
+ this.log = logger.logs[0];
+ }
+}
+
+//////////////////////////////////////////
+// #docregion EvenBetterLogger
+@Injectable()
+class EvenBetterLogger extends Logger {
+ constructor(private userService: UserService) { super(); }
+
+ log(message: string) {
+ let name = this.userService.user.name;
+ super.log(`Message to ${name}: ${message}`);
+ }
+}
+// #enddocregion EvenBetterLogger
+
+@Component({
+ selector: 'provider-5',
+ template: template,
+ providers:
+ // #docregion providers-5
+ [ UserService,
+ { provide: Logger, useClass: EvenBetterLogger }]
+ // #enddocregion providers-5
+})
+export class Provider5Component {
+ log: string;
+ constructor(logger: Logger) {
+ logger.log('Hello from EvenBetterlogger');
+ this.log = logger.logs[0];
+ }
+}
+
+//////////////////////////////////////////
+class NewLogger extends Logger {}
+class OldLogger {
+ logs: string[] = [];
+ log(message: string) {
+ throw new Error('Should not call the old logger!');
+ };
+}
+
+@Component({
+ selector: 'provider-6a',
+ template: template,
+ providers:
+ // #docregion providers-6a
+ [ NewLogger,
+ // Not aliased! Creates two instances of `NewLogger`
+ { provide: OldLogger, useClass: NewLogger}]
+ // #enddocregion providers-6a
+})
+export class Provider6aComponent {
+ log: string;
+ constructor(newLogger: NewLogger, oldLogger: OldLogger) {
+ if (newLogger === oldLogger){
+ throw new Error('expected the two loggers to be different instances');
+ }
+ oldLogger.log('Hello OldLogger (but we want NewLogger)');
+ // The newLogger wasn't called so no logs[]
+ // display the logs of the oldLogger.
+ this.log = newLogger.logs[0] || oldLogger.logs[0];
+ }
+}
+
+@Component({
+ selector: 'provider-6b',
+ template: template,
+ providers:
+ // #docregion providers-6b
+ [ NewLogger,
+ // Alias OldLogger w/ reference to NewLogger
+ { provide: OldLogger, useExisting: NewLogger}]
+ // #enddocregion providers-6b
+})
+export class Provider6bComponent {
+ log: string;
+ constructor(newLogger: NewLogger, oldLogger: OldLogger) {
+ if (newLogger !== oldLogger){
+ throw new Error('expected the two loggers to be the same instance');
+ }
+ oldLogger.log('Hello from NewLogger (via aliased OldLogger)');
+ this.log = newLogger.logs[0];
+ }
+}
+
+//////////////////////////////////////////
+// #docregion silent-logger
+// An object in the shape of the logger service
+let silentLogger = {
+ logs: ['Silent logger says "Shhhhh!". Provided via "useValue"'],
+ log: () => {}
+};
+// #enddocregion silent-logger
+
+@Component({
+ selector: 'provider-7',
+ template: template,
+ providers:
+ // #docregion providers-7
+ [{ provide: Logger, useValue: silentLogger }]
+ // #enddocregion providers-7
+})
+export class Provider7Component {
+ log: string;
+ constructor(logger: Logger) {
+ logger.log('Hello from logger provided with useValue');
+ this.log = logger.logs[0];
+ }
+}
+/////////////////
+
+@Component({
+ selector: 'provider-8',
+ template: template,
+ providers: [heroServiceProvider, Logger, UserService]
+})
+export class Provider8Component {
+ // must be true else this component would have blown up at runtime
+ log = 'Hero service injected successfully via heroServiceProvider';
+
+ // #docregion provider-8-ctor
+ constructor(heroService: HeroService) { }
+ // #enddocregion provider-8-ctor
+}
+
+/////////////////
+@Component({
+ selector: 'provider-9',
+ template: template,
+ /*
+ // #docregion providers-9-interface
+ // FAIL! Can't use interface as provider token
+ [{ provide: AppConfig, useValue: HERO_DI_CONFIG })]
+ // #enddocregion providers-9-interface
+ */
+ // #docregion providers-9
+ providers: [{ provide: APP_CONFIG, useValue: HERO_DI_CONFIG }]
+ // #enddocregion providers-9
+})
+export class Provider9Component implements OnInit {
+ log: string;
+ /*
+ // #docregion provider-9-ctor-interface
+ // FAIL! Can't inject using the interface as the parameter type
+ constructor(private config: AppConfig){ }
+ // #enddocregion provider-9-ctor-interface
+ */
+ // #docregion provider-9-ctor
+ constructor(@Inject(APP_CONFIG) private config: AppConfig) { }
+ // #enddocregion provider-9-ctor
+
+ ngOnInit() {
+ this.log = 'APP_CONFIG Application title is ' + this.config.title;
+ }
+}
+//////////////////////////////////////////
+// Sample providers 1 to 7 illustrate a required logger dependency.
+// Optional logger, can be null
+// #docregion import-optional
+import { Optional } from '@angular/core';
+// #enddocregion import-optional
+
+let some_message = 'Hello from the injected logger';
+
+@Component({
+ selector: 'provider-10',
+ template: template,
+ providers: [{ provide: Logger, useValue: null }]
+})
+export class Provider10Component implements OnInit {
+ log: string;
+ // #docregion provider-10-ctor
+ constructor(@Optional() private logger: Logger) {
+ if (this.logger) {
+ this.logger.log(some_message);
+ }
+ }
+ // #enddocregion provider-10-ctor
+
+ ngOnInit() {
+ this.log = this.logger ? this.logger.logs[0] : 'Optional logger was not available';
+ }
+}
+
+/////////////////
+@Component({
+ selector: 'my-providers',
+ template: `
+ Provider variations
+
+
+
+
+
+
+
+
+
+
+ `
+})
+export class ProvidersComponent { }
diff --git a/public/docs/_examples/dependency-injection/ts/src/app/test.component.ts b/public/docs/_examples/dependency-injection/ts/src/app/test.component.ts
new file mode 100644
index 0000000000..fc0fef75a8
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/app/test.component.ts
@@ -0,0 +1,55 @@
+/* tslint:disable */
+// Simulate a simple test
+// Reader should look to the testing chapter for the real thing
+
+import { Component } from '@angular/core';
+
+import { HeroService } from './heroes/hero.service';
+import { HeroListComponent } from './heroes/hero-list.component';
+
+@Component({
+ selector: 'my-tests',
+ template: `
+ Tests
+ Tests {{results.pass}}: {{results.message}}
+ `
+})
+export class TestComponent {
+ results = runTests();
+}
+
+/////////////////////////////////////
+function runTests() {
+
+ // #docregion spec
+ let expectedHeroes = [{name: 'A'}, {name: 'B'}]
+ let mockService = {getHeroes: () => expectedHeroes }
+
+ it('should have heroes when HeroListComponent created', () => {
+ let hlc = new HeroListComponent(mockService);
+ expect(hlc.heroes.length).toEqual(expectedHeroes.length);
+ });
+ // #enddocregion spec
+
+ return testResults;
+}
+
+//////////////////////////////////
+// Fake Jasmine infrastructure
+var testName: string;
+var testResults: {pass: string; message: string};
+
+function expect(actual: any) {
+ return {
+ toEqual: function(expected: any){
+ testResults = actual === expected ?
+ {pass: 'passed', message: testName} :
+ {pass: 'failed', message: `${testName}; expected ${actual} to equal ${expected}.`};
+ }
+ };
+}
+
+function it(label: string, test: () => void) {
+ testName = label;
+ test();
+}
diff --git a/public/docs/_examples/dependency-injection/ts/src/app/user.service.ts b/public/docs/_examples/dependency-injection/ts/src/app/user.service.ts
new file mode 100644
index 0000000000..8fdda925db
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/app/user.service.ts
@@ -0,0 +1,22 @@
+// #docregion
+import { Injectable } from '@angular/core';
+
+export class User {
+ constructor(
+ public name: string,
+ public isAuthorized = false) { }
+}
+
+// Todo: get the user; don't 'new' it.
+let alice = new User('Alice', true);
+let bob = new User('Bob', false);
+
+@Injectable()
+export class UserService {
+ user = bob; // initial user is Bob
+
+ // swap users
+ getNewUser() {
+ return this.user = this.user === bob ? alice : bob;
+ }
+}
diff --git a/public/docs/_examples/dependency-injection/ts/src/index.html b/public/docs/_examples/dependency-injection/ts/src/index.html
new file mode 100644
index 0000000000..87a9d7e694
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/index.html
@@ -0,0 +1,27 @@
+
+
+
+
+ Dependency Injection
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading my-app ...
+
+
+
diff --git a/public/docs/_examples/dependency-injection/ts/src/main.ts b/public/docs/_examples/dependency-injection/ts/src/main.ts
new file mode 100644
index 0000000000..1a1d481719
--- /dev/null
+++ b/public/docs/_examples/dependency-injection/ts/src/main.ts
@@ -0,0 +1,6 @@
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module';
+
+// #docregion bootstrap
+platformBrowserDynamic().bootstrapModule(AppModule);
+// #enddocregion bootstrap
diff --git a/public/docs/_examples/deployment/ts/.gitignore b/public/docs/_examples/deployment/ts/.gitignore
new file mode 100644
index 0000000000..7f794a0b16
--- /dev/null
+++ b/public/docs/_examples/deployment/ts/.gitignore
@@ -0,0 +1 @@
+!systemjs.config.server.js
diff --git a/public/docs/_examples/upgrade/ts/typescript-conversion/app/css/.gitkeep b/public/docs/_examples/deployment/ts/example-config.json
similarity index 100%
rename from public/docs/_examples/upgrade/ts/typescript-conversion/app/css/.gitkeep
rename to public/docs/_examples/deployment/ts/example-config.json
diff --git a/public/docs/_examples/deployment/ts/src/app/app.component.ts b/public/docs/_examples/deployment/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..47731c13a4
--- /dev/null
+++ b/public/docs/_examples/deployment/ts/src/app/app.component.ts
@@ -0,0 +1,15 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ template: `
+ Simple Deployment
+
+ Crisis Center
+ Heroes
+
+
+ `
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/deployment/ts/src/app/app.module.ts b/public/docs/_examples/deployment/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..a885bc2918
--- /dev/null
+++ b/public/docs/_examples/deployment/ts/src/app/app.module.ts
@@ -0,0 +1,29 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { RouterModule, Routes } from '@angular/router';
+
+import { AppComponent } from './app.component';
+import { CrisisListComponent } from './crisis-list.component';
+import { HeroListComponent } from './hero-list.component';
+
+const appRoutes: Routes = [
+ { path: 'crisis-center', component: CrisisListComponent },
+ { path: 'heroes', component: HeroListComponent },
+
+ { path: '', redirectTo: '/heroes', pathMatch: 'full' }
+];
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ RouterModule.forRoot(appRoutes)
+ ],
+ declarations: [
+ AppComponent,
+ CrisisListComponent,
+ HeroListComponent
+ ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/deployment/ts/src/app/crisis-list.component.ts b/public/docs/_examples/deployment/ts/src/app/crisis-list.component.ts
new file mode 100644
index 0000000000..62ef9e7555
--- /dev/null
+++ b/public/docs/_examples/deployment/ts/src/app/crisis-list.component.ts
@@ -0,0 +1,9 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ template: `
+ CRISIS CENTER
+ Get your crisis here
`
+})
+export class CrisisListComponent { }
diff --git a/public/docs/_examples/deployment/ts/src/app/hero-list.component.ts b/public/docs/_examples/deployment/ts/src/app/hero-list.component.ts
new file mode 100644
index 0000000000..479f73b508
--- /dev/null
+++ b/public/docs/_examples/deployment/ts/src/app/hero-list.component.ts
@@ -0,0 +1,10 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ template: `
+ HEROES
+ Get your heroes here
+ `
+})
+export class HeroListComponent { }
diff --git a/public/docs/_examples/deployment/ts/src/index.html b/public/docs/_examples/deployment/ts/src/index.html
new file mode 100644
index 0000000000..770e64bc4d
--- /dev/null
+++ b/public/docs/_examples/deployment/ts/src/index.html
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+ Simple Deployment
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ loading...
+
+
+
diff --git a/public/docs/_examples/deployment/ts/src/main.ts b/public/docs/_examples/deployment/ts/src/main.ts
new file mode 100644
index 0000000000..6f82bbc745
--- /dev/null
+++ b/public/docs/_examples/deployment/ts/src/main.ts
@@ -0,0 +1,15 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app/app.module';
+
+// #docregion enableProdMode
+import { enableProdMode } from '@angular/core';
+
+// Enable production mode unless running locally
+if (!/localhost/.test(document.location.host)) {
+ enableProdMode();
+}
+// #enddocregion enableProdMode
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/deployment/ts/src/systemjs.config.server.js b/public/docs/_examples/deployment/ts/src/systemjs.config.server.js
new file mode 100644
index 0000000000..40c4426064
--- /dev/null
+++ b/public/docs/_examples/deployment/ts/src/systemjs.config.server.js
@@ -0,0 +1,46 @@
+// #docregion
+/**
+ * System configuration for deployment without installing node_modules
+ * Loads umd packages from the web instead
+ * Adjust as necessary for your application needs.
+ */
+(function (global) {
+ System.config({
+ // #docregion paths
+ paths: {
+ 'npm:': 'https://unpkg.com/' // path serves as alias
+ },
+ // #enddocregion paths
+ // map tells the System loader where to look for things
+ map: {
+ app: 'app', // location of transpiled app files
+
+ // angular minimized umd bundles
+ '@angular/core': 'npm:@angular/core/bundles/core.umd.min.js',
+ '@angular/common': 'npm:@angular/common/bundles/common.umd.min.js',
+ '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.min.js',
+ '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.min.js',
+ '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.min.js',
+ '@angular/http': 'npm:@angular/http/bundles/http.umd.min.js',
+ '@angular/router': 'npm:@angular/router/bundles/router.umd.min.js',
+ '@angular/router/upgrade': 'npm:@angular/router/bundles/router-upgrade.umd.min.js',
+ '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.min.js',
+ '@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.min.js',
+ '@angular/upgrade/static': 'npm:@angular/upgrade/bundles/upgrade-static.umd.min.js',
+
+ // other libraries
+ 'rxjs': 'npm:rxjs@5.0.1',
+ 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js'
+ },
+ // packages tells the System loader how to load when no filename and/or no extension
+ packages: {
+ app: {
+ main: './main.js',
+ defaultExtension: 'js'
+ },
+ rxjs: {
+ defaultExtension: 'js'
+ }
+ }
+ });
+ })(this);
diff --git a/public/docs/_examples/displaying-data/dart/lib/app_component.dart b/public/docs/_examples/displaying-data/dart/lib/app_component.dart
deleted file mode 100644
index 5374ba81a8..0000000000
--- a/public/docs/_examples/displaying-data/dart/lib/app_component.dart
+++ /dev/null
@@ -1,32 +0,0 @@
-// #docregion
-import 'package:angular2/angular2.dart';
-
-import 'hero.dart';
-
-final List _heroes = [
- new Hero(1, 'Windstorm'),
- new Hero(13, 'Bombasto'),
- new Hero(15, 'Magneta'),
- new Hero(20, 'Tornado')
-];
-
-@Component(
- selector: 'my-app',
- template: '''
-{{title}}
-My favorite hero is: {{myHero.name}}
-Heroes:
-
-// #docregion message
- 3">There are many heroes!
-// #enddocregion message
-''')
-class AppComponent {
- String title = 'Tour of Heroes';
- List heroes = _heroes;
- Hero myHero = _heroes[0];
-}
diff --git a/public/docs/_examples/displaying-data/dart/lib/app_component_1.dart b/public/docs/_examples/displaying-data/dart/lib/app_component_1.dart
deleted file mode 100644
index 1991a6645c..0000000000
--- a/public/docs/_examples/displaying-data/dart/lib/app_component_1.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// #docregion
-import 'package:angular2/angular2.dart';
-
-@Component(
- selector: 'my-app',
-// #docregion template
- template: '''
-{{title}}
-My favorite hero is: {{myHero}} '''
-// #enddocregion template
- )
-class AppComponent {
- String title = 'Tour of Heroes';
- String myHero = 'Windstorm';
-}
diff --git a/public/docs/_examples/displaying-data/dart/lib/app_component_2.dart b/public/docs/_examples/displaying-data/dart/lib/app_component_2.dart
deleted file mode 100644
index ff97982532..0000000000
--- a/public/docs/_examples/displaying-data/dart/lib/app_component_2.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-// #docregion
-import 'package:angular2/angular2.dart';
-
-// #docregion mock-heroes
-const List _heroes = const [
- 'Windstorm',
- 'Bombasto',
- 'Magneta',
- 'Tornado'
-];
-// #enddocregion mock-heroes
-
-@Component(
- selector: 'my-app',
-// #docregion template
- template: '''
-{{title}}
-My favorite hero is: {{myHero}}
-Heroes:
-
-// #docregion li-repeater
-
- {{ hero }}
-
-// #enddocregion li-repeater
- '''
-// #enddocregion template
- )
-// #docregion mock-heroes
-class AppComponent {
- String title = 'Tour of Heroes';
- List heroes = _heroes;
- String myHero = _heroes[0];
-}
-// #enddocregion mock-heroes
-// #enddocregion
diff --git a/public/docs/_examples/displaying-data/dart/lib/app_component_3.dart b/public/docs/_examples/displaying-data/dart/lib/app_component_3.dart
deleted file mode 100644
index 9a39808d18..0000000000
--- a/public/docs/_examples/displaying-data/dart/lib/app_component_3.dart
+++ /dev/null
@@ -1,35 +0,0 @@
-// #docregion
-import 'package:angular2/angular2.dart';
-// #docregion heroes
-import 'hero.dart';
-
-final List _heroes = [
- new Hero(1, 'Windstorm'),
- new Hero(13, 'Bombasto'),
- new Hero(15, 'Magneta'),
- new Hero(20, 'Tornado')
-];
-// #enddocregion heroes
-
-@Component(
- selector: 'my-app',
-// #docregion template
- template: '''
-{{title}}
-My favorite hero is: {{myHero.name}}
-Heroes:
-'''
-// #enddocregion template
- )
-// #docregion heroes
-class AppComponent {
- String title = 'Tour of Heroes';
- List heroes = _heroes;
- Hero myHero = _heroes[0];
-}
-// #enddocregion heroes
-// #enddocregion
diff --git a/public/docs/_examples/displaying-data/dart/lib/hero.dart b/public/docs/_examples/displaying-data/dart/lib/hero.dart
deleted file mode 100644
index 6542e4f4ca..0000000000
--- a/public/docs/_examples/displaying-data/dart/lib/hero.dart
+++ /dev/null
@@ -1,9 +0,0 @@
-// #docregion
-class Hero {
- int id;
- String name;
-
- Hero(this.id, this.name);
- String toString() => '$id: $name';
-}
-// #enddocregion
diff --git a/public/docs/_examples/displaying-data/dart/pubspec.yaml b/public/docs/_examples/displaying-data/dart/pubspec.yaml
deleted file mode 100644
index 279d82e35f..0000000000
--- a/public/docs/_examples/displaying-data/dart/pubspec.yaml
+++ /dev/null
@@ -1,15 +0,0 @@
-# #docregion
-name: displaying_data
-description: Displaying Data Example
-version: 0.0.1
-environment:
- sdk: '>=1.13.0 <2.0.0'
-dependencies:
- angular2: 2.0.0-beta.8
- browser: ^0.10.0
- dart_to_js_script_rewriter: ^0.1.0
-transformers:
-- angular2:
- platform_directives: 'package:angular2/common.dart#CORE_DIRECTIVES'
- entry_points: web/main.dart
-- dart_to_js_script_rewriter
diff --git a/public/docs/_examples/displaying-data/dart/web/index.html b/public/docs/_examples/displaying-data/dart/web/index.html
deleted file mode 100644
index 6585d21511..0000000000
--- a/public/docs/_examples/displaying-data/dart/web/index.html
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
- Displaying Data
-
-
-
-
-
-
- Loading...
-
-
-
diff --git a/public/docs/_examples/displaying-data/dart/web/main.dart b/public/docs/_examples/displaying-data/dart/web/main.dart
deleted file mode 100644
index 69650f0740..0000000000
--- a/public/docs/_examples/displaying-data/dart/web/main.dart
+++ /dev/null
@@ -1,20 +0,0 @@
-// #docplaster
-// #docregion final
-import 'package:angular2/bootstrap.dart';
-// #enddocregion final
-//import 'package:displaying_data/app_component_1.dart' as v1;
-//import 'package:displaying_data/app_component_2.dart' as v2;
-//import 'package:displaying_data/app_component_3.dart' as v3;
-// #docregion final
-import 'package:displaying_data/app_component.dart';
-
-main() {
-// #enddocregion final
-// pick one
-// bootstrap(v1.AppComponent);
-// bootstrap(v2.AppComponent);
-// bootstrap(v3.AppComponent);
-// #docregion final
- bootstrap(AppComponent);
-}
-// #enddocregion final
diff --git a/public/docs/_examples/displaying-data/e2e-spec.js b/public/docs/_examples/displaying-data/e2e-spec.js
deleted file mode 100644
index 4768050501..0000000000
--- a/public/docs/_examples/displaying-data/e2e-spec.js
+++ /dev/null
@@ -1,21 +0,0 @@
-describe('Displaying Data Tests', function () {
-
- var _title = "Tour of Heroes";
- var _defaultHero = 'Windstorm'
-
- beforeAll(function () {
- browser.get('');
- });
-
- it('should display correct title: ' + _title, function () {
- expect(element(by.css('h1')).getText()).toEqual(_title);
- });
-
- it('should have correct default hero: ' + _defaultHero, function () {
- expect(element(by.css('h2')).getText()).toContain(_defaultHero);
- });
-
- it('should have many heroes', function () {
- expect(element(by.css('ul ~ p')).getText()).toContain('There are many heroes!');
- });
-});
diff --git a/public/docs/_examples/displaying-data/e2e-spec.ts b/public/docs/_examples/displaying-data/e2e-spec.ts
new file mode 100644
index 0000000000..96c52c5d00
--- /dev/null
+++ b/public/docs/_examples/displaying-data/e2e-spec.ts
@@ -0,0 +1,29 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by } from 'protractor';
+
+describe('Displaying Data Tests', function () {
+ let _title = 'Tour of Heroes';
+ let _defaultHero = 'Windstorm';
+
+ beforeAll(function () {
+ browser.get('');
+ });
+
+ it('should display correct title: ' + _title, function () {
+ expect(element(by.css('h1')).getText()).toEqual(_title);
+ });
+
+ it('should have correct default hero: ' + _defaultHero, function () {
+ expect(element(by.css('h2')).getText()).toContain(_defaultHero);
+ });
+
+ it('should have heroes', function () {
+ let heroEls = element.all(by.css('li'));
+ expect(heroEls.count()).not.toBe(0, 'should have heroes');
+ });
+
+ it('should display "there are many heroes!"', function () {
+ expect(element(by.css('ul ~ p')).getText()).toContain('There are many heroes!');
+ });
+});
diff --git a/public/docs/_examples/displaying-data/ts/.gitignore b/public/docs/_examples/displaying-data/ts/.gitignore
deleted file mode 100644
index 2cb7d2a2e9..0000000000
--- a/public/docs/_examples/displaying-data/ts/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-**/*.js
diff --git a/public/docs/_examples/displaying-data/ts/app/app.component.1.ts b/public/docs/_examples/displaying-data/ts/app/app.component.1.ts
deleted file mode 100644
index 7b1d5b8cca..0000000000
--- a/public/docs/_examples/displaying-data/ts/app/app.component.1.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-// #docregion
-import {Component} from 'angular2/core';
-
-@Component({
- selector: 'my-app',
- // #docregion template
- template: `
- {{title}}
- My favorite hero is: {{myHero}}
- `
- // #enddocregion template
-})
-export class AppComponent {
- title = 'Tour of Heroes';
- myHero = 'Windstorm';
-}
diff --git a/public/docs/_examples/displaying-data/ts/app/app.component.2.ts b/public/docs/_examples/displaying-data/ts/app/app.component.2.ts
deleted file mode 100644
index ed30ee0ebc..0000000000
--- a/public/docs/_examples/displaying-data/ts/app/app.component.2.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-// #docregion
-import {Component} from 'angular2/core';
-
-@Component({
- selector: 'my-app',
- // #docregion template
- template: `
- {{title}}
- My favorite hero is: {{myHero}}
- Heroes:
-
- // #docregion li-repeater
-
- {{ hero }}
-
- // #enddocregion li-repeater
-
- `
- // #enddocregion template
-})
-// #docregion mock-heroes
-export class AppComponent {
- title = 'Tour of Heroes';
- heroes = ['Windstorm', 'Bombasto', 'Magneta', 'Tornado'];
- myHero = this.heroes[0];
-}
-// #enddocregion mock-heroes
-// #enddocregion
diff --git a/public/docs/_examples/displaying-data/ts/app/app.component.3.ts b/public/docs/_examples/displaying-data/ts/app/app.component.3.ts
deleted file mode 100644
index 79edbfdfae..0000000000
--- a/public/docs/_examples/displaying-data/ts/app/app.component.3.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-// #docregion
-import {Component} from 'angular2/core';
-// #docregion import-hero
-import {Hero} from './hero';
-// #enddocregion import-hero
-
-@Component({
- selector: 'my-app',
- // #docregion template
- template: `
- {{title}}
- My favorite hero is: {{myHero.name}}
- Heroes:
-
- `
- // #enddocregion template
-})
-// #docregion class
-export class AppComponent {
- title = 'Tour of Heroes';
- // #docregion heroes
- heroes = [
- new Hero(1, 'Windstorm'),
- new Hero(13, 'Bombasto'),
- new Hero(15, 'Magneta'),
- new Hero(20, 'Tornado')
- ];
- myHero = this.heroes[0];
- // #enddocregion heroes
-}
-// #enddocregion class
-// #enddocregion
diff --git a/public/docs/_examples/displaying-data/ts/app/app.component.ts b/public/docs/_examples/displaying-data/ts/app/app.component.ts
deleted file mode 100644
index a85a09081e..0000000000
--- a/public/docs/_examples/displaying-data/ts/app/app.component.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-// #docplaster
-// #docregion final
-// #docregion imports
-import {Component} from 'angular2/core';
-// #enddocregion imports
-import {Hero} from './hero'
-
-@Component({
- selector: 'my-app',
- template: `
- {{title}}
- My favorite hero is: {{myHero.name}}
- Heroes:
-
- // #docregion message
- 3">There are many heroes!
- // #enddocregion message
-`
-})
-
-export class AppComponent {
- title = 'Tour of Heroes';
- heroes = [
- new Hero(1, 'Windstorm'),
- new Hero(13, 'Bombasto'),
- new Hero(15, 'Magneta'),
- new Hero(20, 'Tornado')
- ];
- myHero = this.heroes[0];
-}
diff --git a/public/docs/_examples/displaying-data/ts/app/hero.ts b/public/docs/_examples/displaying-data/ts/app/hero.ts
deleted file mode 100644
index 8b4f06b658..0000000000
--- a/public/docs/_examples/displaying-data/ts/app/hero.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-// #docregion
-export class Hero {
- constructor(
- // #docregion id-parameter
- public id:number,
- // #enddocregion id-parameter
- public name:string) { }
-}
-// #enddocregion
\ No newline at end of file
diff --git a/public/docs/_examples/displaying-data/ts/app/main.1.ts b/public/docs/_examples/displaying-data/ts/app/main.1.ts
deleted file mode 100644
index 511180507b..0000000000
--- a/public/docs/_examples/displaying-data/ts/app/main.1.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import {bootstrap} from 'angular2/platform/browser';
-import {AppCtorComponent} from './app-ctor.component';
-import {AppComponent as v1} from './app.component.1';
-import {AppComponent as v2} from './app.component.2';
-import {AppComponent as v3} from './app.component.3';
-
-import {AppComponent as final} from './app.component';
-
-// pick one
-//bootstrap(v1);
-//bootstrap(v2);
-//bootstrap(v3);
-bootstrap(final);
-
-// for doc testing
-bootstrap(AppCtorComponent);
\ No newline at end of file
diff --git a/public/docs/_examples/displaying-data/ts/app/main.ts b/public/docs/_examples/displaying-data/ts/app/main.ts
deleted file mode 100644
index ec4c9d12d6..0000000000
--- a/public/docs/_examples/displaying-data/ts/app/main.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-// #docregion
-import {bootstrap} from 'angular2/platform/browser';
-import {AppComponent} from './app.component';
-
-bootstrap(AppComponent);
diff --git a/public/docs/_examples/displaying-data/ts/index.1.html b/public/docs/_examples/displaying-data/ts/index.1.html
deleted file mode 100644
index 93fcaa763d..0000000000
--- a/public/docs/_examples/displaying-data/ts/index.1.html
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
- Displaying Data
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- loading...
-
- loading...
-
-
-
diff --git a/public/docs/_examples/displaying-data/ts/index.html b/public/docs/_examples/displaying-data/ts/index.html
deleted file mode 100644
index 5459c0c3fa..0000000000
--- a/public/docs/_examples/displaying-data/ts/index.html
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
- Displaying Data
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- loading...
-
-
-
-
diff --git a/public/docs/_examples/displaying-data/ts/plnkr.json b/public/docs/_examples/displaying-data/ts/plnkr.json
index ee037aec0b..b4572f0fb6 100644
--- a/public/docs/_examples/displaying-data/ts/plnkr.json
+++ b/public/docs/_examples/displaying-data/ts/plnkr.json
@@ -1,5 +1,6 @@
{
"description": "Displaying Data",
+ "basePath": "src/",
"files": [
"!**/*.d.ts",
"!**/*.js",
@@ -7,4 +8,4 @@
"!**/*.[1,2,3].*"
],
"tags": ["Template"]
-}
\ No newline at end of file
+}
diff --git a/public/docs/_examples/displaying-data/ts/app/app-ctor.component.ts b/public/docs/_examples/displaying-data/ts/src/app/app-ctor.component.ts
similarity index 77%
rename from public/docs/_examples/displaying-data/ts/app/app-ctor.component.ts
rename to public/docs/_examples/displaying-data/ts/src/app/app-ctor.component.ts
index 3b17bcb6e8..b275baa8e6 100644
--- a/public/docs/_examples/displaying-data/ts/app/app-ctor.component.ts
+++ b/public/docs/_examples/displaying-data/ts/src/app/app-ctor.component.ts
@@ -1,4 +1,4 @@
-import {Component} from 'angular2/core';
+import { Component } from '@angular/core';
@Component({
selector: 'my-app-ctor',
@@ -7,7 +7,7 @@ import {Component} from 'angular2/core';
My favorite hero is: {{myHero}}
`
})
-// #docregion app-ctor
+// #docregion class
export class AppCtorComponent {
title: string;
myHero: string;
@@ -17,4 +17,3 @@ export class AppCtorComponent {
this.myHero = 'Windstorm';
}
}
-// #enddocregion app-ctor
\ No newline at end of file
diff --git a/public/docs/_examples/displaying-data/ts/src/app/app.component.1.ts b/public/docs/_examples/displaying-data/ts/src/app/app.component.1.ts
new file mode 100644
index 0000000000..1cbeb0f731
--- /dev/null
+++ b/public/docs/_examples/displaying-data/ts/src/app/app.component.1.ts
@@ -0,0 +1,16 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ // #docregion template
+ template: `
+ {{title}}
+ My favorite hero is: {{myHero}}
+ `
+ // #enddocregion template
+})
+export class AppComponent {
+ title = 'Tour of Heroes';
+ myHero = 'Windstorm';
+}
diff --git a/public/docs/_examples/displaying-data/ts/src/app/app.component.2.ts b/public/docs/_examples/displaying-data/ts/src/app/app.component.2.ts
new file mode 100644
index 0000000000..da7a653973
--- /dev/null
+++ b/public/docs/_examples/displaying-data/ts/src/app/app.component.2.ts
@@ -0,0 +1,26 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ // #docregion template
+ template: `
+ {{title}}
+ My favorite hero is: {{myHero}}
+ Heroes:
+
+ // #docregion li
+
+ {{ hero }}
+
+ // #enddocregion li
+
+ `
+ // #enddocregion template
+})
+// #docregion class
+export class AppComponent {
+ title = 'Tour of Heroes';
+ heroes = ['Windstorm', 'Bombasto', 'Magneta', 'Tornado'];
+ myHero = this.heroes[0];
+}
diff --git a/public/docs/_examples/displaying-data/ts/src/app/app.component.3.ts b/public/docs/_examples/displaying-data/ts/src/app/app.component.3.ts
new file mode 100644
index 0000000000..06ab060557
--- /dev/null
+++ b/public/docs/_examples/displaying-data/ts/src/app/app.component.3.ts
@@ -0,0 +1,35 @@
+// #docregion
+import { Component } from '@angular/core';
+
+// #docregion import
+import { Hero } from './hero';
+// #enddocregion import
+
+@Component({
+ selector: 'my-app',
+ // #docregion template
+ template: `
+ {{title}}
+ My favorite hero is: {{myHero.name}}
+ Heroes:
+
+ `
+ // #enddocregion template
+})
+// #docregion class
+export class AppComponent {
+ title = 'Tour of Heroes';
+ // #docregion heroes
+ heroes = [
+ new Hero(1, 'Windstorm'),
+ new Hero(13, 'Bombasto'),
+ new Hero(15, 'Magneta'),
+ new Hero(20, 'Tornado')
+ ];
+ myHero = this.heroes[0];
+ // #enddocregion heroes
+}
diff --git a/public/docs/_examples/displaying-data/ts/src/app/app.component.ts b/public/docs/_examples/displaying-data/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..7234959265
--- /dev/null
+++ b/public/docs/_examples/displaying-data/ts/src/app/app.component.ts
@@ -0,0 +1,32 @@
+// #docplaster
+// #docregion final
+import { Component } from '@angular/core';
+
+import { Hero } from './hero';
+
+@Component({
+ selector: 'my-app',
+ template: `
+ {{title}}
+ My favorite hero is: {{myHero.name}}
+ Heroes:
+
+ // #docregion message
+ 3">There are many heroes!
+ // #enddocregion message
+`
+})
+export class AppComponent {
+ title = 'Tour of Heroes';
+ heroes = [
+ new Hero(1, 'Windstorm'),
+ new Hero(13, 'Bombasto'),
+ new Hero(15, 'Magneta'),
+ new Hero(20, 'Tornado')
+ ];
+ myHero = this.heroes[0];
+}
diff --git a/public/docs/_examples/displaying-data/ts/src/app/app.module.ts b/public/docs/_examples/displaying-data/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..362f3401fa
--- /dev/null
+++ b/public/docs/_examples/displaying-data/ts/src/app/app.module.ts
@@ -0,0 +1,16 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+import { AppComponent } from './app.component';
+
+@NgModule({
+ imports: [
+ BrowserModule
+ ],
+ declarations: [
+ AppComponent
+ ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/displaying-data/ts/src/app/hero.ts b/public/docs/_examples/displaying-data/ts/src/app/hero.ts
new file mode 100644
index 0000000000..f89d26ad63
--- /dev/null
+++ b/public/docs/_examples/displaying-data/ts/src/app/hero.ts
@@ -0,0 +1,9 @@
+// #docregion
+export class Hero {
+ constructor(
+ // #docregion id
+ public id: number,
+ // #enddocregion id
+ public name: string) { }
+}
+// #enddocregion
diff --git a/public/docs/_examples/displaying-data/ts/src/index.html b/public/docs/_examples/displaying-data/ts/src/index.html
new file mode 100644
index 0000000000..ddcbade46b
--- /dev/null
+++ b/public/docs/_examples/displaying-data/ts/src/index.html
@@ -0,0 +1,28 @@
+
+
+
+ Displaying Data
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ loading...
+
+
+
+
diff --git a/public/docs/_examples/displaying-data/ts/src/main.ts b/public/docs/_examples/displaying-data/ts/src/main.ts
new file mode 100644
index 0000000000..f332d1d245
--- /dev/null
+++ b/public/docs/_examples/displaying-data/ts/src/main.ts
@@ -0,0 +1,6 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/forms/dart/lib/hero.dart b/public/docs/_examples/forms/dart/lib/hero.dart
deleted file mode 100644
index 6ade27c4d3..0000000000
--- a/public/docs/_examples/forms/dart/lib/hero.dart
+++ /dev/null
@@ -1,20 +0,0 @@
-// #docregion all
-class Hero {
- int number;
- String name;
- String power;
- String alterEgo;
-
- Hero(this.number, this.name, this.power, [this.alterEgo]);
-
- String toString() => '$number: $name ($alterEgo). Super power: $power';
-}
-// #enddocregion all
-
-main() {
- // #docregion newhero
- var myHero = new Hero(
- 42, 'SkyDog', 'Fetch any object at any distance', 'Leslie Rollover');
- print('My hero is ${myHero.name}.'); // "My hero is SkyDog."
- // #enddocregion newhero
-}
diff --git a/public/docs/_examples/forms/dart/lib/hero_form_component.dart b/public/docs/_examples/forms/dart/lib/hero_form_component.dart
deleted file mode 100644
index 92f82cf0b1..0000000000
--- a/public/docs/_examples/forms/dart/lib/hero_form_component.dart
+++ /dev/null
@@ -1,34 +0,0 @@
-// #docplaster
-// #docregion
-// #docregion no-todo
-import 'package:angular2/angular2.dart';
-
-import 'hero.dart';
-
-const List _powers = const [
- 'Really Smart',
- 'Super Flexible',
- 'Super Hot',
- 'Weather Changer'
-];
-
-@Component(
- selector: 'hero-form',
- templateUrl: 'hero_form_component.html')
-class HeroFormComponent {
- List get powers => _powers;
-// #docregion submitted
- bool submitted = false;
-// #enddocregion submitted
- Hero model = new Hero(18, 'Dr IQ', _powers[0], 'Chuck Overstreet');
-// #enddocregion no-todo
- // TODO: Remove this when we're done
- String get diagnostic => 'DIAGNOSTIC: $model';
-// #docregion no-todo
-
-// #docregion submitted
- onSubmit() {
- submitted = true;
- }
-// #enddocregion submitted
-}
diff --git a/public/docs/_examples/forms/dart/lib/hero_form_component.html b/public/docs/_examples/forms/dart/lib/hero_form_component.html
deleted file mode 100644
index 22097f5e33..0000000000
--- a/public/docs/_examples/forms/dart/lib/hero_form_component.html
+++ /dev/null
@@ -1,67 +0,0 @@
-
-
-
-
-
-
-
-
-
-
You submitted the following:
-
-
Name
-
{{ model.name }}
-
-
-
Alter Ego
-
{{ model.alterEgo }}
-
-
-
Power
-
{{ model.power }}
-
-
-
Edit
-
-
-
diff --git a/public/docs/_examples/forms/dart/lib/hero_form_component_initial.dart b/public/docs/_examples/forms/dart/lib/hero_form_component_initial.dart
deleted file mode 100644
index 3ba6afb443..0000000000
--- a/public/docs/_examples/forms/dart/lib/hero_form_component_initial.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-// #docregion
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'hero-form', template: 'Hero form will go here')
-class HeroFormComponent {}
diff --git a/public/docs/_examples/forms/dart/lib/hero_form_component_initial.html b/public/docs/_examples/forms/dart/lib/hero_form_component_initial.html
deleted file mode 100644
index 155ea07fa9..0000000000
--- a/public/docs/_examples/forms/dart/lib/hero_form_component_initial.html
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
diff --git a/public/docs/_examples/forms/dart/lib/hero_form_component_ngcontrol.html b/public/docs/_examples/forms/dart/lib/hero_form_component_ngcontrol.html
deleted file mode 100644
index 09ffb3b968..0000000000
--- a/public/docs/_examples/forms/dart/lib/hero_form_component_ngcontrol.html
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
diff --git a/public/docs/_examples/forms/dart/lib/hero_form_component_ngmodel2.html b/public/docs/_examples/forms/dart/lib/hero_form_component_ngmodel2.html
deleted file mode 100644
index 9b86b3745c..0000000000
--- a/public/docs/_examples/forms/dart/lib/hero_form_component_ngmodel2.html
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
diff --git a/public/docs/_examples/forms/dart/lib/hero_form_component_ngmodel_ngfor.html b/public/docs/_examples/forms/dart/lib/hero_form_component_ngmodel_ngfor.html
deleted file mode 100644
index 111ac2403f..0000000000
--- a/public/docs/_examples/forms/dart/lib/hero_form_component_ngmodel_ngfor.html
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
diff --git a/public/docs/_examples/forms/dart/lib/hero_form_component_ngmodelchange.html b/public/docs/_examples/forms/dart/lib/hero_form_component_ngmodelchange.html
deleted file mode 100644
index c8ebb80386..0000000000
--- a/public/docs/_examples/forms/dart/lib/hero_form_component_ngmodelchange.html
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
diff --git a/public/docs/_examples/forms/dart/lib/hero_form_component_spy.html b/public/docs/_examples/forms/dart/lib/hero_form_component_spy.html
deleted file mode 100644
index c1f331eed6..0000000000
--- a/public/docs/_examples/forms/dart/lib/hero_form_component_spy.html
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
diff --git a/public/docs/_examples/forms/dart/pubspec.yaml b/public/docs/_examples/forms/dart/pubspec.yaml
deleted file mode 100644
index 6d4e9825e5..0000000000
--- a/public/docs/_examples/forms/dart/pubspec.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-# #docregion
-name: hero_form
-description: Form example
-version: 0.0.1
-environment:
- sdk: '>=1.13.0 <2.0.0'
-dependencies:
- angular2: 2.0.0-beta.8
- browser: ^0.10.0
- dart_to_js_script_rewriter: ^0.1.0
-transformers:
-- angular2:
- platform_directives:
- - 'package:angular2/common.dart#CORE_DIRECTIVES'
- - 'package:angular2/common.dart#FORM_DIRECTIVES'
- entry_points: web/main.dart
-- dart_to_js_script_rewriter
diff --git a/public/docs/_examples/forms/dart/web/bootstrap.min.css b/public/docs/_examples/forms/dart/web/bootstrap.min.css
deleted file mode 100644
index d65c66b1ba..0000000000
--- a/public/docs/_examples/forms/dart/web/bootstrap.min.css
+++ /dev/null
@@ -1,5 +0,0 @@
-/*!
- * Bootstrap v3.3.5 (http://getbootstrap.com)
- * Copyright 2011-2015 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.33px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:3;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:2;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{min-height:16.43px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-15px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-15px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}}
\ No newline at end of file
diff --git a/public/docs/_examples/forms/dart/web/index.html b/public/docs/_examples/forms/dart/web/index.html
deleted file mode 100644
index e99d87d263..0000000000
--- a/public/docs/_examples/forms/dart/web/index.html
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
-
- Hero Form
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Loading...
-
-
diff --git a/public/docs/_examples/forms/dart/web/main.dart b/public/docs/_examples/forms/dart/web/main.dart
deleted file mode 100644
index 24a30874e3..0000000000
--- a/public/docs/_examples/forms/dart/web/main.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-// #docregion
-import 'package:angular2/bootstrap.dart';
-import 'package:hero_form/hero_form_component.dart';
-
-main() {
- bootstrap(HeroFormComponent);
-}
diff --git a/public/docs/_examples/forms/e2e-spec.js b/public/docs/_examples/forms/e2e-spec.js
deleted file mode 100644
index a90138b744..0000000000
--- a/public/docs/_examples/forms/e2e-spec.js
+++ /dev/null
@@ -1,62 +0,0 @@
-describeIf(browser.appIsTs || browser.appIsJs, 'Forms Tests', function () {
-
- beforeEach(function () {
- browser.get('');
- });
-
- it('should display correct title', function () {
- expect(element.all(by.css('h1')).get(0).getText()).toEqual('Hero Form');
- });
-
-
- it('should not display message before submit', function () {
- var ele = element(by.css('h2'));
- expect(ele.isDisplayed()).toBe(false);
- });
-
- it('should hide form after submit', function () {
- var ele = element.all(by.css('h1')).get(0);
- expect(ele.isDisplayed()).toBe(true);
- var b = element.all(by.css('button[type=submit]')).get(0);
- b.click().then(function() {
- expect(ele.isDisplayed()).toBe(false);
- });
- });
-
- it('should display message after submit', function () {
- var b = element.all(by.css('button[type=submit]')).get(0);
- b.click().then(function() {
- expect(element(by.css('h2')).getText()).toContain('You submitted the following');
- });
- });
-
- it('should hide form after submit', function () {
- var alterEgoEle = element.all(by.css('input[ngcontrol=alterEgo]')).get(0);
- expect(alterEgoEle.isDisplayed()).toBe(true);
- var submitButtonEle = element.all(by.css('button[type=submit]')).get(0);
- submitButtonEle.click().then(function() {
- expect(alterEgoEle.isDisplayed()).toBe(false);
- })
- });
-
- it('should reflect submitted data after submit', function () {
- var test = 'testing 1 2 3';
- var newValue;
- var alterEgoEle = element.all(by.css('input[ngcontrol=alterEgo]')).get(0);
- alterEgoEle.getAttribute('value').then(function(value) {
- // alterEgoEle.sendKeys(test);
- sendKeys(alterEgoEle, test);
- newValue = value + test;
- expect(alterEgoEle.getAttribute('value')).toEqual(newValue);
- }).then(function() {
- var b = element.all(by.css('button[type=submit]')).get(0);
- return b.click();
- }).then(function() {
- var alterEgoTextEle = element(by.cssContainingText('div', 'Alter Ego'));
- expect(alterEgoTextEle.isPresent()).toBe(true, 'cannot locate "Alter Ego" label');
- var divEle = element(by.cssContainingText('div', newValue));
- expect(divEle.isPresent()).toBe(true, 'cannot locate div with this text: ' + newValue);
- });
- });
-});
-
diff --git a/public/docs/_examples/forms/e2e-spec.ts b/public/docs/_examples/forms/e2e-spec.ts
new file mode 100644
index 0000000000..2afd370103
--- /dev/null
+++ b/public/docs/_examples/forms/e2e-spec.ts
@@ -0,0 +1,63 @@
+import { browser, element, by } from 'protractor';
+import { appLang, describeIf } from '../protractor-helpers';
+
+describeIf(appLang.appIsTs || appLang.appIsJs, 'Forms Tests', function () {
+
+ beforeEach(function () {
+ browser.get('');
+ });
+
+ it('should display correct title', function () {
+ expect(element.all(by.css('h1')).get(0).getText()).toEqual('Hero Form');
+ });
+
+
+ it('should not display message before submit', function () {
+ let ele = element(by.css('h2'));
+ expect(ele.isDisplayed()).toBe(false);
+ });
+
+ it('should hide form after submit', function () {
+ let ele = element.all(by.css('h1')).get(0);
+ expect(ele.isDisplayed()).toBe(true);
+ let b = element.all(by.css('button[type=submit]')).get(0);
+ b.click().then(function() {
+ expect(ele.isDisplayed()).toBe(false);
+ });
+ });
+
+ it('should display message after submit', function () {
+ let b = element.all(by.css('button[type=submit]')).get(0);
+ b.click().then(function() {
+ expect(element(by.css('h2')).getText()).toContain('You submitted the following');
+ });
+ });
+
+ it('should hide form after submit', function () {
+ let alterEgoEle = element.all(by.css('input[name=alterEgo]')).get(0);
+ expect(alterEgoEle.isDisplayed()).toBe(true);
+ let submitButtonEle = element.all(by.css('button[type=submit]')).get(0);
+ submitButtonEle.click().then(function() {
+ expect(alterEgoEle.isDisplayed()).toBe(false);
+ });
+ });
+
+ it('should reflect submitted data after submit', function () {
+ let test = 'testing 1 2 3';
+ let newValue: string;
+ let alterEgoEle = element.all(by.css('input[name=alterEgo]')).get(0);
+ alterEgoEle.getAttribute('value').then(function(value: string) {
+ alterEgoEle.sendKeys(test);
+ newValue = value + test;
+ expect(alterEgoEle.getAttribute('value')).toEqual(newValue);
+ let b = element.all(by.css('button[type=submit]')).get(0);
+ return b.click();
+ }).then(function() {
+ let alterEgoTextEle = element(by.cssContainingText('div', 'Alter Ego'));
+ expect(alterEgoTextEle.isPresent()).toBe(true, 'cannot locate "Alter Ego" label');
+ let divEle = element(by.cssContainingText('div', newValue));
+ expect(divEle.isPresent()).toBe(true, 'cannot locate div with this text: ' + newValue);
+ });
+ });
+});
+
diff --git a/public/docs/_examples/forms/js/.gitignore b/public/docs/_examples/forms/js/.gitignore
deleted file mode 100644
index 8b13789179..0000000000
--- a/public/docs/_examples/forms/js/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/public/docs/_examples/forms/js/app/app.component.js b/public/docs/_examples/forms/js/app/app.component.js
deleted file mode 100644
index bb6b789938..0000000000
--- a/public/docs/_examples/forms/js/app/app.component.js
+++ /dev/null
@@ -1,12 +0,0 @@
-// #docregion
-(function(app) {
- app.AppComponent = ng.core
- .Component({
- selector: 'my-app',
- template: ' ',
- directives: [app.HeroFormComponent]
- })
- .Class({
- constructor: function() {}
- });
-})(window.app || (window.app = {}));
diff --git a/public/docs/_examples/forms/js/app/hero-form.component.html b/public/docs/_examples/forms/js/app/hero-form.component.html
deleted file mode 100644
index 2e20f638b7..0000000000
--- a/public/docs/_examples/forms/js/app/hero-form.component.html
+++ /dev/null
@@ -1,195 +0,0 @@
-
-
-
-
-
-
-
-
-
You submitted the following:
-
-
Name
-
{{ model.name }}
-
-
-
Alter Ego
-
{{ model.alterEgo }}
-
-
-
Power
-
{{ model.power }}
-
-
-
Edit
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- TODO: remove this: {{model.name}}
-
-
-
-
- TODO: remove this: {{model.name}}
-
-
-
-
-
-
- Name via form.controls = {{showFormControls(heroForm)}}
-
-
-
diff --git a/public/docs/_examples/forms/js/app/main.js b/public/docs/_examples/forms/js/app/main.js
deleted file mode 100644
index 56de1a0fdb..0000000000
--- a/public/docs/_examples/forms/js/app/main.js
+++ /dev/null
@@ -1,6 +0,0 @@
-// #docregion
-(function(app) {
- document.addEventListener('DOMContentLoaded', function() {
- ng.platform.browser.bootstrap(app.AppComponent);
- });
-})(window.app || (window.app = {}));
diff --git a/public/docs/_examples/forms/js/example-config.json b/public/docs/_examples/forms/js/example-config.json
index e69de29bb2..81f31aaf0d 100644
--- a/public/docs/_examples/forms/js/example-config.json
+++ b/public/docs/_examples/forms/js/example-config.json
@@ -0,0 +1,3 @@
+{
+ "build": "build:babel"
+}
diff --git a/public/docs/_examples/forms/js/forms.css b/public/docs/_examples/forms/js/forms.css
deleted file mode 100644
index d7e11405b1..0000000000
--- a/public/docs/_examples/forms/js/forms.css
+++ /dev/null
@@ -1,9 +0,0 @@
-/* #docregion */
-.ng-valid[required] {
- border-left: 5px solid #42A948; /* green */
-}
-
-.ng-invalid {
- border-left: 5px solid #a94442; /* red */
-}
-/* #enddocregion */
\ No newline at end of file
diff --git a/public/docs/_examples/forms/js/index.html b/public/docs/_examples/forms/js/index.html
deleted file mode 100644
index 1ded44aab9..0000000000
--- a/public/docs/_examples/forms/js/index.html
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
-
- Hero Form
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Loading...
-
-
-
diff --git a/public/docs/_examples/forms/js/plnkr.json b/public/docs/_examples/forms/js/plnkr.json
index 0105283bd3..946cbb88f6 100644
--- a/public/docs/_examples/forms/js/plnkr.json
+++ b/public/docs/_examples/forms/js/plnkr.json
@@ -1,4 +1,5 @@
{
"description": "Forms",
+ "basePath": "src/",
"files":["app/**/*.js", "**/*.html", "**/*.css"]
}
diff --git a/public/docs/_examples/forms/js/src/app/app.component.js b/public/docs/_examples/forms/js/src/app/app.component.js
new file mode 100644
index 0000000000..56bd982416
--- /dev/null
+++ b/public/docs/_examples/forms/js/src/app/app.component.js
@@ -0,0 +1,11 @@
+// #docregion
+(function(app) {
+ app.AppComponent = ng.core
+ .Component({
+ selector: 'my-app',
+ template: ' '
+ })
+ .Class({
+ constructor: function() {}
+ });
+})(window.app || (window.app = {}));
diff --git a/public/docs/_examples/forms/js/src/app/app.module.js b/public/docs/_examples/forms/js/src/app/app.module.js
new file mode 100644
index 0000000000..92c7f8b9e5
--- /dev/null
+++ b/public/docs/_examples/forms/js/src/app/app.module.js
@@ -0,0 +1,19 @@
+// #docplaster
+// #docregion
+(function(app) {
+ app.AppModule =
+ ng.core.NgModule({
+ imports: [
+ ng.platformBrowser.BrowserModule,
+ ng.forms.FormsModule
+ ],
+ declarations: [
+ app.AppComponent,
+ app.HeroFormComponent
+ ],
+ bootstrap: [ app.AppComponent ]
+ })
+ .Class({
+ constructor: function() {}
+ });
+})(window.app || (window.app = {}));
diff --git a/public/docs/_examples/forms/js/src/app/hero-form.component.html b/public/docs/_examples/forms/js/src/app/hero-form.component.html
new file mode 100644
index 0000000000..279ded0866
--- /dev/null
+++ b/public/docs/_examples/forms/js/src/app/hero-form.component.html
@@ -0,0 +1,196 @@
+
+
+
+
+
+
+
+
+
You submitted the following:
+
+
Name
+
{{ model.name }}
+
+
+
Alter Ego
+
{{ model.alterEgo }}
+
+
+
Power
+
{{ model.power }}
+
+
+
Edit
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TODO: remove this: {{model.name}}
+
+
+
+
+ TODO: remove this: {{model.name}}
+
+
+
+
+
+
+ Name via form.controls = {{showFormControls(heroForm)}}
+
+
+
diff --git a/public/docs/_examples/forms/js/app/hero-form.component.js b/public/docs/_examples/forms/js/src/app/hero-form.component.js
similarity index 94%
rename from public/docs/_examples/forms/js/app/hero-form.component.js
rename to public/docs/_examples/forms/js/src/app/hero-form.component.js
index 8988231189..505993a1fd 100644
--- a/public/docs/_examples/forms/js/app/hero-form.component.js
+++ b/public/docs/_examples/forms/js/src/app/hero-form.component.js
@@ -9,7 +9,7 @@
})
.Class({
// #docregion submitted
- constructor: function() {
+ constructor: [function() {
// #enddocregion submitted
this.powers = ['Really Smart', 'Super Flexible',
'Super Hot', 'Weather Changer'
@@ -20,7 +20,7 @@
// #docregion submitted
this.submitted = false;
- },
+ }],
onSubmit: function() {
this.submitted = true;
},
@@ -48,5 +48,5 @@
// #docregion first, final
});
- // #enddocregion first, final
})(window.app || (window.app = {}));
+// #enddocregion first, final
diff --git a/public/docs/_examples/forms/js/app/hero.js b/public/docs/_examples/forms/js/src/app/hero.js
similarity index 100%
rename from public/docs/_examples/forms/js/app/hero.js
rename to public/docs/_examples/forms/js/src/app/hero.js
diff --git a/public/docs/_examples/forms/dart/web/forms.css b/public/docs/_examples/forms/js/src/forms.css
similarity index 100%
rename from public/docs/_examples/forms/dart/web/forms.css
rename to public/docs/_examples/forms/js/src/forms.css
diff --git a/public/docs/_examples/forms/js/src/index.html b/public/docs/_examples/forms/js/src/index.html
new file mode 100644
index 0000000000..3a41d74a3b
--- /dev/null
+++ b/public/docs/_examples/forms/js/src/index.html
@@ -0,0 +1,47 @@
+
+
+
+
+
+ Hero Form
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
diff --git a/public/docs/_examples/forms/js/src/main.js b/public/docs/_examples/forms/js/src/main.js
new file mode 100644
index 0000000000..785823fa84
--- /dev/null
+++ b/public/docs/_examples/forms/js/src/main.js
@@ -0,0 +1,8 @@
+// #docregion
+(function(app) {
+ document.addEventListener('DOMContentLoaded', function() {
+ ng.platformBrowserDynamic
+ .platformBrowserDynamic()
+ .bootstrapModule(app.AppModule);
+ });
+})(window.app || (window.app = {}));
diff --git a/public/docs/_examples/forms/ts/.gitignore b/public/docs/_examples/forms/ts/.gitignore
deleted file mode 100644
index 2cb7d2a2e9..0000000000
--- a/public/docs/_examples/forms/ts/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-**/*.js
diff --git a/public/docs/_examples/forms/ts/app/app.component.ts b/public/docs/_examples/forms/ts/app/app.component.ts
deleted file mode 100644
index 92f4ec5edd..0000000000
--- a/public/docs/_examples/forms/ts/app/app.component.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-// #docregion
-import {Component} from 'angular2/core';
-import {HeroFormComponent} from './hero-form.component'
-
-@Component({
- selector: 'my-app',
- template: ' ',
- directives: [HeroFormComponent]
-})
-export class AppComponent { }
diff --git a/public/docs/_examples/forms/ts/app/hero-form.component.html b/public/docs/_examples/forms/ts/app/hero-form.component.html
deleted file mode 100644
index 3412ceaff2..0000000000
--- a/public/docs/_examples/forms/ts/app/hero-form.component.html
+++ /dev/null
@@ -1,208 +0,0 @@
-
-
-
-
-
-
-
-
-
You submitted the following:
-
-
Name
-
{{ model.name }}
-
-
-
Alter Ego
-
{{ model.alterEgo }}
-
-
-
Power
-
{{ model.power }}
-
-
-
Edit
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- TODO: remove this: {{model.name}}
-
-
-
-
- TODO: remove this: {{model.name}}
-
-
-
-
-
-
diff --git a/public/docs/_examples/forms/ts/app/hero-form.component.ts b/public/docs/_examples/forms/ts/app/hero-form.component.ts
deleted file mode 100644
index 54f9c19151..0000000000
--- a/public/docs/_examples/forms/ts/app/hero-form.component.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-// #docplaster
-// #docregion
-// #docregion first, final
-import {Component} from 'angular2/core';
-import {NgForm} from 'angular2/common';
-import { Hero } from './hero';
-
-@Component({
- selector: 'hero-form',
- templateUrl: 'app/hero-form.component.html'
-})
-export class HeroFormComponent {
-
- powers = ['Really Smart', 'Super Flexible',
- 'Super Hot', 'Weather Changer'];
-
- model = new Hero(18, 'Dr IQ', this.powers[0], 'Chuck Overstreet');
-
- // #docregion submitted
- submitted = false;
-
- onSubmit() { this.submitted = true; }
- // #enddocregion submitted
-
- // #enddocregion final
- // TODO: Remove this when we're done
- get diagnostic() { return JSON.stringify(this.model); }
- // #enddocregion first
-
- // #docregion final
- // Reset the form with a new hero AND restore 'pristine' class state
- // by toggling 'active' flag which causes the form
- // to be removed/re-added in a tick via NgIf
- // TODO: Workaround until NgForm has a reset method (#6822)
- // #docregion new-hero
- active = true;
-
- // #docregion new-hero-v1
- newHero() {
- this.model = new Hero(42, '', '');
- // #enddocregion new-hero-v1
- this.active = false;
- setTimeout(()=> this.active=true, 0);
- // #docregion new-hero-v1
- }
- // #enddocregion new-hero-v1
- // #enddocregion new-hero
- // #enddocregion final
- //////// NOT SHOWN IN DOCS ////////
-
- // Reveal in html:
- // Name via form.controls = {{showFormControls(heroForm)}}
- showFormControls(form:NgForm){
-
- return form && form.controls['name'] &&
- // #docregion form-controls
- form.controls['name'].value; // Dr. IQ
- // #enddocregion form-controls
- }
-
- /////////////////////////////
-
- // #docregion first, final
-}
-// #enddocregion first, final
diff --git a/public/docs/_examples/forms/ts/app/main.ts b/public/docs/_examples/forms/ts/app/main.ts
deleted file mode 100644
index 3fe89a9b15..0000000000
--- a/public/docs/_examples/forms/ts/app/main.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-// #docregion
-import {bootstrap} from 'angular2/platform/browser';
-import {AppComponent} from './app.component';
-
-bootstrap(AppComponent);
diff --git a/public/docs/_examples/forms/ts/forms.css b/public/docs/_examples/forms/ts/forms.css
deleted file mode 100644
index d7e11405b1..0000000000
--- a/public/docs/_examples/forms/ts/forms.css
+++ /dev/null
@@ -1,9 +0,0 @@
-/* #docregion */
-.ng-valid[required] {
- border-left: 5px solid #42A948; /* green */
-}
-
-.ng-invalid {
- border-left: 5px solid #a94442; /* red */
-}
-/* #enddocregion */
\ No newline at end of file
diff --git a/public/docs/_examples/forms/ts/index.html b/public/docs/_examples/forms/ts/index.html
deleted file mode 100644
index b5b08869bc..0000000000
--- a/public/docs/_examples/forms/ts/index.html
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
-
- Hero Form
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Loading...
-
-
-
\ No newline at end of file
diff --git a/public/docs/_examples/forms/ts/plnkr.json b/public/docs/_examples/forms/ts/plnkr.json
index 60063d7d2c..3f0abbfc3d 100644
--- a/public/docs/_examples/forms/ts/plnkr.json
+++ b/public/docs/_examples/forms/ts/plnkr.json
@@ -1,7 +1,8 @@
{
"description": "Forms",
+ "basePath": "src/",
"files":[
- "!**/*.d.ts",
+ "!**/*.d.ts",
"!**/*.js"
]
-}
\ No newline at end of file
+}
diff --git a/public/docs/_examples/forms/ts/src/app/app.component.ts b/public/docs/_examples/forms/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..454f7e03db
--- /dev/null
+++ b/public/docs/_examples/forms/ts/src/app/app.component.ts
@@ -0,0 +1,8 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ template: ' '
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/forms/ts/src/app/app.module.ts b/public/docs/_examples/forms/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..f214c02714
--- /dev/null
+++ b/public/docs/_examples/forms/ts/src/app/app.module.ts
@@ -0,0 +1,20 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { FormsModule } from '@angular/forms';
+
+import { AppComponent } from './app.component';
+import { HeroFormComponent } from './hero-form.component';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ FormsModule
+ ],
+ declarations: [
+ AppComponent,
+ HeroFormComponent
+ ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/forms/ts/src/app/hero-form.component.html b/public/docs/_examples/forms/ts/src/app/hero-form.component.html
new file mode 100644
index 0000000000..73b703f789
--- /dev/null
+++ b/public/docs/_examples/forms/ts/src/app/hero-form.component.html
@@ -0,0 +1,212 @@
+
+
+
+
+
+
+
+
+
You submitted the following:
+
+
Name
+
{{ model.name }}
+
+
+
Alter Ego
+
{{ model.alterEgo }}
+
+
+
Power
+
{{ model.power }}
+
+
+
Edit
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TODO: remove this: {{model.name}}
+
+
+
+
+ TODO: remove this: {{model.name}}
+
+
+
+
+
TODO: remove this: {{spy.className}}
+
+
+
diff --git a/public/docs/_examples/forms/ts/src/app/hero-form.component.ts b/public/docs/_examples/forms/ts/src/app/hero-form.component.ts
new file mode 100644
index 0000000000..34be523a7f
--- /dev/null
+++ b/public/docs/_examples/forms/ts/src/app/hero-form.component.ts
@@ -0,0 +1,59 @@
+// #docplaster
+// #docregion , v1, final
+import { Component } from '@angular/core';
+
+import { Hero } from './hero';
+
+@Component({
+ selector: 'hero-form',
+ templateUrl: './hero-form.component.html'
+})
+export class HeroFormComponent {
+
+ powers = ['Really Smart', 'Super Flexible',
+ 'Super Hot', 'Weather Changer'];
+
+ model = new Hero(18, 'Dr IQ', this.powers[0], 'Chuck Overstreet');
+
+ // #docregion submitted
+ submitted = false;
+
+ onSubmit() { this.submitted = true; }
+ // #enddocregion submitted
+
+ // #enddocregion final
+ // TODO: Remove this when we're done
+ get diagnostic() { return JSON.stringify(this.model); }
+ // #enddocregion v1
+
+ // #docregion final, new-hero
+ newHero() {
+ this.model = new Hero(42, '', '');
+ }
+ // #enddocregion final, new-hero
+
+ skyDog(): Hero {
+ // #docregion SkyDog
+ let myHero = new Hero(42, 'SkyDog',
+ 'Fetch any object at any distance',
+ 'Leslie Rollover');
+ console.log('My hero is called ' + myHero.name); // "My hero is called SkyDog"
+ // #enddocregion SkyDog
+ return myHero;
+ }
+
+ //////// NOT SHOWN IN DOCS ////////
+
+ // Reveal in html:
+ // Name via form.controls = {{showFormControls(heroForm)}}
+ showFormControls(form: any) {
+ return form && form.controls['name'] &&
+ // #docregion form-controls
+ form.controls['name'].value; // Dr. IQ
+ // #enddocregion form-controls
+ }
+
+ /////////////////////////////
+
+ // #docregion v1, final
+}
diff --git a/public/docs/_examples/forms/ts/app/hero.ts b/public/docs/_examples/forms/ts/src/app/hero.ts
similarity index 100%
rename from public/docs/_examples/forms/ts/app/hero.ts
rename to public/docs/_examples/forms/ts/src/app/hero.ts
diff --git a/public/docs/_examples/forms/ts/src/forms.css b/public/docs/_examples/forms/ts/src/forms.css
new file mode 100644
index 0000000000..13ffbe1203
--- /dev/null
+++ b/public/docs/_examples/forms/ts/src/forms.css
@@ -0,0 +1,9 @@
+/* #docregion */
+.ng-valid[required], .ng-valid.required {
+ border-left: 5px solid #42A948; /* green */
+}
+
+.ng-invalid:not(form) {
+ border-left: 5px solid #a94442; /* red */
+}
+/* #enddocregion */
diff --git a/public/docs/_examples/forms/ts/src/index.html b/public/docs/_examples/forms/ts/src/index.html
new file mode 100644
index 0000000000..032888ca3e
--- /dev/null
+++ b/public/docs/_examples/forms/ts/src/index.html
@@ -0,0 +1,35 @@
+
+
+
+
+ Hero Form
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
diff --git a/public/docs/_examples/forms/ts/src/main.ts b/public/docs/_examples/forms/ts/src/main.ts
new file mode 100644
index 0000000000..6b6532d428
--- /dev/null
+++ b/public/docs/_examples/forms/ts/src/main.ts
@@ -0,0 +1,5 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/hierarchical-dependency-injection/dart/lib/edit_item.dart b/public/docs/_examples/hierarchical-dependency-injection/dart/lib/edit_item.dart
deleted file mode 100644
index c5de35a9ed..0000000000
--- a/public/docs/_examples/hierarchical-dependency-injection/dart/lib/edit_item.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-// #docregion
-class EditItem {
- bool editing = false;
- T item;
- EditItem(this.item);
-}
-// #enddocregion
diff --git a/public/docs/_examples/hierarchical-dependency-injection/dart/lib/hero.dart b/public/docs/_examples/hierarchical-dependency-injection/dart/lib/hero.dart
deleted file mode 100644
index 3a9ec96783..0000000000
--- a/public/docs/_examples/hierarchical-dependency-injection/dart/lib/hero.dart
+++ /dev/null
@@ -1,14 +0,0 @@
-// #docregion
-import 'package:angular2/angular2.dart';
-
-class Hero {
- String name;
- String power;
-
- Hero clone() {
- return new Hero()
- ..name = name
- ..power = power;
- }
-}
-// #enddocregion
diff --git a/public/docs/_examples/hierarchical-dependency-injection/dart/lib/hero_card_component.dart b/public/docs/_examples/hierarchical-dependency-injection/dart/lib/hero_card_component.dart
deleted file mode 100644
index bb4b2cfd1e..0000000000
--- a/public/docs/_examples/hierarchical-dependency-injection/dart/lib/hero_card_component.dart
+++ /dev/null
@@ -1,17 +0,0 @@
-// #docregion
-import 'package:angular2/angular2.dart';
-
-import 'hero.dart';
-
-@Component(
- selector: 'hero-card',
- template: '''
-
- Name:
- {{hero.name}}
-
- ''')
-class HeroCardComponent {
- @Input() Hero hero;
-}
-// #docregion
diff --git a/public/docs/_examples/hierarchical-dependency-injection/dart/lib/hero_editor_component.dart b/public/docs/_examples/hierarchical-dependency-injection/dart/lib/hero_editor_component.dart
deleted file mode 100644
index 3619d3ab0d..0000000000
--- a/public/docs/_examples/hierarchical-dependency-injection/dart/lib/hero_editor_component.dart
+++ /dev/null
@@ -1,48 +0,0 @@
-// #docregion
-import 'package:angular2/angular2.dart';
-
-import 'hero.dart';
-import 'restore_service.dart';
-
-@Component(
- selector: 'hero-editor',
- // #docregion providers
- providers: const [RestoreService],
- // #enddocregion providers
- template: '''
-
-
Name:
-
-
- save
- cancel
-
-
- ''')
-class HeroEditorComponent {
- @Output() final EventEmitter canceled = new EventEmitter();
- @Output() final EventEmitter saved = new EventEmitter();
-
- RestoreService _restoreService;
-
- HeroEditorComponent(this._restoreService);
-
- @Input()
- set hero(Hero hero) {
- _restoreService.setItem(hero);
- }
-
- Hero get hero {
- return _restoreService.getItem();
- }
-
- onSaved() {
- saved.add(_restoreService.getItem());
- }
-
- onCanceled() {
- hero = _restoreService.restoreItem();
- canceled.add(hero);
- }
-}
-// #enddocregion
diff --git a/public/docs/_examples/hierarchical-dependency-injection/dart/lib/heroes_list_component.dart b/public/docs/_examples/hierarchical-dependency-injection/dart/lib/heroes_list_component.dart
deleted file mode 100644
index 90fbc8e2c4..0000000000
--- a/public/docs/_examples/hierarchical-dependency-injection/dart/lib/heroes_list_component.dart
+++ /dev/null
@@ -1,54 +0,0 @@
-// #docregion
-import 'package:angular2/angular2.dart';
-
-import 'edit_item.dart';
-import 'hero.dart';
-import 'hero_card_component.dart';
-import 'hero_editor_component.dart';
-import 'heroes_service.dart';
-
-@Component(
- selector: 'heroes-list',
- template: '''
-
- ''',
- directives: const [HeroCardComponent, HeroEditorComponent])
-class HeroesListComponent {
- List> heroes;
- HeroesListComponent(HeroesService heroesService) {
- heroes = heroesService
- .getHeroes()
- .map((Hero item) => new EditItem(item))
- .toList();
- }
-
- onCanceled(EditItem editItem) {
- editItem.editing = false;
- }
-
- onSaved(EditItem editItem, Hero updatedHero) {
- editItem.item = updatedHero;
- editItem.editing = false;
- }
-}
-// #enddocregion
diff --git a/public/docs/_examples/hierarchical-dependency-injection/dart/lib/heroes_service.dart b/public/docs/_examples/hierarchical-dependency-injection/dart/lib/heroes_service.dart
deleted file mode 100644
index adc97586ac..0000000000
--- a/public/docs/_examples/hierarchical-dependency-injection/dart/lib/heroes_service.dart
+++ /dev/null
@@ -1,20 +0,0 @@
-// #docregion
-import 'package:angular2/angular2.dart';
-
-import 'hero.dart';
-
-@Injectable()
-class HeroesService {
- List _heroes = [
- new Hero()
- ..name = "RubberMan"
- ..power = 'Flexibility',
- new Hero()
- ..name = "Tornado"
- ..power = 'Weather changer'
- ];
-
- List getHeroes() {
- return _heroes;
- }
-}
diff --git a/public/docs/_examples/hierarchical-dependency-injection/dart/lib/restore_service.dart b/public/docs/_examples/hierarchical-dependency-injection/dart/lib/restore_service.dart
deleted file mode 100644
index a6d8c59d35..0000000000
--- a/public/docs/_examples/hierarchical-dependency-injection/dart/lib/restore_service.dart
+++ /dev/null
@@ -1,29 +0,0 @@
-// #docregion
-import 'package:angular2/angular2.dart';
-
-@Injectable()
-class RestoreService {
- T _originalItem;
- T _currentItem;
-
- setItem(T item) {
- print(item.runtimeType);
- _originalItem = item;
- _currentItem = clone(item);
- }
-
- T getItem() {
- return _currentItem;
- }
-
- T restoreItem() {
- _currentItem = _originalItem;
- return getItem();
- }
-
- T clone(T item) {
- // super poor clone implementation
- return item.clone();
- }
-}
-// #enddocregion
diff --git a/public/docs/_examples/hierarchical-dependency-injection/dart/pubspec.yaml b/public/docs/_examples/hierarchical-dependency-injection/dart/pubspec.yaml
deleted file mode 100644
index e07635bdc4..0000000000
--- a/public/docs/_examples/hierarchical-dependency-injection/dart/pubspec.yaml
+++ /dev/null
@@ -1,15 +0,0 @@
-# #docregion
-name: 'hierarchical_di'
-description: Hierarchical dependency injection example
-version: 0.0.1
-environment:
- sdk: '>=1.13.0 <2.0.0'
-dependencies:
- angular2: 2.0.0-beta.8
- browser: ^0.10.0
- dart_to_js_script_rewriter: ^0.1.0
-transformers:
-- angular2:
- platform_directives: 'package:angular2/common.dart#COMMON_DIRECTIVES'
- entry_points: web/main.dart
-- dart_to_js_script_rewriter
diff --git a/public/docs/_examples/hierarchical-dependency-injection/dart/web/index.html b/public/docs/_examples/hierarchical-dependency-injection/dart/web/index.html
deleted file mode 100644
index 598203b414..0000000000
--- a/public/docs/_examples/hierarchical-dependency-injection/dart/web/index.html
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
-
- Hierarchical Injector
-
-
-
-
-
-
-
- loading...
-
-
-
-
diff --git a/public/docs/_examples/hierarchical-dependency-injection/dart/web/main.dart b/public/docs/_examples/hierarchical-dependency-injection/dart/web/main.dart
deleted file mode 100644
index a265c21e69..0000000000
--- a/public/docs/_examples/hierarchical-dependency-injection/dart/web/main.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// #docregion
-import 'package:angular2/bootstrap.dart';
-import 'package:hierarchical_di/heroes_list_component.dart';
-import 'package:hierarchical_di/heroes_service.dart';
-
-void main() {
- bootstrap(HeroesListComponent, [HeroesService]);
-}
-
-/* Documentation artifact below
-// #docregion bad-alternative
-// Don't do this!
-bootstrap(HeroesListComponent, [HeroesService, RestoreService])
-// #enddocregion bad-alternative
-*/
diff --git a/public/docs/_examples/hierarchical-dependency-injection/e2e-spec.js b/public/docs/_examples/hierarchical-dependency-injection/e2e-spec.js
deleted file mode 100644
index 2f63c32d52..0000000000
--- a/public/docs/_examples/hierarchical-dependency-injection/e2e-spec.js
+++ /dev/null
@@ -1,56 +0,0 @@
-describe('Hierarchical dependency injection', function () {
-
- beforeEach(function () {
- browser.get('');
- });
-
- it('should open with a card view', function () {
- expect(element.all(by.cssContainingText('button','edit')).get(0).isDisplayed()).toBe(true,
- "edit button should be displayed");
- });
-
- it('should have multiple heros listed', function () {
- expect(element.all(by.css('heroes-list li')).count()).toBeGreaterThan(1);
- });
-
- it('should change to editor view after selection', function () {
- var editButtonEle = element.all(by.cssContainingText('button','edit')).get(0);
- editButtonEle.click().then(function() {
- expect(editButtonEle.isDisplayed()).toBe(false, "edit button should be hidden after selection");
- })
- });
-
- it('should be able to save editor change', function () {
- testEdit(true);
- });
-
- it('should be able to cancel editor change', function () {
- testEdit(false);
- });
-
- function testEdit(shouldSave) {
- var inputEle;
- // select 2nd ele
- var heroEle = element.all(by.css('heroes-list li')).get(1);
- // get the 2nd span which is the name of the hero
- var heroNameEle = heroEle.all(by.css('hero-card span')).get(1);
- var editButtonEle = heroEle.element(by.cssContainingText('button','edit'));
- editButtonEle.click().then(function() {
- inputEle = heroEle.element(by.css('hero-editor input'));
- // return inputEle.sendKeys("foo");
- return sendKeys(inputEle, "foo");
- }).then(function() {
- buttonName = shouldSave ? 'save' : 'cancel';
- var buttonEle = heroEle.element(by.cssContainingText('button', buttonName));
- return buttonEle.click();
- }).then(function() {
- if (shouldSave) {
- expect(heroNameEle.getText()).toContain('foo');
- } else {
- expect(heroNameEle.getText()).not.toContain('foo');
- }
- })
- }
-
-
-});
diff --git a/public/docs/_examples/hierarchical-dependency-injection/e2e-spec.ts b/public/docs/_examples/hierarchical-dependency-injection/e2e-spec.ts
new file mode 100644
index 0000000000..4630453f78
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/e2e-spec.ts
@@ -0,0 +1,103 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, by, element } from 'protractor';
+
+describe('Hierarchical dependency injection', () => {
+
+ beforeAll(() => {
+ browser.get('');
+ });
+
+ describe('Heroes Scenario', () => {
+ let page = {
+ heroName: '',
+ income: '',
+
+ // queries
+ heroEl: element.all(by.css('heroes-list li')).get(0), // first hero
+ heroCardEl: element(by.css('heroes-list hero-tax-return')), // first hero tax-return
+ taxReturnNameEl: element.all(by.css('heroes-list hero-tax-return #name')).get(0),
+ incomeInputEl: element.all(by.css('heroes-list hero-tax-return input')).get(0),
+ cancelButtonEl: element(by.cssContainingText('heroes-list hero-tax-return button', 'Cancel')),
+ closeButtonEl: element(by.cssContainingText('heroes-list hero-tax-return button', 'Close')),
+ saveButtonEl: element(by.cssContainingText('heroes-list hero-tax-return button', 'Save'))
+ };
+
+ it('should list multiple heroes', () => {
+ expect(element.all(by.css('heroes-list li')).count()).toBeGreaterThan(1);
+ });
+
+ it('should show no hero tax-returns at the start', () => {
+ expect(element.all(by.css('heroes-list li hero-tax-return')).count()).toBe(0);
+ });
+
+ it('should open first hero in hero-tax-return view after click', () => {
+ page.heroEl.getText()
+ .then(val => {
+ page.heroName = val;
+ })
+ .then(() => page.heroEl.click())
+ .then(() => {
+ expect(page.heroCardEl.isDisplayed()).toBe(true);
+ });
+ });
+
+ it('hero tax-return should have first hero\'s name', () => {
+ // Not `page.tax-returnNameInputEl.getAttribute('value')` although later that is essential
+ expect(page.taxReturnNameEl.getText()).toEqual(page.heroName);
+ });
+
+ it('should be able to cancel change', () => {
+ page.incomeInputEl.clear()
+ .then(() => page.incomeInputEl.sendKeys('777'))
+ .then(() => {
+ expect(page.incomeInputEl.getAttribute('value')).toBe('777', 'income should be 777');
+ return page.cancelButtonEl.click();
+ })
+ .then(() => {
+ expect(page.incomeInputEl.getAttribute('value')).not.toBe('777', 'income should not be 777');
+ });
+ });
+
+ it('should be able to save change', () => {
+ page.incomeInputEl.clear()
+ .then(() => page.incomeInputEl.sendKeys('999'))
+ .then(() => {
+ expect(page.incomeInputEl.getAttribute('value')).toBe('999', 'income should be 999');
+ return page.saveButtonEl.click();
+ })
+ .then(() => {
+ expect(page.incomeInputEl.getAttribute('value')).toBe('999', 'income should still be 999');
+ });
+ });
+
+ it('should be able to close tax-return', () => {
+ page.saveButtonEl.click()
+ .then(() => {
+ expect(element.all(by.css('heroes-list li hero-tax-return')).count()).toBe(0);
+ });
+ });
+
+ });
+
+ describe('Villains Scenario', () => {
+ it('should list multiple villains', () => {
+ expect(element.all(by.css('villains-list li')).count()).toBeGreaterThan(1);
+ });
+ });
+
+ describe('Cars Scenario', () => {
+
+ it('A-component should use expected services', () => {
+ expect(element(by.css('a-car')).getText()).toContain('C1-E1-T1');
+ });
+
+ it('B-component should use expected services', () => {
+ expect(element(by.css('b-car')).getText()).toContain('C2-E2-T1');
+ });
+
+ it('C-component should use expected services', () => {
+ expect(element(by.css('c-car')).getText()).toContain('C3-E2-T1');
+ });
+ });
+});
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/.gitignore b/public/docs/_examples/hierarchical-dependency-injection/ts/.gitignore
deleted file mode 100644
index 2cb7d2a2e9..0000000000
--- a/public/docs/_examples/hierarchical-dependency-injection/ts/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-**/*.js
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/edit-item.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/app/edit-item.ts
deleted file mode 100644
index abbeabf2b0..0000000000
--- a/public/docs/_examples/hierarchical-dependency-injection/ts/app/edit-item.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-// #docregion
-export class EditItem {
- editing: boolean
- constructor (public item: T) {}
-}
-// #docregion
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero-card.component.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero-card.component.ts
deleted file mode 100644
index 04d64ad19d..0000000000
--- a/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero-card.component.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-// #docregion
-import {Component, Input} from 'angular2/core';
-import {Hero} from './hero';
-
-@Component({
- selector: 'hero-card',
- template: `
-
- Name:
- {{hero.name}}
-
`
-})
-export class HeroCardComponent {
- @Input() hero: Hero;
-}
-// #docregion
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero-editor.component.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero-editor.component.ts
deleted file mode 100644
index 1c19577cda..0000000000
--- a/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero-editor.component.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-// #docregion
-import {Component, Input, Output, EventEmitter} from 'angular2/core';
-import {RestoreService} from './restore.service';
-import {Hero} from './hero';
-
-@Component({
- selector: 'hero-editor',
- // #docregion providers
- providers: [RestoreService],
- // #enddocregion providers
- template: `
-
-
Name:
-
-
- save
- cancel
-
-
`
-})
-
-export class HeroEditorComponent {
- @Output() canceled = new EventEmitter();
- @Output() saved = new EventEmitter();
-
- constructor(private restoreService: RestoreService) {}
-
- @Input()
- set hero (hero: Hero) {
- this.restoreService.setItem(hero);
- }
-
- get hero () {
- return this.restoreService.getItem();
- }
-
- onSaved () {
- this.saved.next(this.restoreService.getItem());
- }
-
- onCanceled () {
- this.hero = this.restoreService.restoreItem();
- this.canceled.next(this.hero);
- }
-}
-// #enddocregion
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero.ts
deleted file mode 100644
index 76f808b1c5..0000000000
--- a/public/docs/_examples/hierarchical-dependency-injection/ts/app/hero.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-// #docregion
-export class Hero {
- name: string;
- power: string;
-}
-// #enddocregion
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/heroes-list.component.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/app/heroes-list.component.ts
deleted file mode 100644
index a2d477710a..0000000000
--- a/public/docs/_examples/hierarchical-dependency-injection/ts/app/heroes-list.component.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-// #docregion
-import {Component} from 'angular2/core';
-import {EditItem} from './edit-item';
-import {HeroesService} from './heroes.service';
-import {HeroCardComponent} from './hero-card.component';
-import {HeroEditorComponent} from './hero-editor.component';
-import {Hero} from './hero';
-
-@Component({
- selector: 'heroes-list',
- template: `
- `,
- directives: [HeroCardComponent, HeroEditorComponent]
-})
-export class HeroesListComponent {
- heroes: Array>;
- constructor(heroesService: HeroesService) {
- this.heroes = heroesService.getHeroes()
- .map(item => new EditItem(item));
- }
-
- onSaved (editItem: EditItem, updatedHero: Hero) {
- editItem.item = updatedHero;
- editItem.editing = false;
- }
-
- onCanceled (editItem: EditItem) {
- editItem.editing = false;
- }
-}
-
-
-// #enddocregion
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/heroes.service.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/app/heroes.service.ts
deleted file mode 100644
index e4f9e2d213..0000000000
--- a/public/docs/_examples/hierarchical-dependency-injection/ts/app/heroes.service.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import {Hero} from './hero';
-
-export class HeroesService {
- heroes: Array = [
- { name: "RubberMan", power: 'flexibility'},
- { name: "Tornado", power: 'Weather changer'}
- ];
-
- getHeroes () {
- return this.heroes;
- }
-}
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/main.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/app/main.ts
deleted file mode 100644
index 7b3189eb3e..0000000000
--- a/public/docs/_examples/hierarchical-dependency-injection/ts/app/main.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-// #docregion
-import {bootstrap} from 'angular2/platform/browser';
-import {HeroesListComponent} from './heroes-list.component';
-import {HeroesService} from './heroes.service';
-
-bootstrap(HeroesListComponent, [HeroesService])
-
-/* Documentation artifact below
-// #docregion bad-alternative
-// Don't do this!
-bootstrap(HeroesListComponent, [HeroesService, RestoreService])
-// #enddocregion bad-alternative
-*/
\ No newline at end of file
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/app/restore.service.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/app/restore.service.ts
deleted file mode 100644
index c81786b2a3..0000000000
--- a/public/docs/_examples/hierarchical-dependency-injection/ts/app/restore.service.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-// #docregion
-export class RestoreService {
- originalItem: T;
- currentItem: T;
-
- setItem (item: T) {
- this.originalItem = item;
- this.currentItem = this.clone(item);
- }
-
- getItem () :T {
- return this.currentItem;
- }
-
- restoreItem () :T {
- this.currentItem = this.originalItem;
- return this.getItem();
- }
-
- clone (item: T) :T {
- // super poor clone implementation
- return JSON.parse(JSON.stringify(item));
- }
-}
-// #enddocregion
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/index.html b/public/docs/_examples/hierarchical-dependency-injection/ts/index.html
deleted file mode 100644
index e029217cee..0000000000
--- a/public/docs/_examples/hierarchical-dependency-injection/ts/index.html
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
- Hierarchical Injectors
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- loading...
-
-
-
-
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/plnkr.json b/public/docs/_examples/hierarchical-dependency-injection/ts/plnkr.json
index 84cd89d7ca..ca92b93b06 100644
--- a/public/docs/_examples/hierarchical-dependency-injection/ts/plnkr.json
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/plnkr.json
@@ -1,5 +1,9 @@
{
- "description": "Hierachical Injectors",
- "files":["!**/*.d.ts", "!**/*.js"],
+ "description": "Hierachical Dependency Injection",
+ "basePath": "src/",
+ "files":[
+ "!**/*.d.ts",
+ "!**/*.js"
+ ],
"tags": ["dependency", "injection"]
-}
\ No newline at end of file
+}
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/app.component.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..34b5dd0a5a
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/app.component.ts
@@ -0,0 +1,21 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ template: `
+ Heroes
+ Villains
+ Cars
+
+ Hierarchical Dependency Injection
+
+
+
+
+ `
+})
+export class AppComponent {
+ showCars = true;
+ showHeroes = true;
+ showVillains = true;
+}
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/app.module.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..6ea18655af
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/app.module.ts
@@ -0,0 +1,33 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { FormsModule } from '@angular/forms';
+
+import { AppComponent } from './app.component';
+import { HeroTaxReturnComponent } from './hero-tax-return.component';
+import { HeroesListComponent } from './heroes-list.component';
+import { HeroesService } from './heroes.service';
+import { VillainsListComponent } from './villains-list.component';
+
+import { carComponents, carServices } from './car.components';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ FormsModule
+ ],
+ providers: [
+ carServices,
+ HeroesService
+ ],
+ declarations: [
+ AppComponent,
+ carComponents,
+ HeroesListComponent,
+ HeroTaxReturnComponent,
+ VillainsListComponent
+ ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
+
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/car.components.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/car.components.ts
new file mode 100644
index 0000000000..5b4df19696
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/car.components.ts
@@ -0,0 +1,74 @@
+import { Component } from '@angular/core';
+
+import {
+ CarService, CarService2, CarService3,
+ EngineService, EngineService2, TiresService
+} from './car.services';
+
+////////// CCarComponent ////////////
+@Component({
+ selector: 'c-car',
+ template: `C: {{description}}
`,
+ providers: [
+ { provide: CarService, useClass: CarService3 }
+ ]
+})
+export class CCarComponent {
+ description: string;
+ constructor(carService: CarService) {
+ this.description = `${carService.getCar().description} (${carService.name})`;
+ }
+}
+
+////////// BCarComponent ////////////
+@Component({
+ selector: 'b-car',
+ template: `
+ B: {{description}}
+
+ `,
+ providers: [
+ { provide: CarService, useClass: CarService2 },
+ { provide: EngineService, useClass: EngineService2 }
+ ]
+})
+export class BCarComponent {
+ description: string;
+ constructor(carService: CarService) {
+ this.description = `${carService.getCar().description} (${carService.name})`;
+ }
+}
+
+////////// ACarComponent ////////////
+@Component({
+ selector: 'a-car',
+ template: `
+ A: {{description}}
+ `
+})
+export class ACarComponent {
+ description: string;
+ constructor(carService: CarService) {
+ this.description = `${carService.getCar().description} (${carService.name})`;
+ }
+}
+////////// CarsComponent ////////////
+@Component({
+ selector: 'my-cars',
+ template: `
+ Cars
+ `
+})
+export class CarsComponent { }
+
+////////////////
+
+export const carComponents = [
+ CarsComponent,
+ ACarComponent, BCarComponent, CCarComponent
+];
+
+// generic car-related services
+export const carServices = [
+ CarService, EngineService, TiresService
+];
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/car.services.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/car.services.ts
new file mode 100644
index 0000000000..03c79270b0
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/car.services.ts
@@ -0,0 +1,95 @@
+import { Injectable } from '@angular/core';
+
+/// Model ///
+export class Car {
+ name = 'Avocado Motors';
+ constructor(public engine: Engine, public tires: Tires) { }
+
+ get description() {
+ return `${this.name} car with ` +
+ `${this.engine.cylinders} cylinders and ${this.tires.make} tires.`;
+ }
+}
+
+export class Engine {
+ cylinders = 4;
+}
+
+export class Tires {
+ make = 'Flintstone';
+ model = 'Square';
+}
+
+//// Engine services ///
+@Injectable()
+export class EngineService {
+ id = 'E1';
+ getEngine() { return new Engine(); }
+}
+
+@Injectable()
+export class EngineService2 {
+ id = 'E2';
+ getEngine() {
+ const eng = new Engine();
+ eng.cylinders = 8;
+ return eng;
+ }
+}
+
+//// Tire services ///
+@Injectable()
+export class TiresService {
+ id = 'T1';
+ getTires() { return new Tires(); }
+}
+
+/// Car Services ///
+@Injectable()
+export class CarService {
+ id = 'C1';
+ constructor(
+ protected engineService: EngineService,
+ protected tiresService: TiresService) { }
+
+ getCar() {
+ return new Car(
+ this.engineService.getEngine(),
+ this.tiresService.getTires());
+ }
+
+ get name() {
+ return `${this.id}-${this.engineService.id}-${this.tiresService.id}`;
+ }
+}
+
+@Injectable()
+export class CarService2 extends CarService {
+ id = 'C2';
+ constructor(
+ protected engineService: EngineService,
+ protected tiresService: TiresService) {
+ super(engineService, tiresService);
+ }
+ getCar() {
+ const car = super.getCar();
+ car.name = 'BamBam Motors, BroVan 2000';
+ return car;
+ }
+}
+
+@Injectable()
+export class CarService3 extends CarService2 {
+ id = 'C3';
+ constructor(
+ protected engineService: EngineService,
+ protected tiresService: TiresService) {
+ super(engineService, tiresService);
+ }
+ getCar() {
+ const car = super.getCar();
+ car.name = 'Chizzamm Motors, Calico UltraMax Supreme';
+ return car;
+ }
+}
+
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/hero-tax-return.component.css b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/hero-tax-return.component.css
new file mode 100644
index 0000000000..1d29a1d168
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/hero-tax-return.component.css
@@ -0,0 +1,22 @@
+.tax-return { border: thin dashed green; margin: 1em; padding: 1em; width: 18em; position: relative }
+#name { font-weight: bold;}
+#tid { float: right; }
+input { font-size: 100%; padding-left: 2px; width: 6em; }
+input.num { text-align: right; padding-left: 0; padding-right: 4px; width: 4em;}
+fieldset { border: 0 none;}
+
+.msg {
+ color: white;
+ font-size: 150%;
+ position: absolute;
+ /*opacity: 0.3;*/
+ left: 2px;
+ top: 3em;
+ width: 98%;
+ background-color: green;
+ text-align: center;
+}
+.msg.canceled {
+ color: white;
+ background-color: red;
+}
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/hero-tax-return.component.html b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/hero-tax-return.component.html
new file mode 100644
index 0000000000..ebf2dcbaaa
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/hero-tax-return.component.html
@@ -0,0 +1,20 @@
+
+
{{message}}
+
+ {{taxReturn.name}}
+ TID: {{taxReturn.tid}}
+
+
+
+ Income:
+
+
+
+ Tax: {{taxReturn.tax}}
+
+
+ Save
+ Cancel
+ Close
+
+
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/hero-tax-return.component.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/hero-tax-return.component.ts
new file mode 100644
index 0000000000..ad8e0153d9
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/hero-tax-return.component.ts
@@ -0,0 +1,44 @@
+// #docregion
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+import { HeroTaxReturn } from './hero';
+import { HeroTaxReturnService } from './hero-tax-return.service';
+
+@Component({
+ selector: 'hero-tax-return',
+ templateUrl: './hero-tax-return.component.html',
+ styleUrls: [ './hero-tax-return.component.css' ],
+ // #docregion providers
+ providers: [ HeroTaxReturnService ]
+ // #enddocregion providers
+})
+export class HeroTaxReturnComponent {
+ message = '';
+ @Output() close = new EventEmitter();
+
+ get taxReturn(): HeroTaxReturn {
+ return this.heroTaxReturnService.taxReturn;
+ }
+ @Input()
+ set taxReturn (htr: HeroTaxReturn) {
+ this.heroTaxReturnService.taxReturn = htr;
+ }
+
+ constructor(private heroTaxReturnService: HeroTaxReturnService ) { }
+
+ onCanceled() {
+ this.flashMessage('Canceled');
+ this.heroTaxReturnService.restoreTaxReturn();
+ };
+
+ onClose() { this.close.emit(); };
+
+ onSaved() {
+ this.flashMessage('Saved');
+ this.heroTaxReturnService.saveTaxReturn();
+ }
+
+ flashMessage(msg: string) {
+ this.message = msg;
+ setTimeout(() => this.message = '', 500);
+ }
+}
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/hero-tax-return.service.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/hero-tax-return.service.ts
new file mode 100644
index 0000000000..d6ff0f7fff
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/hero-tax-return.service.ts
@@ -0,0 +1,30 @@
+// #docregion
+import { Injectable } from '@angular/core';
+import { HeroTaxReturn } from './hero';
+import { HeroesService } from './heroes.service';
+
+@Injectable()
+export class HeroTaxReturnService {
+ private currentTaxReturn: HeroTaxReturn;
+ private originalTaxReturn: HeroTaxReturn;
+
+ constructor(private heroService: HeroesService) { }
+
+ set taxReturn (htr: HeroTaxReturn) {
+ this.originalTaxReturn = htr;
+ this.currentTaxReturn = htr.clone();
+ }
+
+ get taxReturn (): HeroTaxReturn {
+ return this.currentTaxReturn;
+ }
+
+ restoreTaxReturn() {
+ this.taxReturn = this.originalTaxReturn;
+ }
+
+ saveTaxReturn() {
+ this.taxReturn = this.currentTaxReturn;
+ this.heroService.saveTaxReturn(this.currentTaxReturn).subscribe();
+ }
+}
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/hero.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/hero.ts
new file mode 100644
index 0000000000..4ad6ccd8eb
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/hero.ts
@@ -0,0 +1,31 @@
+// #docregion
+
+export class Hero {
+ id: number;
+ name: string;
+ tid: string; // tax id
+}
+
+//// HeroTaxReturn ////
+let nextId = 100;
+
+export class HeroTaxReturn {
+ constructor(
+ public id = nextId++,
+ public hero: Hero,
+ public income = 0 ) {
+ if (id === 0) { id = nextId++; }
+ }
+
+ get name() { return this.hero.name; }
+ get tax() { return this.income ? .10 * this.income : 0; }
+ get tid() { return this.hero.tid; }
+
+ toString() {
+ return `${this.hero.name}`;
+ }
+
+ clone() {
+ return new HeroTaxReturn(this.id, this.hero, this.income);
+ }
+}
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/heroes-list.component.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/heroes-list.component.ts
new file mode 100644
index 0000000000..36cb5ec1c3
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/heroes-list.component.ts
@@ -0,0 +1,48 @@
+// #docregion
+import { Component } from '@angular/core';
+import { Observable } from 'rxjs/Observable';
+
+import { Hero, HeroTaxReturn } from './hero';
+import { HeroesService } from './heroes.service';
+
+@Component({
+ selector: 'heroes-list',
+ template: `
+
+
Hero Tax Returns
+
+
+
+
+ `,
+ styles: [ 'li {cursor: pointer;}' ]
+})
+export class HeroesListComponent {
+ heroes: Observable;
+ selectedTaxReturns: HeroTaxReturn[] = [];
+
+ constructor(private heroesService: HeroesService) {
+ this.heroes = heroesService.getHeroes();
+ }
+
+ showTaxReturn(hero: Hero) {
+ this.heroesService.getTaxReturn(hero)
+ .subscribe(htr => {
+ // show if not currently shown
+ if (!this.selectedTaxReturns.find(tr => tr.id === htr.id)) {
+ this.selectedTaxReturns.push(htr);
+ }
+ });
+ }
+
+ closeTaxReturn(ix: number) {
+ this.selectedTaxReturns.splice(ix, 1);
+ }
+}
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/heroes.service.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/heroes.service.ts
new file mode 100644
index 0000000000..85b33c89a0
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/heroes.service.ts
@@ -0,0 +1,47 @@
+import { Injectable } from '@angular/core';
+
+import { Observable } from 'rxjs/Observable';
+import { Observer } from 'rxjs/Observer';
+
+import { Hero, HeroTaxReturn } from './hero';
+
+@Injectable()
+export class HeroesService {
+ heroes: Hero[] = [
+ { id: 1, name: 'RubberMan', tid: '082-27-5678'},
+ { id: 2, name: 'Tornado', tid: '099-42-4321'}
+ ];
+
+ heroTaxReturns: HeroTaxReturn[] = [
+ new HeroTaxReturn(10, this.heroes[0], 35000),
+ new HeroTaxReturn(20, this.heroes[1], 1250000)
+ ];
+
+ getHeroes(): Observable {
+ return new Observable((observer: Observer) => {
+ observer.next(this.heroes);
+ observer.complete();
+ });
+ }
+
+ getTaxReturn(hero: Hero): Observable {
+ return new Observable((observer: Observer) => {
+ const htr = this.heroTaxReturns.find(t => t.hero.id === hero.id);
+ observer.next(htr || new HeroTaxReturn(0, hero));
+ observer.complete();
+ });
+ }
+
+ saveTaxReturn(heroTaxReturn: HeroTaxReturn): Observable {
+ return new Observable((observer: Observer) => {
+ const htr = this.heroTaxReturns.find(t => t.id === heroTaxReturn.id);
+ if (htr) {
+ heroTaxReturn = Object.assign(htr, heroTaxReturn); // demo: mutate
+ } else {
+ this.heroTaxReturns.push(heroTaxReturn);
+ }
+ observer.next(heroTaxReturn);
+ observer.complete();
+ });
+ }
+}
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/villains-list.component.html b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/villains-list.component.html
new file mode 100644
index 0000000000..75e5ba3237
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/villains-list.component.html
@@ -0,0 +1,6 @@
+
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/villains-list.component.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/villains-list.component.ts
new file mode 100644
index 0000000000..5226d4f2a9
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/villains-list.component.ts
@@ -0,0 +1,20 @@
+// #docregion
+import { Component } from '@angular/core';
+import { Observable } from 'rxjs/Observable';
+
+import { Villain, VillainsService } from './villains.service';
+
+// #docregion metadata
+@Component({
+ selector: 'villains-list',
+ templateUrl: './villains-list.component.html',
+ providers: [ VillainsService ]
+})
+// #enddocregion metadata
+export class VillainsListComponent {
+ villains: Observable;
+
+ constructor(private villainsService: VillainsService) {
+ this.villains = villainsService.getVillains();
+ }
+}
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/villains.service.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/villains.service.ts
new file mode 100644
index 0000000000..3d480c20af
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/src/app/villains.service.ts
@@ -0,0 +1,17 @@
+import { Injectable } from '@angular/core';
+
+import { of } from 'rxjs/observable/of';
+
+export interface Villain { id: number; name: string; }
+
+@Injectable()
+export class VillainsService {
+ villains: Villain[] = [
+ { id: 1, name: 'Dr. Evil'},
+ { id: 2, name: 'Moriarty'}
+ ];
+
+ getVillains() {
+ return of(this.villains);
+ }
+}
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/src/index.html b/public/docs/_examples/hierarchical-dependency-injection/ts/src/index.html
new file mode 100644
index 0000000000..0ea32679e6
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/src/index.html
@@ -0,0 +1,26 @@
+
+
+
+ Hierarchical Injectors
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ loading...
+
+
+
diff --git a/public/docs/_examples/hierarchical-dependency-injection/ts/src/main.ts b/public/docs/_examples/hierarchical-dependency-injection/ts/src/main.ts
new file mode 100644
index 0000000000..6b6532d428
--- /dev/null
+++ b/public/docs/_examples/hierarchical-dependency-injection/ts/src/main.ts
@@ -0,0 +1,5 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/homepage-hello-world/e2e-spec.js b/public/docs/_examples/homepage-hello-world/e2e-spec.js
deleted file mode 100644
index 4cccdfa4e3..0000000000
--- a/public/docs/_examples/homepage-hello-world/e2e-spec.js
+++ /dev/null
@@ -1,29 +0,0 @@
-
-describe('Homepage Hello World', function () {
-
- beforeAll(function () {
- browser.get('');
- });
-
- // Does it even launch?
- var expectedLabel = 'Name:';
- it('should display the label: ' + expectedLabel, function () {
- expect(element(by.css('label')).getText()).toEqual(expectedLabel);
- });
-
- it('should display entered name', function () {
- var testName = 'Bobby Joe';
- var newValue;
- var nameEle = element.all(by.css('input')).get(0);
- nameEle.getAttribute('value').then(function(value) {
- // nameEle.sendKeys(testName); // should work but doesn't
- sendKeys(nameEle, testName); // utility that does work
- newValue = value + testName; // old input box value + new name
- expect(nameEle.getAttribute('value')).toEqual(newValue);
- }).then(function() {
- // Check the interpolated message built from name
- var helloEle = element.all(by.css('h1')).get(0);
- expect(helloEle.getText()).toEqual('Hello ' + testName + '!');
- });
- });
-});
diff --git a/public/docs/_examples/homepage-hello-world/e2e-spec.ts b/public/docs/_examples/homepage-hello-world/e2e-spec.ts
new file mode 100644
index 0000000000..c4c6464937
--- /dev/null
+++ b/public/docs/_examples/homepage-hello-world/e2e-spec.ts
@@ -0,0 +1,30 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by } from 'protractor';
+
+describe('Homepage Hello World', function () {
+
+ beforeAll(function () {
+ browser.get('');
+ });
+
+ // Does it even launch?
+ let expectedLabel = 'Name:';
+ it(`should display the label: ${expectedLabel}`, function () {
+ expect(element(by.css('label')).getText()).toEqual(expectedLabel);
+ });
+
+ it('should display entered name', function () {
+ let testName = 'Bobby Joe';
+ let nameEle = element.all(by.css('input')).get(0);
+ nameEle.getAttribute('value').then(function(value: string) {
+ nameEle.sendKeys(testName);
+ let newValue = value + testName; // old input box value + new name
+ expect(nameEle.getAttribute('value')).toEqual(newValue);
+ }).then(function() {
+ // Check the interpolated message built from name
+ let helloEle = element.all(by.css('h1')).get(0);
+ expect(helloEle.getText()).toEqual('Hello ' + testName + '!');
+ });
+ });
+});
diff --git a/public/docs/_examples/homepage-hello-world/ts/.gitignore b/public/docs/_examples/homepage-hello-world/ts/.gitignore
deleted file mode 100644
index 2cb7d2a2e9..0000000000
--- a/public/docs/_examples/homepage-hello-world/ts/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-**/*.js
diff --git a/public/docs/_examples/homepage-hello-world/ts/app/hello_world.ts b/public/docs/_examples/homepage-hello-world/ts/app/hello_world.ts
deleted file mode 100644
index af08051387..0000000000
--- a/public/docs/_examples/homepage-hello-world/ts/app/hello_world.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-// #docregion
-import {Component} from 'angular2/core';
-
-@Component({
- // Declare the tag name in index.html to where the component attaches
- selector: 'hello-world',
-
- // Location of the template for this component
- templateUrl: 'app/hello_world.html'
-})
-export class HelloWorld {
-
- // Declaring the variable for binding with initial value
- yourName: string = '';
-}
diff --git a/public/docs/_examples/homepage-hello-world/ts/app/main.ts b/public/docs/_examples/homepage-hello-world/ts/app/main.ts
deleted file mode 100644
index edafebcde5..0000000000
--- a/public/docs/_examples/homepage-hello-world/ts/app/main.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-// #docregion
-import {bootstrap} from 'angular2/platform/browser';
-import {HelloWorld} from './hello_world';
-
-bootstrap(HelloWorld);
\ No newline at end of file
diff --git a/public/docs/_examples/homepage-hello-world/ts/index.1.html b/public/docs/_examples/homepage-hello-world/ts/index.1.html
deleted file mode 100644
index 74910a7a45..0000000000
--- a/public/docs/_examples/homepage-hello-world/ts/index.1.html
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
- Angular 2 Hello World
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Loading...
-
-
-
\ No newline at end of file
diff --git a/public/docs/_examples/homepage-hello-world/ts/index.html b/public/docs/_examples/homepage-hello-world/ts/index.html
deleted file mode 100644
index 997edd82d7..0000000000
--- a/public/docs/_examples/homepage-hello-world/ts/index.html
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-
-
- Angular 2 Hello World
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Loading...
-
-
-
\ No newline at end of file
diff --git a/public/docs/_examples/homepage-hello-world/ts/plnkr.json b/public/docs/_examples/homepage-hello-world/ts/plnkr.json
index 78f6fd979d..bfe6aecc8b 100644
--- a/public/docs/_examples/homepage-hello-world/ts/plnkr.json
+++ b/public/docs/_examples/homepage-hello-world/ts/plnkr.json
@@ -1,8 +1,9 @@
{
"description": "Hello World",
+ "basePath": "src/",
"files":[
- "!**/*.d.ts",
+ "!**/*.d.ts",
"!**/*.js",
"!**/*.[1].*"
]
-}
\ No newline at end of file
+}
diff --git a/public/docs/_examples/homepage-hello-world/ts/src/app/app.module.ts b/public/docs/_examples/homepage-hello-world/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..55a2ef3693
--- /dev/null
+++ b/public/docs/_examples/homepage-hello-world/ts/src/app/app.module.ts
@@ -0,0 +1,16 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { FormsModule } from '@angular/forms';
+
+import { HelloWorldComponent } from './hello_world';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ FormsModule
+ ],
+ declarations: [ HelloWorldComponent ],
+ bootstrap: [ HelloWorldComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/homepage-hello-world/ts/app/hello_world.html b/public/docs/_examples/homepage-hello-world/ts/src/app/hello_world.html
similarity index 100%
rename from public/docs/_examples/homepage-hello-world/ts/app/hello_world.html
rename to public/docs/_examples/homepage-hello-world/ts/src/app/hello_world.html
diff --git a/public/docs/_examples/homepage-hello-world/ts/src/app/hello_world.ts b/public/docs/_examples/homepage-hello-world/ts/src/app/hello_world.ts
new file mode 100644
index 0000000000..145d22e1e9
--- /dev/null
+++ b/public/docs/_examples/homepage-hello-world/ts/src/app/hello_world.ts
@@ -0,0 +1,15 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ // Declare the tag name in index.html to where the component attaches
+ selector: 'hello-world',
+
+ // Location of the template for this component
+ templateUrl: './hello_world.html'
+})
+export class HelloWorldComponent {
+
+ // Declaring the variable for binding with initial value
+ yourName: string = '';
+}
diff --git a/public/docs/_examples/homepage-hello-world/ts/src/index.1.html b/public/docs/_examples/homepage-hello-world/ts/src/index.1.html
new file mode 100644
index 0000000000..37c1bf787c
--- /dev/null
+++ b/public/docs/_examples/homepage-hello-world/ts/src/index.1.html
@@ -0,0 +1,32 @@
+
+
+
+
+ Angular Hello World
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
diff --git a/public/docs/_examples/homepage-hello-world/ts/src/index.html b/public/docs/_examples/homepage-hello-world/ts/src/index.html
new file mode 100644
index 0000000000..9dab660d10
--- /dev/null
+++ b/public/docs/_examples/homepage-hello-world/ts/src/index.html
@@ -0,0 +1,28 @@
+
+
+
+
+ Angular Hello World
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
diff --git a/public/docs/_examples/homepage-hello-world/ts/src/main.ts b/public/docs/_examples/homepage-hello-world/ts/src/main.ts
new file mode 100644
index 0000000000..6b6532d428
--- /dev/null
+++ b/public/docs/_examples/homepage-hello-world/ts/src/main.ts
@@ -0,0 +1,5 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/homepage-tabs/e2e-spec.js b/public/docs/_examples/homepage-tabs/e2e-spec.js
deleted file mode 100644
index 12f4f4bf53..0000000000
--- a/public/docs/_examples/homepage-tabs/e2e-spec.js
+++ /dev/null
@@ -1,14 +0,0 @@
-
-describe('Homepage Tabs', function () {
-
- beforeAll(function () {
- browser.get('');
- });
-
- // Does it even launch?
- var expectedAppTitle = 'Tabs Demo';
- it('should display app title: ' + expectedAppTitle, function () {
- expect(element(by.css('h4')).getText()).toEqual(expectedAppTitle);
- });
-
-});
diff --git a/public/docs/_examples/homepage-tabs/e2e-spec.ts b/public/docs/_examples/homepage-tabs/e2e-spec.ts
new file mode 100644
index 0000000000..2131d75906
--- /dev/null
+++ b/public/docs/_examples/homepage-tabs/e2e-spec.ts
@@ -0,0 +1,17 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by } from 'protractor';
+
+describe('Homepage Tabs', function () {
+
+ beforeAll(function () {
+ browser.get('');
+ });
+
+ // Does it even launch?
+ let expectedAppTitle = 'Tabs Demo';
+ it(`should display app title: ${expectedAppTitle}`, function () {
+ expect(element(by.css('h4')).getText()).toEqual(expectedAppTitle);
+ });
+
+});
diff --git a/public/docs/_examples/homepage-tabs/ts/.gitignore b/public/docs/_examples/homepage-tabs/ts/.gitignore
deleted file mode 100644
index 2cb7d2a2e9..0000000000
--- a/public/docs/_examples/homepage-tabs/ts/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-**/*.js
diff --git a/public/docs/_examples/homepage-tabs/ts/app/di_demo.ts b/public/docs/_examples/homepage-tabs/ts/app/di_demo.ts
deleted file mode 100644
index 96c4751771..0000000000
--- a/public/docs/_examples/homepage-tabs/ts/app/di_demo.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-// #docregion
-import {Component} from 'angular2/core';
-import {UiTabs, UiPane} from './ui_tabs';
-
-class Detail {
- title: string;
- text: string;
-}
-
-@Component({
- selector: 'di-demo',
- template: `
- Tabs Demo
-
-
- You have {{details.length}} details.
-
-
- {{detail.text}}
- Remove
-
-
- Next last ID is {{id}}.
-
-
-
- Add Detail
- `,
- directives: [UiTabs, UiPane]
-})
-export class DiDemo {
- details: Detail[] = [];
- id: number = 0;
-
- addDetail() {
- this.id++;
- this.details.push({
- title: `Detail ${this.id}`,
- text: `Some detail text for ${this.id}...`
- });
- }
-
- removeDetail(detail:Detail) {
- this.details = this.details.filter((d) => d !== detail);
- }
-}
-
diff --git a/public/docs/_examples/homepage-tabs/ts/app/main.ts b/public/docs/_examples/homepage-tabs/ts/app/main.ts
deleted file mode 100644
index 35eaece68e..0000000000
--- a/public/docs/_examples/homepage-tabs/ts/app/main.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-// #docregion
-import {bootstrap} from 'angular2/platform/browser';
-import {DiDemo} from './di_demo';
-
-bootstrap(DiDemo);
\ No newline at end of file
diff --git a/public/docs/_examples/homepage-tabs/ts/app/ui_tabs.ts b/public/docs/_examples/homepage-tabs/ts/app/ui_tabs.ts
deleted file mode 100644
index 63a3e87c54..0000000000
--- a/public/docs/_examples/homepage-tabs/ts/app/ui_tabs.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-// #docregion
-import {Component, Directive, Input, QueryList,
- ViewContainerRef, TemplateRef, ContentChildren} from 'angular2/core';
-
-@Directive({
- selector: '[ui-pane]'
-})
-export class UiPane {
- @Input() title: string;
- private _active:boolean = false;
-
- constructor(public viewContainer: ViewContainerRef,
- public templateRef: TemplateRef) { }
-
- @Input() set active(active: boolean) {
- if (active == this._active) return;
- this._active = active;
- if (active) {
- this.viewContainer.createEmbeddedView(this.templateRef);
- } else {
- this.viewContainer.remove(0);
- }
- }
-
- get active(): boolean {
- return this._active;
- }
-}
-
-@Component({
- selector: 'ui-tabs',
- template: `
-
-
- `,
- styles:['a { cursor: pointer; cursor: hand; }']
-})
-export class UiTabs {
- @ContentChildren(UiPane) panes: QueryList;
-
- select(pane: UiPane) {
- this.panes.toArray().forEach((p: UiPane) => p.active = p == pane);
- }
-}
-
diff --git a/public/docs/_examples/homepage-tabs/ts/index.1.html b/public/docs/_examples/homepage-tabs/ts/index.1.html
deleted file mode 100644
index 3878af0216..0000000000
--- a/public/docs/_examples/homepage-tabs/ts/index.1.html
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
-
- Angular 2 Tabs
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Loading...
-
-
-
\ No newline at end of file
diff --git a/public/docs/_examples/homepage-tabs/ts/index.html b/public/docs/_examples/homepage-tabs/ts/index.html
deleted file mode 100644
index 8cc7032da8..0000000000
--- a/public/docs/_examples/homepage-tabs/ts/index.html
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
- Angular 2 Tabs
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Loading...
-
-
-
\ No newline at end of file
diff --git a/public/docs/_examples/homepage-tabs/ts/plnkr.json b/public/docs/_examples/homepage-tabs/ts/plnkr.json
index 05ee7a2b9d..c1a33dc8f0 100644
--- a/public/docs/_examples/homepage-tabs/ts/plnkr.json
+++ b/public/docs/_examples/homepage-tabs/ts/plnkr.json
@@ -1,8 +1,9 @@
{
"description": "Tabs",
+ "basePath": "src/",
"files":[
- "!**/*.d.ts",
+ "!**/*.d.ts",
"!**/*.js",
"!**/*.[1].*"
]
-}
\ No newline at end of file
+}
diff --git a/public/docs/_examples/homepage-tabs/ts/src/app/app.module.ts b/public/docs/_examples/homepage-tabs/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..bd2193755c
--- /dev/null
+++ b/public/docs/_examples/homepage-tabs/ts/src/app/app.module.ts
@@ -0,0 +1,17 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+import { DiDemoComponent } from './di_demo';
+import { UiTabsComponent, UiPaneDirective } from './ui_tabs';
+
+@NgModule({
+ imports: [ BrowserModule ],
+ declarations: [
+ DiDemoComponent,
+ UiTabsComponent,
+ UiPaneDirective
+ ],
+ bootstrap: [ DiDemoComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/homepage-tabs/ts/src/app/di_demo.ts b/public/docs/_examples/homepage-tabs/ts/src/app/di_demo.ts
new file mode 100644
index 0000000000..be72ae5c79
--- /dev/null
+++ b/public/docs/_examples/homepage-tabs/ts/src/app/di_demo.ts
@@ -0,0 +1,45 @@
+// #docregion
+import { Component } from '@angular/core';
+
+class Detail {
+ title: string;
+ text: string;
+}
+
+@Component({
+ selector: 'di-demo',
+ template: `
+ Tabs Demo
+
+
+ You have {{details.length}} details.
+
+
+ {{detail.text}}
+ Remove
+
+
+ Next last ID is {{id}}.
+
+
+
+ Add Detail
+ `
+})
+export class DiDemoComponent {
+ details: Detail[] = [];
+ id: number = 0;
+
+ addDetail() {
+ this.id++;
+ this.details.push({
+ title: `Detail ${this.id}`,
+ text: `Some detail text for ${this.id}...`
+ });
+ }
+
+ removeDetail(detail: Detail) {
+ this.details = this.details.filter((d) => d !== detail);
+ }
+}
+
diff --git a/public/docs/_examples/homepage-tabs/ts/src/app/ui_tabs.ts b/public/docs/_examples/homepage-tabs/ts/src/app/ui_tabs.ts
new file mode 100644
index 0000000000..5e2f47b140
--- /dev/null
+++ b/public/docs/_examples/homepage-tabs/ts/src/app/ui_tabs.ts
@@ -0,0 +1,51 @@
+// #docregion
+import { Component, Directive, Input, QueryList,
+ ViewContainerRef, TemplateRef, ContentChildren } from '@angular/core';
+
+@Directive({
+ selector: '[uiPane]'
+})
+export class UiPaneDirective {
+ @Input() title: string;
+ private _active: boolean = false;
+
+ constructor(public viewContainer: ViewContainerRef,
+ public templateRef: TemplateRef) { }
+
+ @Input() set active(active: boolean) {
+ if (active === this._active) { return; }
+ this._active = active;
+ if (active) {
+ this.viewContainer.createEmbeddedView(this.templateRef);
+ } else {
+ this.viewContainer.remove(0);
+ }
+ }
+
+ get active(): boolean {
+ return this._active;
+ }
+}
+
+@Component({
+ selector: 'ui-tabs',
+ template: `
+
+
+ `,
+ styles: ['a { cursor: pointer; cursor: hand; }']
+})
+export class UiTabsComponent {
+ @ContentChildren(UiPaneDirective) panes: QueryList;
+
+ select(pane: UiPaneDirective) {
+ this.panes.toArray().forEach((p: UiPaneDirective) => p.active = p === pane);
+ }
+}
+
diff --git a/public/docs/_examples/homepage-tabs/ts/src/index.1.html b/public/docs/_examples/homepage-tabs/ts/src/index.1.html
new file mode 100644
index 0000000000..a25071b484
--- /dev/null
+++ b/public/docs/_examples/homepage-tabs/ts/src/index.1.html
@@ -0,0 +1,33 @@
+
+
+
+
+ Angular Tabs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
diff --git a/public/docs/_examples/homepage-tabs/ts/src/index.html b/public/docs/_examples/homepage-tabs/ts/src/index.html
new file mode 100644
index 0000000000..d38b36e033
--- /dev/null
+++ b/public/docs/_examples/homepage-tabs/ts/src/index.html
@@ -0,0 +1,29 @@
+
+
+
+
+ Angular Tabs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
diff --git a/public/docs/_examples/homepage-tabs/ts/src/main.ts b/public/docs/_examples/homepage-tabs/ts/src/main.ts
new file mode 100644
index 0000000000..f332d1d245
--- /dev/null
+++ b/public/docs/_examples/homepage-tabs/ts/src/main.ts
@@ -0,0 +1,6 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/homepage-todo/e2e-spec.js b/public/docs/_examples/homepage-todo/e2e-spec.js
deleted file mode 100644
index 4bc9b5f6a6..0000000000
--- a/public/docs/_examples/homepage-todo/e2e-spec.js
+++ /dev/null
@@ -1,14 +0,0 @@
-
-describe('Homepage Todo', function () {
-
- beforeAll(function () {
- browser.get('');
- });
-
- // Does it even launch?
- var expectedAppTitle = 'Todo';
- it('should display app title: ' + expectedAppTitle, function () {
- expect(element(by.css('h2')).getText()).toEqual(expectedAppTitle);
- });
-
-});
diff --git a/public/docs/_examples/homepage-todo/e2e-spec.ts b/public/docs/_examples/homepage-todo/e2e-spec.ts
new file mode 100644
index 0000000000..fb74e4e70f
--- /dev/null
+++ b/public/docs/_examples/homepage-todo/e2e-spec.ts
@@ -0,0 +1,17 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by } from 'protractor';
+
+describe('Homepage Todo', function () {
+
+ beforeAll(function () {
+ browser.get('');
+ });
+
+ // Does it even launch?
+ let expectedAppTitle = 'Todo';
+ it(`should display app title: ${expectedAppTitle}`, function () {
+ expect(element(by.css('h2')).getText()).toEqual(expectedAppTitle);
+ });
+
+});
diff --git a/public/docs/_examples/homepage-todo/ts/.gitignore b/public/docs/_examples/homepage-todo/ts/.gitignore
deleted file mode 100644
index 2cb7d2a2e9..0000000000
--- a/public/docs/_examples/homepage-todo/ts/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-**/*.js
diff --git a/public/docs/_examples/homepage-todo/ts/app/main.ts b/public/docs/_examples/homepage-todo/ts/app/main.ts
deleted file mode 100644
index 717623acdc..0000000000
--- a/public/docs/_examples/homepage-todo/ts/app/main.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-// #docregion
-import {bootstrap} from 'angular2/platform/browser';
-import {TodoApp} from './todo_app';
-
-bootstrap(TodoApp);
\ No newline at end of file
diff --git a/public/docs/_examples/homepage-todo/ts/app/todo.ts b/public/docs/_examples/homepage-todo/ts/app/todo.ts
deleted file mode 100644
index 57070dc72c..0000000000
--- a/public/docs/_examples/homepage-todo/ts/app/todo.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-// #docregion
-// Declare an interaface for type safety
-export interface Todo {
- text: string,
- done: boolean
-}
diff --git a/public/docs/_examples/homepage-todo/ts/app/todo_app.ts b/public/docs/_examples/homepage-todo/ts/app/todo_app.ts
deleted file mode 100644
index 5688868b73..0000000000
--- a/public/docs/_examples/homepage-todo/ts/app/todo_app.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-// #docregion
-import {Component} from 'angular2/core';
-import {Todo} from './todo';
-import {TodoList} from './todo_list';
-import {TodoForm} from './todo_form';
-
-@Component({
- selector: 'todo-app',
- template: `
- Todo
- {{remaining}} of {{todos.length}} remaining
- [ archive ]
-
-
- `,
- styles:['a { cursor: pointer; cursor: hand; }'],
- directives: [TodoList, TodoForm]
-})
-export class TodoApp {
- todos: Todo[] = [
- {text:'learn angular', done:true},
- {text:'build an angular app', done:false}
- ];
-
- get remaining() {
- return this.todos.reduce((count: number, todo: Todo) => count + +!todo.done, 0);
- }
-
- archive(): void {
- var oldTodos = this.todos;
- this.todos = [];
- oldTodos.forEach((todo: Todo) => {
- if (!todo.done) this.todos.push(todo);
- });
- }
-
- addTask(task: Todo) {
- this.todos.push(task);
- }
-}
diff --git a/public/docs/_examples/homepage-todo/ts/app/todo_form.ts b/public/docs/_examples/homepage-todo/ts/app/todo_form.ts
deleted file mode 100644
index 29117525ff..0000000000
--- a/public/docs/_examples/homepage-todo/ts/app/todo_form.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-// #docregion
-import {Component, Output, EventEmitter} from 'angular2/core';
-import {Todo} from './todo';
-
-@Component({
- selector: 'todo-form',
- template: `
- `
-})
-export class TodoForm {
- @Output() newTask = new EventEmitter();
- task: string = '';
-
- addTodo() {
- if (this.task) {
- this.newTask.next({text:this.task, done:false});
- }
- this.task = '';
- }
-}
-
diff --git a/public/docs/_examples/homepage-todo/ts/app/todo_list.ts b/public/docs/_examples/homepage-todo/ts/app/todo_list.ts
deleted file mode 100644
index f680832b23..0000000000
--- a/public/docs/_examples/homepage-todo/ts/app/todo_list.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-// #docregion
-import {Component, Input} from 'angular2/core';
-import {Todo} from './todo';
-
-@Component({
- selector: 'todo-list',
- styles: [`
- .done-true {
- text-decoration: line-through;
- color: grey;
- }`
- ],
- template: `
- `
-})
-export class TodoList {
- @Input() todos: Todo[];
-}
diff --git a/public/docs/_examples/homepage-todo/ts/index.1.html b/public/docs/_examples/homepage-todo/ts/index.1.html
deleted file mode 100644
index 76cf01f802..0000000000
--- a/public/docs/_examples/homepage-todo/ts/index.1.html
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
-
- Angular 2 Todos
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Loading...
-
-
-
\ No newline at end of file
diff --git a/public/docs/_examples/homepage-todo/ts/index.html b/public/docs/_examples/homepage-todo/ts/index.html
deleted file mode 100644
index c0796e4ff2..0000000000
--- a/public/docs/_examples/homepage-todo/ts/index.html
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
- Angular 2 Todos
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Loading...
-
-
-
\ No newline at end of file
diff --git a/public/docs/_examples/homepage-todo/ts/plnkr.json b/public/docs/_examples/homepage-todo/ts/plnkr.json
index 7fecc539f7..8e69701221 100644
--- a/public/docs/_examples/homepage-todo/ts/plnkr.json
+++ b/public/docs/_examples/homepage-todo/ts/plnkr.json
@@ -1,8 +1,9 @@
{
"description": "Todo",
+ "basePath": "src/",
"files":[
- "!**/*.d.ts",
+ "!**/*.d.ts",
"!**/*.js",
"!**/*.[1].*"
]
-}
\ No newline at end of file
+}
diff --git a/public/docs/_examples/homepage-todo/ts/src/app/app.module.ts b/public/docs/_examples/homepage-todo/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..a77bb640ab
--- /dev/null
+++ b/public/docs/_examples/homepage-todo/ts/src/app/app.module.ts
@@ -0,0 +1,22 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { FormsModule } from '@angular/forms';
+
+import { TodoAppComponent } from './todo_app';
+import { TodoListComponent } from './todo_list';
+import { TodoFormComponent } from './todo_form';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ FormsModule
+ ],
+ declarations: [
+ TodoAppComponent,
+ TodoListComponent,
+ TodoFormComponent
+ ],
+ bootstrap: [ TodoAppComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/homepage-todo/ts/src/app/todo.ts b/public/docs/_examples/homepage-todo/ts/src/app/todo.ts
new file mode 100644
index 0000000000..35faec9705
--- /dev/null
+++ b/public/docs/_examples/homepage-todo/ts/src/app/todo.ts
@@ -0,0 +1,6 @@
+// #docregion
+// Declare an interaface for type safety
+export interface Todo {
+ text: string;
+ done: boolean;
+}
diff --git a/public/docs/_examples/homepage-todo/ts/src/app/todo_app.ts b/public/docs/_examples/homepage-todo/ts/src/app/todo_app.ts
new file mode 100644
index 0000000000..e56bad95b6
--- /dev/null
+++ b/public/docs/_examples/homepage-todo/ts/src/app/todo_app.ts
@@ -0,0 +1,38 @@
+// #docregion
+import { Component } from '@angular/core';
+
+import { Todo } from './todo';
+
+@Component({
+ selector: 'todo-app',
+ template: `
+ Todo
+ {{remaining}} of {{todos.length}} remaining
+ [ archive ]
+
+
+ `,
+ styles: ['a { cursor: pointer; cursor: hand; }']
+})
+export class TodoAppComponent {
+ todos: Todo[] = [
+ {text: 'learn angular', done: true},
+ {text: 'build an angular app', done: false}
+ ];
+
+ get remaining() {
+ return this.todos.filter(todo => !todo.done).length;
+ }
+
+ archive(): void {
+ let oldTodos = this.todos;
+ this.todos = [];
+ oldTodos.forEach(todo => {
+ if (!todo.done) { this.todos.push(todo); }
+ });
+ }
+
+ addTask(task: Todo) {
+ this.todos.push(task);
+ }
+}
diff --git a/public/docs/_examples/homepage-todo/ts/src/app/todo_form.ts b/public/docs/_examples/homepage-todo/ts/src/app/todo_form.ts
new file mode 100644
index 0000000000..38e8d991a7
--- /dev/null
+++ b/public/docs/_examples/homepage-todo/ts/src/app/todo_form.ts
@@ -0,0 +1,25 @@
+// #docregion
+import { Component, Output, EventEmitter } from '@angular/core';
+import { Todo } from './todo';
+
+@Component({
+ selector: 'todo-form',
+ template: `
+ `
+})
+export class TodoFormComponent {
+ @Output() newTask = new EventEmitter();
+ task: string = '';
+
+ addTodo() {
+ if (this.task) {
+ this.newTask.emit({text: this.task, done: false});
+ }
+ this.task = '';
+ }
+}
+
diff --git a/public/docs/_examples/homepage-todo/ts/src/app/todo_list.ts b/public/docs/_examples/homepage-todo/ts/src/app/todo_list.ts
new file mode 100644
index 0000000000..b6495f37c2
--- /dev/null
+++ b/public/docs/_examples/homepage-todo/ts/src/app/todo_list.ts
@@ -0,0 +1,24 @@
+// #docregion
+import { Component, Input } from '@angular/core';
+
+import { Todo } from './todo';
+
+@Component({
+ selector: 'todo-list',
+ styles: [`
+ .done-true {
+ text-decoration: line-through;
+ color: grey;
+ }`
+ ],
+ template: `
+ `
+})
+export class TodoListComponent {
+ @Input() todos: Todo[];
+}
diff --git a/public/docs/_examples/homepage-todo/ts/src/index.1.html b/public/docs/_examples/homepage-todo/ts/src/index.1.html
new file mode 100644
index 0000000000..4e8d034fd3
--- /dev/null
+++ b/public/docs/_examples/homepage-todo/ts/src/index.1.html
@@ -0,0 +1,33 @@
+
+
+
+
+ Angular Todos
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
diff --git a/public/docs/_examples/homepage-todo/ts/src/index.html b/public/docs/_examples/homepage-todo/ts/src/index.html
new file mode 100644
index 0000000000..e7a656a106
--- /dev/null
+++ b/public/docs/_examples/homepage-todo/ts/src/index.html
@@ -0,0 +1,29 @@
+
+
+
+
+ Angular Todos
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
diff --git a/public/docs/_examples/homepage-todo/ts/src/main.ts b/public/docs/_examples/homepage-todo/ts/src/main.ts
new file mode 100644
index 0000000000..6b6532d428
--- /dev/null
+++ b/public/docs/_examples/homepage-todo/ts/src/main.ts
@@ -0,0 +1,5 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/karma-test-shim.js b/public/docs/_examples/karma-test-shim.js
deleted file mode 100644
index 8ccb27a727..0000000000
--- a/public/docs/_examples/karma-test-shim.js
+++ /dev/null
@@ -1,68 +0,0 @@
-// Tun on full stack traces in errors to help debugging
-Error.stackTraceLimit=Infinity;
-
-
-jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;
-
-// // Cancel Karma's synchronous start,
-// // we will call `__karma__.start()` later, once all the specs are loaded.
-__karma__.loaded = function() {};
-
-
-System.config({
- packages: {
- 'base/app': {
- defaultExtension: false,
- // removed because of issues with raw .js files not being found.
- // format: 'register',
- map: Object.keys(window.__karma__.files).
- filter(onlyAppFiles).
- reduce(function createPathRecords(pathsMapping, appPath) {
- // creates local module name mapping to global path with karma's fingerprint in path, e.g.:
- // './hero.service': '/base/src/app/hero.service.js?f4523daf879cfb7310ef6242682ccf10b2041b3e'
- var moduleName = appPath.replace(/^\/base\/app\//, './').replace(/\.js$/, '');
- pathsMapping[moduleName] = appPath + '?' + window.__karma__.files[appPath]
- return pathsMapping;
- }, {})
-
- }
- }
-});
-
-// old code from angular 44
-// System.import('angular2/src/core/dom/browser_adapter').then(function(browser_adapter) {
-// new path for angular 51
-System.import('angular2/src/platform/browser/browser_adapter').then(function(browser_adapter) {
- browser_adapter.BrowserDomAdapter.makeCurrent();
-}).then(function() {
- return Promise.all(
- Object.keys(window.__karma__.files) // All files served by Karma.
- .filter(onlySpecFiles)
- // .map(filePath2moduleName) // Normalize paths to module names.
- .map(function(moduleName) {
- // loads all spec files via their global module names (e.g. 'base/src/app/hero.service.spec')
- return System.import(moduleName);
- }));
-})
-.then(function() {
- __karma__.start();
-}, function(error) {
- __karma__.error(error.stack || error);
-});
-
-
-function filePath2moduleName(filePath) {
- return filePath.
- replace(/^\//, ''). // remove / prefix
- replace(/\.\w+$/, ''); // remove suffix
-}
-
-
-function onlyAppFiles(filePath) {
- return /^\/base\/app\/.*\.js$/.test(filePath) && !onlySpecFiles(filePath);
-}
-
-
-function onlySpecFiles(filePath) {
- return /\.spec\.js$/.test(filePath);
-}
diff --git a/public/docs/_examples/karma.conf.js b/public/docs/_examples/karma.conf.js
deleted file mode 100644
index 5b07bee380..0000000000
--- a/public/docs/_examples/karma.conf.js
+++ /dev/null
@@ -1,43 +0,0 @@
-module.exports = function(config) {
- config.set({
-
- basePath: '',
-
- frameworks: ['jasmine'],
-
- files: [
- // paths loaded by Karma
- {pattern: 'node_modules/systemjs/dist/system.src.js', included: true, watched: true},
- {pattern: 'node_modules/angular2/bundles/angular2.js', included: true, watched: true},
- {pattern: 'node_modules/angular2/bundles/testing.js', included: true, watched: true},
- {pattern: 'karma-test-shim.js', included: true, watched: true},
- {pattern: 'app/test/*.js', included: true, watched: true},
-
- // paths loaded via module imports
- {pattern: 'app/**/*.js', included: false, watched: true},
-
- // paths loaded via Angular's component compiler
- // (these paths need to be rewritten, see proxies section)
- {pattern: 'app/**/*.html', included: false, watched: true},
- {pattern: 'app/**/*.css', included: false, watched: true},
-
- // paths to support debugging with source maps in dev tools
- {pattern: 'app/**/*.ts', included: false, watched: false},
- {pattern: 'app/**/*.js.map', included: false, watched: false}
- ],
-
- // proxied base paths
- proxies: {
- // required for component assests fetched by Angular's compiler
- "/app/": "/base/app/"
- },
-
- reporters: ['progress'],
- port: 9877,
- colors: true,
- logLevel: config.LOG_INFO,
- autoWatch: true,
- browsers: ['Chrome'],
- singleRun: true
- })
-}
diff --git a/public/docs/_examples/karma.js.conf.js b/public/docs/_examples/karma.js.conf.js
deleted file mode 100644
index e55127f0f0..0000000000
--- a/public/docs/_examples/karma.js.conf.js
+++ /dev/null
@@ -1,68 +0,0 @@
-// Karma configuration
-// Generated on Mon Aug 10 2015 11:36:40 GMT-0700 (Pacific Daylight Time)
-
-module.exports = function(config) {
- config.set({
-
- // base path that will be used to resolve all patterns (eg. files, exclude)
- basePath: '',
-
-
- // frameworks to use
- // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
- frameworks: ['jasmine'],
-
-
- // list of files / patterns to load in the browser
- files: [
- { pattern: 'https://code.angularjs.org/2.0.0-alpha.34/angular2.sfx.dev.js', watched: false },
-
- '**/js/*.js',
- ],
-
-
- // list of files to exclude
- exclude: [
- '**/*.e2e-spec.js'
- ],
-
-
- // preprocess matching files before serving them to the browser
- // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
- preprocessors: {
- },
-
-
- // test results reporter to use
- // possible values: 'dots', 'progress'
- // available reporters: https://npmjs.org/browse/keyword/karma-reporter
- reporters: ['progress'],
-
-
- // web server port
- port: 9876,
-
-
- // enable / disable colors in the output (reporters and logs)
- colors: true,
-
-
- // level of logging
- // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
- logLevel: config.LOG_INFO,
-
-
- // enable / disable watching file and executing tests whenever any file changes
- autoWatch: true,
-
-
- // start these browsers
- // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
- browsers: ['Chrome'],
-
-
- // Continuous Integration mode
- // if true, Karma captures browsers, runs the tests and exits
- singleRun: false
- })
-}
diff --git a/public/docs/_examples/karma.ts.conf.js b/public/docs/_examples/karma.ts.conf.js
deleted file mode 100644
index 5b2d176b56..0000000000
--- a/public/docs/_examples/karma.ts.conf.js
+++ /dev/null
@@ -1,70 +0,0 @@
-// Karma configuration
-// Generated on Mon Aug 10 2015 11:36:40 GMT-0700 (Pacific Daylight Time)
-
-module.exports = function(config) {
- config.set({
-
- // base path that will be used to resolve all patterns (eg. files, exclude)
- basePath: '',
-
-
- // frameworks to use
- // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
- frameworks: ['jasmine'],
-
-
- // list of files / patterns to load in the browser
- files: [
- { pattern: 'https://github.jspm.io/jmcriffey/bower-traceur-runtime@0.0.87/traceur-runtime.js', watched: false },
- { pattern: 'https://jspm.io/system@0.16.js', watched: false },
- { pattern: 'https://code.angularjs.org/2.0.0-alpha.34/angular2.dev.js', watched: false },
-
- '**/ts/**/*.spec.js'
- ],
-
-
- // list of files to exclude
- exclude: [
- '**/*.e2e-spec.js'
- ],
-
-
- // preprocess matching files before serving them to the browser
- // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
- preprocessors: {
- },
-
-
- // test results reporter to use
- // possible values: 'dots', 'progress'
- // available reporters: https://npmjs.org/browse/keyword/karma-reporter
- reporters: ['progress'],
-
-
- // web server port
- port: 9876,
-
-
- // enable / disable colors in the output (reporters and logs)
- colors: true,
-
-
- // level of logging
- // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
- logLevel: config.LOG_INFO,
-
-
- // enable / disable watching file and executing tests whenever any file changes
- autoWatch: true,
-
-
- // start these browsers
- // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
- browsers: ['Chrome'],
-
-
- // Continuous Integration mode
- // if true, Karma captures browsers, runs the tests and exits
- singleRun: false
- })
-}
diff --git a/public/docs/_examples/lifecycle-hooks/dart/lib/after_content_parent.dart b/public/docs/_examples/lifecycle-hooks/dart/lib/after_content_parent.dart
deleted file mode 100644
index bffea129ab..0000000000
--- a/public/docs/_examples/lifecycle-hooks/dart/lib/after_content_parent.dart
+++ /dev/null
@@ -1,95 +0,0 @@
-// #docregion
-import 'package:angular2/angular2.dart';
-
-import 'child_component.dart';
-import 'logger_service.dart';
-
-@Component(
- selector: 'after-content',
- template: '''
-
-
-- child content begins --
-
-
-
-
-- child content ends --
-
- ''',
- styles: const ['.after-content {background: LightCyan; padding: 8px;}'])
-class AfterContentComponent
- implements AfterContentChecked, AfterContentInit, AfterViewInit {
- LoggerService _logger;
-
- // Query for a CONTENT child of type `ChildComponent`
- @ContentChild(ChildComponent) ChildComponent contentChild;
-
- // Query for a VIEW child of type`ChildComponent`
- // No such VIEW child exists!
- // This component holds content but no view of that type.
- @ViewChild(ChildComponent) ChildComponent viewChild;
-
- String _prevHero;
-
- AfterContentComponent(this._logger) {
- _logger.log('AfterContent ctor: $message');
- }
-
- ///// Hooks
- ngAfterContentInit() {
- // contentChild is set after the content has been initialized
- _logger.log('AfterContentInit: $message');
- }
-
- get hasViewChild => viewChild != null;
-
- ngAfterViewInit() {
- _logger
- .log('AfterViewInit: There is ${hasViewChild ? 'a' : 'no'} view child');
- }
-
- ngAfterContentChecked() {
- // contentChild is updated after the content has been checked
- // Called frequently; only report when the hero changes
- if (!hasContentChild || _prevHero == contentChild.hero) return;
- _prevHero = contentChild.hero;
- _logger.log('AfterContentChecked: $message');
- }
-
- bool get hasContentChild => contentChild != null;
-
- String get message => hasContentChild
- ? '"${contentChild.hero}" child content'
- : 'no child content';
-}
-
-@Component(
- selector: 'after-content-parent',
- template: '''
-
-
AfterContent
-
-
-
- Toggle child view
-
-
-
-
-
-- Lifecycle Hook Log --
-
{{msg}}
-
- ''',
- styles: const [
- '.parent {background: powderblue; padding: 8px; margin:100px 8px;}'
- ],
- directives: const [AfterContentComponent, ChildComponent],
- providers: const [LoggerService])
-class AfterContentParentComponent {
- List hookLog;
- String hero = 'Magneta';
- bool showChild = true;
-
- AfterContentParentComponent(LoggerService logger) {
- hookLog = logger.logs;
- }
-}
diff --git a/public/docs/_examples/lifecycle-hooks/dart/lib/after_view_component.dart b/public/docs/_examples/lifecycle-hooks/dart/lib/after_view_component.dart
deleted file mode 100644
index 505571a679..0000000000
--- a/public/docs/_examples/lifecycle-hooks/dart/lib/after_view_component.dart
+++ /dev/null
@@ -1,77 +0,0 @@
-// #docregion
-import 'package:angular2/angular2.dart';
-
-import 'child_component.dart';
-import 'logger_service.dart';
-
-@Component(
- selector: 'after-view-parent',
- template: '''
-
-
AfterView
-
-
-
- Toggle child view
-
-
-
-
-
-- Lifecycle Hook Log --
-
{{msg}}
-
- ''',
- styles: const [
- '.parent {background: burlywood; padding: 8px; margin:100px 8px;}'
- ],
- directives: const [ChildComponent],
- providers: const [LoggerService])
-class AfterViewParentComponent
- implements AfterContentInit, AfterViewChecked, AfterViewInit {
- LoggerService _logger;
- List hookLog;
- String hero = 'Magneta';
- bool showChild = true;
-
- // Query for a CONTENT child of type `ChildComponent`
- // No such CONTENT child exists!
- // This component holds a view but no content of that type.
- @ContentChild(ChildComponent)
- ChildComponent contentChild;
-
- // Query for a VIEW child of type `ChildComponent`
- @ViewChild(ChildComponent)
- ChildComponent viewChild;
-
- String _prevHero;
-
- AfterViewParentComponent(this._logger) {
- hookLog = _logger.logs;
- _logger.log('AfterView ctor: $message');
- }
-
- bool get _hasContentChild => contentChild != null;
- bool get _hasViewChild => viewChild != null;
-
- ///// Hooks
- ngAfterContentInit() {
- _logger.log(
- 'AfterContentInit: There is ${ _hasContentChild ? 'a' : 'no'} content child');
- }
-
- ngAfterViewInit() {
- // viewChild is set after the view has been initialized
- _logger.log('AfterViewInit: $message');
- }
-
- ngAfterViewChecked() {
- // viewChild is updated after the view has been checked
- // Called frequently; only report when the hero changes
- if (!_hasViewChild || _prevHero == viewChild.hero) return;
- _prevHero = viewChild.hero;
- _logger.log('AfterViewChecked: $message');
- }
-
- String get message =>
- _hasViewChild ? '"${viewChild.hero}" child view' : 'no child view';
-}
diff --git a/public/docs/_examples/lifecycle-hooks/dart/lib/app_component.dart b/public/docs/_examples/lifecycle-hooks/dart/lib/app_component.dart
deleted file mode 100644
index dff8c59cf1..0000000000
--- a/public/docs/_examples/lifecycle-hooks/dart/lib/app_component.dart
+++ /dev/null
@@ -1,29 +0,0 @@
-// #docregion
-import 'package:angular2/angular2.dart';
-
-import 'after_content_parent.dart';
-import 'after_view_component.dart';
-import 'counter_component.dart';
-import 'on_changes_component.dart';
-import 'peek_a_boo_parent_component.dart';
-import 'spy_component.dart';
-
-@Component(
- selector: 'my-app',
- template: '''
-
-
-
-
-
-
- ''',
- directives: const [
- PeekABooParentComponent,
- OnChangesParentComponent,
- AfterViewParentComponent,
- AfterContentParentComponent,
- SpyParentComponent,
- CounterParentComponent
- ])
-class AppComponent {}
diff --git a/public/docs/_examples/lifecycle-hooks/dart/lib/child_component.dart b/public/docs/_examples/lifecycle-hooks/dart/lib/child_component.dart
deleted file mode 100644
index dc43e899dc..0000000000
--- a/public/docs/_examples/lifecycle-hooks/dart/lib/child_component.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-// #docregion
-import 'package:angular2/angular2.dart';
-
-@Component(
- selector: 'my-child',
- template: '''
-
-
-- child view begins --
-
{{hero}} is my hero.
-
-- child view ends --
-
- ''',
- styles: const [
- '.child {background: Yellow; padding: 8px; }',
- '.my-child {background: LightYellow; padding: 8px; margin-top: 8px}'
- ])
-class ChildComponent {
- @Input() String hero;
-}
diff --git a/public/docs/_examples/lifecycle-hooks/dart/lib/counter_component.dart b/public/docs/_examples/lifecycle-hooks/dart/lib/counter_component.dart
deleted file mode 100644
index 0aaf2b155f..0000000000
--- a/public/docs/_examples/lifecycle-hooks/dart/lib/counter_component.dart
+++ /dev/null
@@ -1,77 +0,0 @@
-// #docregion
-import 'package:angular2/angular2.dart';
-
-import 'logger_service.dart';
-import 'spy_directive.dart';
-
-@Component(
- selector: 'my-counter',
- template: '''
-
- Counter = {{counter}}
-
-
-- Counter Change Log --
-
{{chg}}
-
- ''',
- styles: const [
- '.counter {background: LightYellow; padding: 8px; margin-top: 8px}'
- ],
- directives: const [Spy])
-class MyCounter implements OnChanges {
- @Input() num counter;
- List changeLog = [];
-
- ngOnChanges(Map changes) {
- // Empty the changeLog whenever counter goes to zero
- // hint: this is a way to respond programmatically to external value changes.
- if (this.counter == 0) {
- changeLog.clear();
- }
-
- // A change to `counter` is the only change we care about
- SimpleChange prop = changes['counter'];
- var prev = prop.isFirstChange() ? "{}" : prop.previousValue;
- changeLog.add(
- 'counter: currentValue = ${prop.currentValue}, previousValue = $prev');
- }
-}
-
-@Component(
- selector: 'counter-parent',
- template: '''
-
-
Counter Spy
-
-
Update counter
-
Reset Counter
-
-
-
-
-- Spy Lifecycle Hook Log --
-
{{msg}}
-
- ''',
- styles: const [
- '.parent {background: gold; padding: 10px; margin:100px 8px;}'
- ],
- directives: const [MyCounter],
- providers: const [LoggerService])
-class CounterParentComponent {
- num value;
- List spyLog = [];
-
- LoggerService _logger;
-
- CounterParentComponent(this._logger) {
- spyLog = _logger.logs;
- reset();
- }
-
- updateCounter() => value += 1;
-
- reset() {
- _logger.log('-- reset --');
- value = 0;
- }
-}
diff --git a/public/docs/_examples/lifecycle-hooks/dart/lib/logger_service.dart b/public/docs/_examples/lifecycle-hooks/dart/lib/logger_service.dart
deleted file mode 100644
index 51fe44cb39..0000000000
--- a/public/docs/_examples/lifecycle-hooks/dart/lib/logger_service.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-import 'dart:async';
-
-import 'package:angular2/angular2.dart';
-
-@Injectable()
-class LoggerService {
- List logs = [];
-
- log(String msg, [bool noTick = false]) {
- if (!noTick) {
- tick();
- }
- logs.add(msg);
- }
-
- clear() => logs.clear();
-
- tick() => new Future(() {});
-}
diff --git a/public/docs/_examples/lifecycle-hooks/dart/lib/on_changes_component.dart b/public/docs/_examples/lifecycle-hooks/dart/lib/on_changes_component.dart
deleted file mode 100644
index 34389ddb2e..0000000000
--- a/public/docs/_examples/lifecycle-hooks/dart/lib/on_changes_component.dart
+++ /dev/null
@@ -1,81 +0,0 @@
-// #docregion
-import 'dart:convert';
-
-import 'package:angular2/angular2.dart';
-
-class Hero {
- String name;
- Hero(this.name);
-
- Map toJson() => {'name': name};
-}
-
-@Component(
- selector: 'my-hero',
- template: '''
-
-
{{hero.name}} can {{power}}
-
-
-- Change Log --
-
{{chg}}
-
- ''',
- styles: const [
- '.hero {background: LightYellow; padding: 8px; margin-top: 8px}',
- 'p {background: Yellow; padding: 8px; margin-top: 8px}'
- ])
-class MyHeroComponent implements OnChanges {
- @Input() Hero hero;
- @Input() String power;
- @Input() bool reset;
- List changeLog = [];
-
- ngOnChanges(Map changes) {
- // Empty the changeLog whenever 'reset' property changes
- // hint: this is a way to respond programmatically to external value changes.
- if (changes.containsKey('reset')) changeLog.clear();
-
- changes.forEach((String key, SimpleChange change) {
- String cur = JSON.encode(change.currentValue);
- String prev =
- change.isFirstChange() ? "{}" : JSON.encode(change.previousValue);
- changeLog.add('$key: currentValue = ${cur}, previousValue = $prev');
- });
- }
-}
-
-@Component(
- selector: 'on-changes-parent',
- template: '''
-
-
OnChanges
-
-
Hero.name: does NOT trigger onChanges
-
Power: DOES trigger onChanges
-
Reset Log triggers onChanges and clears the change log
-
-
-
- ''',
- styles: const [
- '.parent {background: Lavender; padding: 10px; margin:100px 8px;}'
- ],
- directives: const [MyHeroComponent])
-class OnChangesParentComponent {
- Hero hero;
- String power;
- bool resetTrigger = false;
-
- OnChangesParentComponent() {
- reset();
- }
-
- reset() {
- // new Hero object every time; triggers onChange
- hero = new Hero('Windstorm');
- // setting power only triggers onChange if this value is different
- power = 'sing';
- // always triggers onChange ... which is interpreted as a reset
- resetTrigger = !resetTrigger;
- }
-}
diff --git a/public/docs/_examples/lifecycle-hooks/dart/lib/peek_a_boo_component.dart b/public/docs/_examples/lifecycle-hooks/dart/lib/peek_a_boo_component.dart
deleted file mode 100644
index 5315e3cd44..0000000000
--- a/public/docs/_examples/lifecycle-hooks/dart/lib/peek_a_boo_component.dart
+++ /dev/null
@@ -1,78 +0,0 @@
-// #docregion
-// #docregion lc-imports
-import 'package:angular2/angular2.dart';
-
-import 'logger_service.dart';
-
-int nextId = 1;
-
-@Component(
- selector: 'peek-a-boo',
- template: 'Now you see my hero, {{name}}
',
- styles: const ['p {background: LightYellow; padding: 8px}'])
-class PeekABooComponent
- implements
- OnChanges,
- OnInit,
- AfterContentInit,
- AfterContentChecked,
- AfterViewInit,
- AfterViewChecked,
- OnDestroy {
- @Input() String name;
-
- int _afterContentCheckedCounter = 1;
- int _afterViewCheckedCounter = 1;
- int _id = nextId++;
- LoggerService _logger;
- int _onChangesCounter = 1;
- String _verb = 'initialized';
-
- PeekABooComponent(this._logger);
-
- // Only called if there is an @input variable set by parent.
- ngOnChanges(Map changes) {
- List messages = [];
- changes.forEach((String propName, SimpleChange change) {
- if (propName == 'name') {
- var name = changes['name'].currentValue;
- messages.add('name $_verb to "$name"');
- } else {
- messages.add('$propName $_verb');
- }
- });
- _logIt('onChanges (${_onChangesCounter++}): ${messages.join('; ')}');
- _verb = 'changed'; // Next time it will be a change
- }
-
- ngOnInit() => _logIt('onInit');
-
- ngAfterContentInit() => _logIt('afterContentInit');
-
- // Called after every change detection check
- // of the component (directive) CONTENT
- // Beware! Called frequently!
- ngAfterContentChecked() {
- int counter = _afterContentCheckedCounter++;
- _logIt('afterContentChecked (${counter})');
- }
-
- ngAfterViewInit() => _logIt('afterViewInit');
-
- // Called after every change detection check
- // of the component (directive) VIEW
- // Beware! Called frequently!
- ngAfterViewChecked() {
- int counter = _afterViewCheckedCounter++;
- _logIt('afterViewChecked ($counter)');
- }
-
- ngOnDestroy() => _logIt('onDestroy');
-
- _logIt(String msg) {
- // Don't tick or else
- // the AfterContentChecked and AfterViewChecked recurse.
- // Let parent call tick()
- _logger.log("#$_id $msg", true);
- }
-}
diff --git a/public/docs/_examples/lifecycle-hooks/dart/lib/peek_a_boo_parent_component.dart b/public/docs/_examples/lifecycle-hooks/dart/lib/peek_a_boo_parent_component.dart
deleted file mode 100644
index d9cdfa68bf..0000000000
--- a/public/docs/_examples/lifecycle-hooks/dart/lib/peek_a_boo_parent_component.dart
+++ /dev/null
@@ -1,54 +0,0 @@
-// #docregion
-import 'package:angular2/angular2.dart';
-
-import 'logger_service.dart';
-import 'peek_a_boo_component.dart';
-
-@Component(
- selector: 'peek-a-boo-parent',
- template: '''
-
-
Peek-A-Boo
-
-
- {{hasChild ? 'Destroy' : 'Create'}} PeekABooComponent
-
-
Update Hero
-
-
-
-
-
-- Lifecycle Hook Log --
-
{{msg}}
-
- ''',
- styles: const [
- '.parent {background: moccasin; padding: 10px; margin:100px 8px}'
- ],
- directives: const [PeekABooComponent],
- providers: const [LoggerService])
-class PeekABooParentComponent {
- bool hasChild = false;
- List hookLog;
-
- String heroName = 'Windstorm';
- LoggerService _logger;
-
- PeekABooParentComponent(this._logger) {
- hookLog = _logger.logs;
- }
-
- toggleChild() {
- hasChild = !hasChild;
- if (hasChild) {
- heroName = 'Windstorm';
- _logger.clear(); // clear log on create
- }
- _logger.tick();
- }
-
- updateHero() {
- heroName += '!';
- _logger.tick();
- }
-}
diff --git a/public/docs/_examples/lifecycle-hooks/dart/lib/spy_component.dart b/public/docs/_examples/lifecycle-hooks/dart/lib/spy_component.dart
deleted file mode 100644
index b5db1d0059..0000000000
--- a/public/docs/_examples/lifecycle-hooks/dart/lib/spy_component.dart
+++ /dev/null
@@ -1,53 +0,0 @@
-// #docregion
-import 'package:angular2/angular2.dart';
-
-import 'logger_service.dart';
-import 'spy_directive.dart';
-
-@Component(
- selector: 'spy-parent',
- template: '''
-
-
Spy Directive
-
-
-
Add Hero
-
Reset Heroes
-
-
-
- {{hero}}
-
-
-
-- Spy Lifecycle Hook Log --
-
{{msg}}
-
- ''',
- styles: const [
- '.parent {background: khaki; padding: 10px; margin:100px 8px}',
- '.heroes {background: LightYellow; padding: 0 8px}'
- ],
- directives: const [Spy],
- providers: const [LoggerService])
-class SpyParentComponent {
- String newName = 'Herbie';
- List heroes = ['Windstorm', 'Magneta'];
- List spyLog;
- LoggerService _logger;
-
- SpyParentComponent(this._logger) {
- spyLog = _logger.logs;
- }
-
- addHero() {
- if (newName.trim().isNotEmpty) {
- heroes.add(newName.trim());
- newName = '';
- }
- }
-
- reset() {
- _logger.log('-- reset --');
- heroes.clear();
- }
-}
diff --git a/public/docs/_examples/lifecycle-hooks/dart/lib/spy_directive.dart b/public/docs/_examples/lifecycle-hooks/dart/lib/spy_directive.dart
deleted file mode 100644
index 84e5937a56..0000000000
--- a/public/docs/_examples/lifecycle-hooks/dart/lib/spy_directive.dart
+++ /dev/null
@@ -1,22 +0,0 @@
-// #docregion
-import 'package:angular2/angular2.dart';
-
-import 'logger_service.dart';
-
-int nextId = 1;
-
-// Spy on any element to which it is applied.
-// Usage: ...
-@Directive(selector: '[mySpy]')
-class Spy implements OnInit, OnDestroy {
- int _id = nextId++;
- LoggerService _logger;
-
- Spy(this._logger);
-
- ngOnInit() => _logIt('onInit');
-
- ngOnDestroy() => _logIt('onDestroy');
-
- _logIt(String msg) => _logger.log('Spy #$_id $msg');
-}
diff --git a/public/docs/_examples/lifecycle-hooks/dart/pubspec.yaml b/public/docs/_examples/lifecycle-hooks/dart/pubspec.yaml
deleted file mode 100644
index 2d60856b8c..0000000000
--- a/public/docs/_examples/lifecycle-hooks/dart/pubspec.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-# #docregion
-name: lifecycle_hooks
-description: Lifecycle Hooks
-version: 0.0.1
-environment:
- sdk: '>=1.13.0 <2.0.0'
-dependencies:
- angular2: 2.0.0-beta.8
- browser: ^0.10.0
- dart_to_js_script_rewriter: ^0.1.0
-transformers:
-- angular2:
- platform_directives:
- - 'package:angular2/common.dart#CORE_DIRECTIVES'
- - 'package:angular2/common.dart#FORM_DIRECTIVES'
- entry_points: web/main.dart
-- dart_to_js_script_rewriter
diff --git a/public/docs/_examples/lifecycle-hooks/dart/web/index.html b/public/docs/_examples/lifecycle-hooks/dart/web/index.html
deleted file mode 100644
index ae668dd2e9..0000000000
--- a/public/docs/_examples/lifecycle-hooks/dart/web/index.html
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
- Angular 2 Lifecycle Hooks
-
-
-
-
-
-
- Loading...
-
-
-
diff --git a/public/docs/_examples/lifecycle-hooks/dart/web/main.dart b/public/docs/_examples/lifecycle-hooks/dart/web/main.dart
deleted file mode 100644
index 6fc83949b7..0000000000
--- a/public/docs/_examples/lifecycle-hooks/dart/web/main.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-// #docregion
-import 'package:angular2/bootstrap.dart';
-import 'package:lifecycle_hooks/app_component.dart';
-
-main() {
- bootstrap(AppComponent);
-}
diff --git a/public/docs/_examples/lifecycle-hooks/e2e-spec.js b/public/docs/_examples/lifecycle-hooks/e2e-spec.js
deleted file mode 100644
index d201fd7bfb..0000000000
--- a/public/docs/_examples/lifecycle-hooks/e2e-spec.js
+++ /dev/null
@@ -1,144 +0,0 @@
-describe('Lifecycle hooks', function () {
-
- beforeAll(function () {
- browser.get('');
- });
-
- it('should open correctly', function () {
- expect(element.all(by.css('h2')).get(0).getText()).toEqual('Peek-A-Boo');
- });
-
- it('should be able to drive peek-a-boo button', function () {
- var pabComp = element(by.css('peek-a-boo-parent peek-a-boo'));
- expect(pabComp.isPresent()).toBe(false, "should not be able to find the 'peek-a-boo' component");
- var pabButton = element.all(by.css('peek-a-boo-parent button')).get(0);
- var updateHeroButton = element.all(by.css('peek-a-boo-parent button')).get(1);
- expect(pabButton.getText()).toContain('Create Peek');
- pabButton.click().then(function () {
- expect(pabButton.getText()).toContain('Destroy Peek');
- expect(pabComp.isDisplayed()).toBe(true, "should be able to see the 'peek-a-boo' component");
- expect(pabComp.getText()).toContain('Windstorm');
- expect(pabComp.getText()).not.toContain('Windstorm!');
- expect(updateHeroButton.isPresent()).toBe(true, "should be able to see the update hero button");
- return updateHeroButton.click();
- }).then(function () {
- expect(pabComp.getText()).toContain('Windstorm!');
- return pabButton.click();
- }).then(function () {
- expect(pabComp.isPresent()).toBe(false, "should no longer be able to find the 'peek-a-boo' component");
- });
- });
-
- it('should be able to trigger onChanges', function () {
- var onChangesViewEle = element.all(by.css('on-changes-parent my-hero div')).get(0);
- var inputEles = element.all(by.css('on-changes-parent input'));
- var heroNameInputEle = inputEles.get(0);
- var powerInputEle = inputEles.get(1);
- var titleEle = onChangesViewEle.element(by.css('p'));
- expect(titleEle.getText()).toContain('Windstorm can sing');
- var changeLogEles = onChangesViewEle.all(by.css('div'));
- expect(changeLogEles.count()).toEqual(3, "should start with 3 messages");
- // heroNameInputEle.sendKeys('-foo-').then(function () {
- sendKeys(heroNameInputEle, '-foo-').then(function () {
- expect(titleEle.getText()).toContain('Windstorm-foo- can sing');
- expect(changeLogEles.count()).toEqual(3, "should still have 3 messages");
- // protractor bug with sendKeys means that line below does not work.
- // return powerInputEle.sendKeys('-bar-');
- return sendKeys(powerInputEle, '-bar-');
- }).then(function () {
- expect(titleEle.getText()).toContain('Windstorm-foo- can sing-bar-');
- // 8 == 3 previously + length of '-bar-'
- expect(changeLogEles.count()).toEqual(8, "should have 8 messages now");
- });
- });
-
- it('should support after-view hooks', function () {
- var inputEle = element(by.css('after-view-parent input'));
- var buttonEle = element(by.css('after-view-parent button'));
- var logEles = element.all(by.css('after-view-parent h4 ~ div'));
- var childViewTextEle = element(by.css('after-view-parent my-child .child'));
- expect(childViewTextEle.getText()).toContain('Magneta is my hero');
- expect(logEles.count()).toBeGreaterThan(2);
- var logCount;
- logEles.count().then(function(count) {
- logCount = count;
- return sendKeys(inputEle, "-test-");
- }).then(function() {
- expect(childViewTextEle.getText()).toContain('-test-');
- return logEles.count();
- }).then(function(count) {
- expect(logCount + 6).toEqual(count, "6 additional log messages should have been added");
- logCount = count;
- return buttonEle.click();
- }).then(function() {
- expect(childViewTextEle.isPresent()).toBe(false,"child view should no longer be part of the DOM");
- sendKeys(inputEle, "-foo-");
- expect(logEles.count()).toEqual(logCount, "no additional log messages should have been added");
- });
- });
-
- it('should support after-content hooks', function () {
- var inputEle = element(by.css('after-content-parent input'));
- var buttonEle = element(by.css('after-content-parent button'));
- var logEles = element.all(by.css('after-content-parent h4 ~ div'));
- var childViewTextEle = element(by.css('after-content-parent my-child .child'));
- expect(childViewTextEle.getText()).toContain('Magneta is my hero');
- expect(logEles.count()).toBeGreaterThan(2);
- var logCount;
- logEles.count().then(function(count) {
- logCount = count;
- return sendKeys(inputEle, "-test-");
- }).then(function() {
- expect(childViewTextEle.getText()).toContain('-test-');
- return logEles.count();
- }).then(function(count) {
- expect(logCount + 6).toEqual(count, "6 additional log messages should have been added");
- logCount = count;
- return buttonEle.click();
- }).then(function() {
- expect(childViewTextEle.isPresent()).toBe(false,"child view should no longer be part of the DOM");
- sendKeys(inputEle, "-foo-");
- expect(logEles.count()).toEqual(logCount, "no additional log messages should have been added");
- });
- });
-
- it('should support "spy" hooks', function () {
- var inputEle = element(by.css('spy-parent input'));
- var addHeroButtonEle = element(by.cssContainingText('spy-parent button','Add Hero'));
- var resetHeroesButtonEle = element(by.cssContainingText('spy-parent button','Reset Heroes'));
- var heroEles = element.all(by.css('spy-parent div[my-spy'));
- var logEles = element.all(by.css('spy-parent h4 ~ div'));
- expect(heroEles.count()).toBe(2, 'should have two heroes displayed');
- expect(logEles.count()).toBe(2, 'should have two log entries');
- sendKeys(inputEle, "-test-").then(function() {
- return addHeroButtonEle.click();
- }).then(function() {
- expect(heroEles.count()).toBe(3, 'should have added one hero');
- expect(heroEles.get(2).getText()).toContain('-test-');
- expect(logEles.count()).toBe(3, 'should now have 3 log entries');
- return resetHeroesButtonEle.click();
- }).then(function() {
- expect(heroEles.count()).toBe(0, 'should no longer have any heroes');
- expect(logEles.count()).toBe(7, 'should now have 7 log entries - 3 orig + 1 reset + 3 removeall');
- })
- });
-
- it('should support "spy counter" hooks', function () {
- var updateCounterButtonEle = element(by.cssContainingText('counter-parent button','Update'));
- var resetCounterButtonEle = element(by.cssContainingText('counter-parent button','Reset'));
- var textEle = element(by.css('counter-parent my-counter > div'));
- var logEles = element.all(by.css('counter-parent h4 ~ div'));
- expect(textEle.getText()).toContain('Counter = 0');
- expect(logEles.count()).toBe(2, 'should start with two log entries');
- updateCounterButtonEle.click().then(function() {
- expect(textEle.getText()).toContain('Counter = 1');
- expect(logEles.count()).toBe(3, 'should now have 3 log entries');
- return resetCounterButtonEle.click();
- }).then(function() {
- expect(textEle.getText()).toContain('Counter = 0');
- expect(logEles.count()).toBe(7, 'should now have 7 log entries - 3 prev + 1 reset + 2 destroy + 1 init');
- })
- });
-
-
-});
diff --git a/public/docs/_examples/lifecycle-hooks/e2e-spec.ts b/public/docs/_examples/lifecycle-hooks/e2e-spec.ts
new file mode 100644
index 0000000000..8e9acb1c76
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/e2e-spec.ts
@@ -0,0 +1,178 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by } from 'protractor';
+
+describe('Lifecycle hooks', function () {
+
+ beforeAll(function () {
+ browser.get('');
+ });
+
+ it('should open correctly', function () {
+ expect(element.all(by.css('h2')).get(0).getText()).toEqual('Peek-A-Boo');
+ });
+
+ it('should support peek-a-boo', function () {
+ let pabComp = element(by.css('peek-a-boo-parent peek-a-boo'));
+ expect(pabComp.isPresent()).toBe(false, 'should not be able to find the "peek-a-boo" component');
+ let pabButton = element.all(by.css('peek-a-boo-parent button')).get(0);
+ let updateHeroButton = element.all(by.css('peek-a-boo-parent button')).get(1);
+ expect(pabButton.getText()).toContain('Create Peek');
+ pabButton.click().then(function () {
+ expect(pabButton.getText()).toContain('Destroy Peek');
+ expect(pabComp.isDisplayed()).toBe(true, 'should be able to see the "peek-a-boo" component');
+ expect(pabComp.getText()).toContain('Windstorm');
+ expect(pabComp.getText()).not.toContain('Windstorm!');
+ expect(updateHeroButton.isPresent()).toBe(true, 'should be able to see the update hero button');
+ return updateHeroButton.click();
+ }).then(function () {
+ expect(pabComp.getText()).toContain('Windstorm!');
+ return pabButton.click();
+ }).then(function () {
+ expect(pabComp.isPresent()).toBe(false, 'should no longer be able to find the "peek-a-boo" component');
+ });
+ });
+
+ it('should support OnChanges hook', function () {
+ let onChangesViewEle = element.all(by.css('on-changes div')).get(0);
+ let inputEles = element.all(by.css('on-changes-parent input'));
+ let heroNameInputEle = inputEles.get(1);
+ let powerInputEle = inputEles.get(0);
+ let titleEle = onChangesViewEle.element(by.css('p'));
+ let changeLogEles = onChangesViewEle.all(by.css('div'));
+
+ expect(titleEle.getText()).toContain('Windstorm can sing');
+ expect(changeLogEles.count()).toEqual(2, 'should start with 2 messages');
+ heroNameInputEle.sendKeys('-foo-');
+ expect(titleEle.getText()).toContain('Windstorm-foo- can sing');
+ expect(changeLogEles.count()).toEqual(2, 'should still have 2 messages');
+ powerInputEle.sendKeys('-bar-');
+ expect(titleEle.getText()).toContain('Windstorm-foo- can sing-bar-');
+ // 7 == 2 previously + length of '-bar-'
+ expect(changeLogEles.count()).toEqual(7, 'should have 7 messages now');
+ });
+
+ it('should support DoCheck hook', function () {
+ let doCheckViewEle = element.all(by.css('do-check div')).get(0);
+ let inputEles = element.all(by.css('do-check-parent input'));
+ let heroNameInputEle = inputEles.get(1);
+ let powerInputEle = inputEles.get(0);
+ let titleEle = doCheckViewEle.element(by.css('p'));
+ let changeLogEles = doCheckViewEle.all(by.css('div'));
+ let logCount: number;
+
+ expect(titleEle.getText()).toContain('Windstorm can sing');
+ changeLogEles.count().then(function(count: number) {
+ // 3 messages to start
+ expect(count).toEqual(3, 'should start with 3 messages');
+ logCount = count;
+ return heroNameInputEle.sendKeys('-foo-');
+ }).then(function () {
+ expect(titleEle.getText()).toContain('Windstorm-foo- can sing');
+ return changeLogEles.count();
+ }).then(function(count: number) {
+ // one more for each keystroke
+ expect(count).toEqual(logCount + 5, 'should add 5 more messages');
+ logCount = count;
+ return powerInputEle.sendKeys('-bar-');
+ }).then(function () {
+ expect(titleEle.getText()).toContain('Windstorm-foo- can sing-bar-');
+ expect(changeLogEles.count()).toEqual(logCount + 6, 'should add 6 more messages');
+ });
+ });
+
+ it('should support AfterView hooks', function () {
+ let parentEle = element(by.tagName('after-view-parent'));
+ let buttonEle = parentEle.element(by.tagName('button')); // Reset
+ let commentEle = parentEle.element(by.className('comment'));
+ let logEles = parentEle.all(by.css('h4 ~ div'));
+ let childViewInputEle = parentEle.element(by.css('my-child-view input'));
+ let logCount: number;
+
+ expect(childViewInputEle.getAttribute('value')).toContain('Magneta');
+ expect(commentEle.isPresent()).toBe(false, 'comment should not be in DOM');
+
+ logEles.count().then(function(count: number) {
+ logCount = count;
+ return childViewInputEle.sendKeys('-test-');
+ }).then(function() {
+ expect(childViewInputEle.getAttribute('value')).toContain('-test-');
+ expect(commentEle.isPresent()).toBe(true, 'should have comment because >10 chars');
+ expect(commentEle.getText()).toContain('long name');
+ return logEles.count();
+ }).then(function(count: number) {
+ expect(logCount + 7).toEqual(count, '7 additional log messages should have been added');
+ logCount = count;
+ return buttonEle.click();
+ }).then(function() {
+ expect(logEles.count()).toBeLessThan(logCount, 'log should shrink after reset');
+ });
+ });
+
+
+ it('should support AfterContent hooks', function () {
+ let parentEle = element(by.tagName('after-content-parent'));
+ let buttonEle = parentEle.element(by.tagName('button')); // Reset
+ let commentEle = parentEle.element(by.className('comment'));
+ let logEles = parentEle.all(by.css('h4 ~ div'));
+ let childViewInputEle = parentEle.element(by.css('my-child input'));
+ let logCount: number;
+
+ expect(childViewInputEle.getAttribute('value')).toContain('Magneta');
+ expect(commentEle.isPresent()).toBe(false, 'comment should not be in DOM');
+
+ logEles.count().then(function(count: number) {
+ logCount = count;
+ return childViewInputEle.sendKeys('-test-');
+ }).then(function() {
+ expect(childViewInputEle.getAttribute('value')).toContain('-test-');
+ expect(commentEle.isPresent()).toBe(true, 'should have comment because >10 chars');
+ expect(commentEle.getText()).toContain('long name');
+ return logEles.count();
+ }).then(function(count: number) {
+ expect(logCount + 5).toEqual(count, '5 additional log messages should have been added');
+ logCount = count;
+ return buttonEle.click();
+ }).then(function() {
+ expect(logEles.count()).toBeLessThan(logCount, 'log should shrink after reset');
+ });
+ });
+
+ it('should support spy\'s OnInit & OnDestroy hooks', function () {
+ let inputEle = element(by.css('spy-parent input'));
+ let addHeroButtonEle = element(by.cssContainingText('spy-parent button', 'Add Hero'));
+ let resetHeroesButtonEle = element(by.cssContainingText('spy-parent button', 'Reset Heroes'));
+ let heroEles = element.all(by.css('spy-parent div[mySpy'));
+ let logEles = element.all(by.css('spy-parent h4 ~ div'));
+ expect(heroEles.count()).toBe(2, 'should have two heroes displayed');
+ expect(logEles.count()).toBe(2, 'should have two log entries');
+ inputEle.sendKeys('-test-').then(function() {
+ return addHeroButtonEle.click();
+ }).then(function() {
+ expect(heroEles.count()).toBe(3, 'should have added one hero');
+ expect(heroEles.get(2).getText()).toContain('-test-');
+ expect(logEles.count()).toBe(3, 'should now have 3 log entries');
+ return resetHeroesButtonEle.click();
+ }).then(function() {
+ expect(heroEles.count()).toBe(0, 'should no longer have any heroes');
+ expect(logEles.count()).toBe(7, 'should now have 7 log entries - 3 orig + 1 reset + 3 removeall');
+ });
+ });
+
+ it('should support "spy counter"', function () {
+ let updateCounterButtonEle = element(by.cssContainingText('counter-parent button', 'Update'));
+ let resetCounterButtonEle = element(by.cssContainingText('counter-parent button', 'Reset'));
+ let textEle = element(by.css('counter-parent my-counter > div'));
+ let logEles = element.all(by.css('counter-parent h4 ~ div'));
+ expect(textEle.getText()).toContain('Counter = 0');
+ expect(logEles.count()).toBe(2, 'should start with two log entries');
+ updateCounterButtonEle.click().then(function() {
+ expect(textEle.getText()).toContain('Counter = 1');
+ expect(logEles.count()).toBe(3, 'should now have 3 log entries');
+ return resetCounterButtonEle.click();
+ }).then(function() {
+ expect(textEle.getText()).toContain('Counter = 0');
+ expect(logEles.count()).toBe(7, 'should now have 7 log entries - 3 prev + 1 reset + 2 destroy + 1 init');
+ });
+ });
+});
diff --git a/public/docs/_examples/lifecycle-hooks/ts/.gitignore b/public/docs/_examples/lifecycle-hooks/ts/.gitignore
deleted file mode 100644
index cf44e148ba..0000000000
--- a/public/docs/_examples/lifecycle-hooks/ts/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-**/*.js
\ No newline at end of file
diff --git a/public/docs/_examples/lifecycle-hooks/ts/app/after-content.component.ts b/public/docs/_examples/lifecycle-hooks/ts/app/after-content.component.ts
deleted file mode 100644
index 1774470535..0000000000
--- a/public/docs/_examples/lifecycle-hooks/ts/app/after-content.component.ts
+++ /dev/null
@@ -1,102 +0,0 @@
-// #docregion
-import {
- Component, Input, Output,
- AfterContentChecked, AfterContentInit, ContentChild,
- AfterViewInit, ViewChild
-} from 'angular2/core';
-
-import {ChildComponent} from './child.component';
-import {LoggerService} from './logger.service';
-
-@Component({
- selector: 'after-content',
- template: `
-
-
-- child content begins --
-
-
-
-
-- child content ends --
-
- `,
- styles: ['.after-content {background: LightCyan; padding: 8px;}'],
-
-})
-export class AfterContentComponent
- implements AfterContentChecked, AfterContentInit, AfterViewInit {
-
- private _logger:LoggerService;
-
- constructor(logger:LoggerService){
- this._logger = logger;
- logger.log('AfterContent ctor: ' + this._getMessage());
- }
-
- // Query for a CONTENT child of type `ChildComponent`
- @ContentChild(ChildComponent) contentChild: ChildComponent;
-
- // Query for a VIEW child of type`ChildComponent`
- // No such VIEW child exists!
- // This component holds content but no view of that type.
- @ViewChild(ChildComponent) viewChild: ChildComponent;
-
-
- ///// Hooks
- ngAfterContentInit() {
- // contentChild is set after the content has been initialized
- this._logger.log('AfterContentInit: ' + this._getMessage());
- }
-
- ngAfterViewInit() {
- this._logger.log(`AfterViewInit: There is ${this.viewChild ? 'a' : 'no'} view child`);
- }
-
- private _prevHero:string;
- ngAfterContentChecked() {
- // contentChild is updated after the content has been checked
- // Called frequently; only report when the hero changes
- if (!this.contentChild || this._prevHero === this.contentChild.hero) {return;}
- this._prevHero = this.contentChild.hero;
- this._logger.log('AfterContentChecked: ' + this._getMessage());
- }
-
- private _getMessage(): string {
- let cmp = this.contentChild;
- return cmp ? `"${cmp.hero}" child content` : 'no child content';
- }
-
-}
-
-/***************************************/
-
-@Component({
- selector: 'after-content-parent',
- template: `
-
-
AfterContent
-
-
-
- Toggle child view
-
-
-
-
-
-- Lifecycle Hook Log --
-
{{msg}}
-
- `,
- styles: ['.parent {background: powderblue; padding: 8px; margin:100px 8px;}'],
- directives: [AfterContentComponent, ChildComponent],
- providers:[LoggerService]
-})
-export class AfterContentParentComponent {
-
- hookLog:string[];
- hero = 'Magneta';
- showChild = true;
-
- constructor(logger:LoggerService){
- this.hookLog = logger.logs;
- }
-}
diff --git a/public/docs/_examples/lifecycle-hooks/ts/app/after-view.component.ts b/public/docs/_examples/lifecycle-hooks/ts/app/after-view.component.ts
deleted file mode 100644
index 47f12b53ae..0000000000
--- a/public/docs/_examples/lifecycle-hooks/ts/app/after-view.component.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-// #docregion
-import {
- Component, Input, Output,
- AfterContentInit, ContentChild,
- AfterViewChecked, AfterViewInit, ViewChild
-} from 'angular2/core';
-
-import {ChildComponent} from './child.component';
-import {LoggerService} from './logger.service';
-
-@Component({
- selector: 'after-view-parent',
- template: `
-
-
AfterView
-
-
-
- Toggle child view
-
-
-
-
-
-- Lifecycle Hook Log --
-
{{msg}}
-
- `,
- styles: ['.parent {background: burlywood; padding: 8px; margin:100px 8px;}'],
- directives: [ChildComponent],
- providers:[LoggerService]
-})
-export class AfterViewParentComponent
- implements AfterContentInit, AfterViewChecked, AfterViewInit {
-
- private _logger:LoggerService;
-
- constructor(logger:LoggerService){
- this._logger = logger;
- this.hookLog = logger.logs;
- logger.log('AfterView ctor: ' + this._getMessage());
- }
-
- hookLog:string[];
- hero = 'Magneta';
- showChild = true;
-
- // Query for a CONTENT child of type `ChildComponent`
- // No such CONTENT child exists!
- // This component holds a view but no content of that type.
- @ContentChild(ChildComponent) contentChild: ChildComponent;
-
- // Query for a VIEW child of type `ChildComponent`
- @ViewChild(ChildComponent) viewChild: ChildComponent;
-
-
- ///// Hooks
- ngAfterContentInit() {
- this._logger.log(`AfterContentInit: There is ${this.contentChild ? 'a' : 'no'} content child`);
- }
-
- ngAfterViewInit() {
- // viewChild is set after the view has been initialized
- this._logger.log('AfterViewInit: ' + this._getMessage());
- }
-
- private _prevHero:string;
- ngAfterViewChecked() {
- // viewChild is updated after the view has been checked
- // Called frequently; only report when the hero changes
- if (!this.viewChild || this._prevHero === this.viewChild.hero) {return;}
- this._prevHero = this.viewChild.hero;
- this._logger.log('AfterViewChecked: ' + this._getMessage());
- }
-
- private _getMessage(): string {
- let cmp = this.viewChild;
- return cmp ? `"${cmp.hero}" child view` : 'no child view';
- }
-
-}
diff --git a/public/docs/_examples/lifecycle-hooks/ts/app/app.component.ts b/public/docs/_examples/lifecycle-hooks/ts/app/app.component.ts
deleted file mode 100644
index 14f1bdab24..0000000000
--- a/public/docs/_examples/lifecycle-hooks/ts/app/app.component.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-// #docregion
-import {Component} from 'angular2/core';
-
-import {AfterContentParentComponent} from './after-content.component';
-import {AfterViewParentComponent} from './after-view.component';
-import {CounterParentComponent} from './counter.component';
-import {OnChangesParentComponent} from './on-changes.component';
-import {PeekABooParentComponent} from './peek-a-boo-parent.component';
-import {SpyParentComponent} from './spy.component';
-
-/***************************************/
-/*
- template: `
-
-
-
-
-
-
- `,
- */
-
-@Component({
- selector: 'my-app',
- template: `
-
-
-
-
-
-
- `,
- directives: [
- AfterContentParentComponent,
- AfterViewParentComponent,
- OnChangesParentComponent,
- PeekABooParentComponent,
- SpyParentComponent,
- CounterParentComponent
- ]
-})
-export class AppComponent {
-}
diff --git a/public/docs/_examples/lifecycle-hooks/ts/app/child.component.ts b/public/docs/_examples/lifecycle-hooks/ts/app/child.component.ts
deleted file mode 100644
index a027d9180c..0000000000
--- a/public/docs/_examples/lifecycle-hooks/ts/app/child.component.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-// #docregion
-import {Component, Input} from 'angular2/core';
-
-@Component({
- selector: 'my-child',
- template: `
-
-
-- child view begins --
-
{{hero}} is my hero.
-
-- child view ends --
-
- `,
- styles: [
- '.child {background: Yellow; padding: 8px; }',
- '.my-child {background: LightYellow; padding: 8px; margin-top: 8px}'
- ]
-})
-export class ChildComponent {
- @Input() hero: string;
-}
\ No newline at end of file
diff --git a/public/docs/_examples/lifecycle-hooks/ts/app/counter.component.ts b/public/docs/_examples/lifecycle-hooks/ts/app/counter.component.ts
deleted file mode 100644
index 7a502a25b0..0000000000
--- a/public/docs/_examples/lifecycle-hooks/ts/app/counter.component.ts
+++ /dev/null
@@ -1,86 +0,0 @@
-// #docregion
-import {
- Component, Input, Output,
- OnChanges, SimpleChange,
-} from 'angular2/core';
-
-import {Spy} from './spy.directive';
-import {LoggerService} from './logger.service';
-
-@Component({
- selector: 'my-counter',
- template: `
-
- Counter = {{counter}}
-
-
-- Counter Change Log --
-
{{chg}}
-
- `,
- styles: ['.counter {background: LightYellow; padding: 8px; margin-top: 8px}'],
- directives:[Spy]
-})
-export class MyCounter implements OnChanges {
- @Input() counter: number;
- changeLog:string[] = [];
-
- ngOnChanges(changes: {[propertyName: string]: SimpleChange}) {
-
- // Empty the changeLog whenever counter goes to zero
- // hint: this is a way to respond programmatically to external value changes.
- if (this.counter === 0) {
- this.changeLog.length = 0;
- }
-
- // A change to `counter` is the only change we care about
- let prop = changes['counter'];
- let cur = prop.currentValue;
- let prev = JSON.stringify(prop.previousValue); // first time is {}; after is integer
- this.changeLog.push(`counter: currentValue = ${cur}, previousValue = ${prev}`);
- }
-
-}
-
-/***************************************/
-
-@Component({
- selector: 'counter-parent',
- template: `
-
-
Counter Spy
-
-
Update counter
-
Reset Counter
-
-
-
-
-- Spy Lifecycle Hook Log --
-
{{msg}}
-
- `,
- styles: ['.parent {background: gold; padding: 10px; margin:100px 8px;}'],
- directives: [MyCounter],
- providers: [LoggerService]
-})
-export class CounterParentComponent {
- value: number;
- spyLog:string[] = [];
-
- private _logger:LoggerService;
-
- constructor(logger:LoggerService){
- this._logger = logger;
- this.spyLog = logger.logs;
- this.reset();
- }
-
- updateCounter() {
- this.value += 1;
- }
-
- reset(){
- this._logger.log('-- reset --');
- this.value=0;
- }
-}
-
diff --git a/public/docs/_examples/lifecycle-hooks/ts/app/logger.service.ts b/public/docs/_examples/lifecycle-hooks/ts/app/logger.service.ts
deleted file mode 100644
index 209bd6a2a5..0000000000
--- a/public/docs/_examples/lifecycle-hooks/ts/app/logger.service.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import {Injectable} from 'angular2/core';
-
-@Injectable()
-export class LoggerService {
- logs:string[] = [];
-
- log(msg:string, noTick:boolean = false) {
- if (!noTick) { this.tick(); }
- this.logs.push(msg);
- }
-
- clear() {this.logs.length = 0;}
-
- tick() {
- setTimeout(() => {
- // console.log('tick')
- }, 0);
- }
-}
diff --git a/public/docs/_examples/lifecycle-hooks/ts/app/main.ts b/public/docs/_examples/lifecycle-hooks/ts/app/main.ts
deleted file mode 100644
index 4651bd780a..0000000000
--- a/public/docs/_examples/lifecycle-hooks/ts/app/main.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import {bootstrap} from 'angular2/platform/browser';
-import {AppComponent} from './app.component';
-
-bootstrap(AppComponent).catch(err => console.error(err));
\ No newline at end of file
diff --git a/public/docs/_examples/lifecycle-hooks/ts/app/on-changes.component.ts b/public/docs/_examples/lifecycle-hooks/ts/app/on-changes.component.ts
deleted file mode 100644
index 32a2185aba..0000000000
--- a/public/docs/_examples/lifecycle-hooks/ts/app/on-changes.component.ts
+++ /dev/null
@@ -1,84 +0,0 @@
-// #docregion
-import {
- Component, Input, Output,
- OnChanges, SimpleChange,
-} from 'angular2/core';
-
-
-export class Hero {
- constructor(public name:string){}
-}
-
-@Component({
- selector: 'my-hero',
- template: `
-
-
{{hero.name}} can {{power}}
-
-
-- Change Log --
-
{{chg}}
-
- `,
- styles: [
- '.hero {background: LightYellow; padding: 8px; margin-top: 8px}',
- 'p {background: Yellow; padding: 8px; margin-top: 8px}'
- ]
-})
-export class MyHeroComponent implements OnChanges {
- @Input() hero: Hero;
- @Input() power: string;
- @Input() reset: {};
-
- changeLog:string[] = [];
-
- ngOnChanges(changes: {[propertyName: string]: SimpleChange}) {
-
- // Empty the changeLog whenever 'reset' property changes
- // hint: this is a way to respond programmatically to external value changes.
- if (changes['reset']) { this.changeLog.length = 0; }
-
- for (let propName in changes) {
- let prop = changes[propName];
- let cur = JSON.stringify(prop.currentValue)
- let prev = JSON.stringify(prop.previousValue); // first time is {}; after is integer
- this.changeLog.push(`${propName}: currentValue = ${cur}, previousValue = ${prev}`);
- }
- }
-}
-
-/***************************************/
-
-@Component({
- selector: 'on-changes-parent',
- template: `
-
-
OnChanges
-
-
Hero.name: does NOT trigger onChanges
-
Power: DOES trigger onChanges
-
Reset Log triggers onChanges and clears the change log
-
-
-
- `,
- styles: ['.parent {background: Lavender; padding: 10px; margin:100px 8px;}'],
- directives: [MyHeroComponent]
-})
-export class OnChangesParentComponent {
- hero:Hero;
- power:string;
- resetTrigger = false;
-
- constructor() {
- this.reset();
- }
-
- reset(){
- // new Hero object every time; triggers onChange
- this.hero = new Hero('Windstorm');
- // setting power only triggers onChange if this value is different
- this.power = 'sing';
- // always triggers onChange ... which is interpreted as a reset
- this.resetTrigger = !this.resetTrigger;
- }
-}
diff --git a/public/docs/_examples/lifecycle-hooks/ts/app/peek-a-boo-parent.component.ts b/public/docs/_examples/lifecycle-hooks/ts/app/peek-a-boo-parent.component.ts
deleted file mode 100644
index 57e4754866..0000000000
--- a/public/docs/_examples/lifecycle-hooks/ts/app/peek-a-boo-parent.component.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-// #docregion
-import {Component} from 'angular2/core';
-import {PeekABooComponent} from './peek-a-boo.component'
-import {LoggerService} from './logger.service';
-
-@Component({
- selector: 'peek-a-boo-parent',
- template: `
-
-
Peek-A-Boo
-
-
- {{hasChild ? 'Destroy' : 'Create'}} PeekABooComponent
-
-
Update Hero
-
-
-
-
-
-- Lifecycle Hook Log --
-
{{msg}}
-
- `,
- styles: ['.parent {background: moccasin; padding: 10px; margin:100px 8px}'],
- directives: [PeekABooComponent],
- providers: [LoggerService]
-})
-export class PeekABooParentComponent {
-
- hasChild = false;
- hookLog:string[];
-
- heroName = 'Windstorm';
- private _logger:LoggerService;
-
- constructor(logger:LoggerService){
- this._logger = logger;
- this.hookLog = logger.logs;
- }
-
- toggleChild() {
- this.hasChild = !this.hasChild;
- if (this.hasChild) {
- this.heroName = 'Windstorm';
- this._logger.clear(); // clear log on create
- }
- this._logger.tick();
- }
-
- updateHero() {
- this.heroName += '!';
- this._logger.tick();
- }
-}
diff --git a/public/docs/_examples/lifecycle-hooks/ts/app/peek-a-boo.component.ts b/public/docs/_examples/lifecycle-hooks/ts/app/peek-a-boo.component.ts
deleted file mode 100644
index 5800554cf4..0000000000
--- a/public/docs/_examples/lifecycle-hooks/ts/app/peek-a-boo.component.ts
+++ /dev/null
@@ -1,98 +0,0 @@
-// #docregion
-// #docregion lc-imports
-import {
- OnChanges, SimpleChange,
- OnInit,
- // DoCheck, // not demonstrated
- AfterContentInit,
- AfterContentChecked,
- AfterViewInit,
- AfterViewChecked,
- OnDestroy
-} from 'angular2/core';
-// #docregion lc-imports
-import {Component, Input, Output} from 'angular2/core';
-import {LoggerService} from './logger.service';
-
-let nextId = 1;
-
-@Component({
- selector: 'peek-a-boo',
- template: 'Now you see my hero, {{name}}
',
- styles: ['p {background: LightYellow; padding: 8px}']
-})
-// Don't HAVE to mention the Lifecycle Hook interfaces
-// unless we want typing and tool support.
-export class PeekABooComponent
- implements OnChanges, OnInit,AfterContentInit,AfterContentChecked,
- AfterViewInit, AfterViewChecked, OnDestroy {
- @Input() name:string;
-
- private _afterContentCheckedCounter = 1;
- private _afterViewCheckedCounter = 1;
- private _id = nextId++;
- private _logger:LoggerService;
- private _onChangesCounter = 1;
- private _verb = 'initialized';
-
- constructor(logger:LoggerService){
- this._logger = logger;
- }
-
- // only called if there is an @input variable set by parent.
- ngOnChanges(changes: {[propertyName: string]: SimpleChange}){
- let changesMsgs:string[] = []
- for (let propName in changes) {
- if (propName === 'name') {
- let name = changes['name'].currentValue;
- changesMsgs.push(`name ${this._verb} to "${name}"`);
- } else {
- changesMsgs.push(propName + ' ' + this._verb);
- }
- }
- this._logIt(`onChanges (${this._onChangesCounter++}): ${changesMsgs.join('; ')}`);
- this._verb = 'changed'; // next time it will be a change
- }
-
- ngOnInit() {
- this._logIt(`onInit`);
- }
-
- ngAfterContentInit(){
- this._logIt(`afterContentInit`);
- }
-
- // Called after every change detection check
- // of the component (directive) CONTENT
- // Beware! Called frequently!
- ngAfterContentChecked(){
- let counter = this._afterContentCheckedCounter++;
- let msg = `afterContentChecked (${counter})`;
- this._logIt(msg);
- }
-
- ngAfterViewInit(){
- this._logIt(`afterViewInit`);
- }
-
- // Called after every change detection check
- // of the component (directive) VIEW
- // Beware! Called frequently!
-
- ngAfterViewChecked(){
- let counter = this._afterViewCheckedCounter++;
- let msg = `afterViewChecked (${counter})`;
- this._logIt(msg);
- }
-
- ngOnDestroy() {
- this._logIt(`onDestroy`);
- }
-
- private _logIt(msg:string){
- // Don't tick or else
- // the AfterContentChecked and AfterViewChecked recurse.
- // Let parent call tick()
- this._logger.log(`#${this._id } ${msg}`, true);
- }
-}
\ No newline at end of file
diff --git a/public/docs/_examples/lifecycle-hooks/ts/app/spy.component.ts b/public/docs/_examples/lifecycle-hooks/ts/app/spy.component.ts
deleted file mode 100644
index 9a82b2faa8..0000000000
--- a/public/docs/_examples/lifecycle-hooks/ts/app/spy.component.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-// #docregion
-import {Component} from 'angular2/core';
-import {LoggerService} from './logger.service';
-import {Spy} from './spy.directive';
-
-@Component({
- selector: 'spy-parent',
- template: `
-
-
Spy Directive
-
-
-
Add Hero
-
Reset Heroes
-
-
-
- {{hero}}
-
-
-
-- Spy Lifecycle Hook Log --
-
{{msg}}
-
- `,
- styles: [
- '.parent {background: khaki; padding: 10px; margin:100px 8px}',
- '.heroes {background: LightYellow; padding: 0 8px}'
- ],
- directives: [Spy],
- providers: [LoggerService]
-})
-export class SpyParentComponent {
- newName = 'Herbie';
- heroes:string[] = ['Windstorm', 'Magneta'];
- spyLog:string[];
-
- private _logger:LoggerService;
-
- constructor(logger:LoggerService){
- this._logger = logger;
- this.spyLog = logger.logs;
- }
-
- addHero() {
- if (this.newName.trim()) {
- this.heroes.push(this.newName.trim());
- this.newName = '';
- }
- }
-
- reset(){
- this._logger.log('-- reset --');
- this.heroes.length = 0;
- }
-}
diff --git a/public/docs/_examples/lifecycle-hooks/ts/app/spy.directive.ts b/public/docs/_examples/lifecycle-hooks/ts/app/spy.directive.ts
deleted file mode 100644
index 31c54ba9bc..0000000000
--- a/public/docs/_examples/lifecycle-hooks/ts/app/spy.directive.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-// #docregion
-import {Directive, Input,
- OnInit, OnDestroy} from 'angular2/core';
-
-import {LoggerService} from './logger.service';
-
-/***************************************/
-let nextId = 1;
-
-// Spy on any element to which it is applied.
-// Usage: ...
-@Directive({selector: '[my-spy]'})
-export class Spy implements OnInit, OnDestroy {
-
- private _id = nextId++;
- private _logger:LoggerService;
-
- constructor(logger:LoggerService){
- this._logger = logger;
- }
-
- ngOnInit() {
- this._logIt(`onInit`);
- }
-
- ngOnDestroy() {
- this._logIt(`onDestroy`);
- }
-
- private _logIt(msg:string){
- this._logger.log(`Spy #${this._id } ${msg}`);
- }
-}
diff --git a/public/docs/_examples/lifecycle-hooks/ts/index.html b/public/docs/_examples/lifecycle-hooks/ts/index.html
deleted file mode 100644
index a55cab995a..0000000000
--- a/public/docs/_examples/lifecycle-hooks/ts/index.html
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
- Angular 2 Lifecycle Hooks
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Loading...
-
-
-
\ No newline at end of file
diff --git a/public/docs/_examples/lifecycle-hooks/ts/plnkr.json b/public/docs/_examples/lifecycle-hooks/ts/plnkr.json
index 366b8325ce..49290aa804 100644
--- a/public/docs/_examples/lifecycle-hooks/ts/plnkr.json
+++ b/public/docs/_examples/lifecycle-hooks/ts/plnkr.json
@@ -1,7 +1,9 @@
{
"description": "Lifecycle Hooks",
+ "basePath": "src/",
"files":["!**/*.d.ts", "!**/*.js"],
- "tags": ["lifecycle", "hooks",
- "onInit", "onDestroy", "onChange",
- "ngOnInit", "ngOnDestroy", "ngOnChange"]
-}
\ No newline at end of file
+ "tags": ["lifecycle", "hooks",
+ "OnInit", "OnDestroy", "OnChange", "DoCheck",
+ "AfterContentInit", "AfterContentChecked",
+ "AfterViewInit", "AfterViewChecked"]
+}
diff --git a/public/docs/_examples/lifecycle-hooks/ts/src/app/after-content.component.ts b/public/docs/_examples/lifecycle-hooks/ts/src/app/after-content.component.ts
new file mode 100644
index 0000000000..dfd2b80d24
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/ts/src/app/after-content.component.ts
@@ -0,0 +1,116 @@
+// #docplaster
+// #docregion
+import { AfterContentChecked, AfterContentInit, Component, ContentChild } from '@angular/core';
+
+import { LoggerService } from './logger.service';
+
+//////////////////
+@Component({
+ selector: 'my-child',
+ template: ' '
+})
+export class ChildComponent {
+ hero = 'Magneta';
+}
+
+//////////////////////
+@Component({
+ selector: 'after-content',
+// #docregion template
+ template: `
+ -- projected content begins --
+
+ -- projected content ends --
`
+// #enddocregion template
+ + `
+
+ `
+})
+// #docregion hooks
+export class AfterContentComponent implements AfterContentChecked, AfterContentInit {
+ private prevHero = '';
+ comment = '';
+
+ // Query for a CONTENT child of type `ChildComponent`
+ @ContentChild(ChildComponent) contentChild: ChildComponent;
+
+// #enddocregion hooks
+ constructor(private logger: LoggerService) {
+ this.logIt('AfterContent constructor');
+ }
+
+// #docregion hooks
+ ngAfterContentInit() {
+ // contentChild is set after the content has been initialized
+ this.logIt('AfterContentInit');
+ this.doSomething();
+ }
+
+ ngAfterContentChecked() {
+ // contentChild is updated after the content has been checked
+ if (this.prevHero === this.contentChild.hero) {
+ this.logIt('AfterContentChecked (no change)');
+ } else {
+ this.prevHero = this.contentChild.hero;
+ this.logIt('AfterContentChecked');
+ this.doSomething();
+ }
+ }
+// #enddocregion hooks
+// #docregion do-something
+
+ // This surrogate for real business logic sets the `comment`
+ private doSomething() {
+ this.comment = this.contentChild.hero.length > 10 ? `That's a long name` : '';
+ }
+
+ private logIt(method: string) {
+ let child = this.contentChild;
+ let message = `${method}: ${child ? child.hero : 'no'} child content`;
+ this.logger.log(message);
+ }
+// #docregion hooks
+ // ...
+}
+// #enddocregion hooks
+
+//////////////
+@Component({
+ selector: 'after-content-parent',
+ template: `
+
+
AfterContent
+
+
` +
+// #docregion parent-template
+ `
+
+ `
+// #enddocregion parent-template
++ `
+
+
-- AfterContent Logs --
+
Reset
+
{{msg}}
+
+ `,
+ styles: ['.parent {background: burlywood}'],
+ providers: [LoggerService]
+})
+export class AfterContentParentComponent {
+ logs: string[];
+ show = true;
+
+ constructor(private logger: LoggerService) {
+ this.logs = logger.logs;
+ }
+
+ reset() {
+ this.logs.length = 0;
+ // quickly remove and reload AfterContentComponent which recreates it
+ this.show = false;
+ this.logger.tick_then(() => this.show = true);
+ }
+}
diff --git a/public/docs/_examples/lifecycle-hooks/ts/src/app/after-view.component.ts b/public/docs/_examples/lifecycle-hooks/ts/src/app/after-view.component.ts
new file mode 100644
index 0000000000..71310e4530
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/ts/src/app/after-view.component.ts
@@ -0,0 +1,118 @@
+// #docplaster
+// #docregion
+import { AfterViewChecked, AfterViewInit, Component, ViewChild } from '@angular/core';
+
+import { LoggerService } from './logger.service';
+
+//////////////////
+// #docregion child-view
+@Component({
+ selector: 'my-child-view',
+ template: ' '
+})
+export class ChildViewComponent {
+ hero = 'Magneta';
+}
+// #enddocregion child-view
+
+//////////////////////
+@Component({
+ selector: 'after-view',
+// #docregion template
+ template: `
+ -- child view begins --
+
+ -- child view ends --
`
+// #enddocregion template
+ + `
+
+ `
+})
+// #docregion hooks
+export class AfterViewComponent implements AfterViewChecked, AfterViewInit {
+ private prevHero = '';
+
+ // Query for a VIEW child of type `ChildViewComponent`
+ @ViewChild(ChildViewComponent) viewChild: ChildViewComponent;
+
+// #enddocregion hooks
+ constructor(private logger: LoggerService) {
+ this.logIt('AfterView constructor');
+ }
+
+// #docregion hooks
+ ngAfterViewInit() {
+ // viewChild is set after the view has been initialized
+ this.logIt('AfterViewInit');
+ this.doSomething();
+ }
+
+ ngAfterViewChecked() {
+ // viewChild is updated after the view has been checked
+ if (this.prevHero === this.viewChild.hero) {
+ this.logIt('AfterViewChecked (no change)');
+ } else {
+ this.prevHero = this.viewChild.hero;
+ this.logIt('AfterViewChecked');
+ this.doSomething();
+ }
+ }
+// #enddocregion hooks
+
+ comment = '';
+
+// #docregion do-something
+ // This surrogate for real business logic sets the `comment`
+ private doSomething() {
+ let c = this.viewChild.hero.length > 10 ? `That's a long name` : '';
+ if (c !== this.comment) {
+ // Wait a tick because the component's view has already been checked
+ this.logger.tick_then(() => this.comment = c);
+ }
+ }
+// #enddocregion do-something
+
+ private logIt(method: string) {
+ let child = this.viewChild;
+ let message = `${method}: ${child ? child.hero : 'no'} child view`;
+ this.logger.log(message);
+ }
+// #docregion hooks
+ // ...
+}
+// #enddocregion hooks
+
+//////////////
+@Component({
+ selector: 'after-view-parent',
+ template: `
+
+
AfterView
+
+
+
+
-- AfterView Logs --
+
Reset
+
{{msg}}
+
+ `,
+ styles: ['.parent {background: burlywood}'],
+ providers: [LoggerService]
+})
+export class AfterViewParentComponent {
+ logs: string[];
+ show = true;
+
+ constructor(private logger: LoggerService) {
+ this.logs = logger.logs;
+ }
+
+ reset() {
+ this.logs.length = 0;
+ // quickly remove and reload AfterViewComponent which recreates it
+ this.show = false;
+ this.logger.tick_then(() => this.show = true);
+ }
+}
diff --git a/public/docs/_examples/lifecycle-hooks/ts/src/app/app.component.html b/public/docs/_examples/lifecycle-hooks/ts/src/app/app.component.html
new file mode 100644
index 0000000000..d0692e28ac
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/ts/src/app/app.component.html
@@ -0,0 +1,37 @@
+
+Component Lifecycle Hooks
+Peek-a-boo: (most) lifecycle hooks
+OnChanges
+DoCheck
+AfterViewInit & AfterViewChecked
+AfterContentInit & AfterContentChecked
+Spy: directive with OnInit & OnDestroy
+Counter: OnChanges + Spy directive
+
+
+
+back to top
+
+
+
+back to top
+
+
+
+back to top
+
+
+
+back to top
+
+
+
+back to top
+
+
+
+back to top
+
+
+
+back to top
diff --git a/public/docs/_examples/lifecycle-hooks/ts/src/app/app.component.ts b/public/docs/_examples/lifecycle-hooks/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..5bd535a113
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/ts/src/app/app.component.ts
@@ -0,0 +1,7 @@
+// #docregion
+import { Component } from '@angular/core';
+@Component({
+ selector: 'my-app',
+ templateUrl: './app.component.html'
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/lifecycle-hooks/ts/src/app/app.module.ts b/public/docs/_examples/lifecycle-hooks/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..4d9cabf218
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/ts/src/app/app.module.ts
@@ -0,0 +1,67 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { FormsModule } from '@angular/forms';
+
+import { AppComponent } from './app.component';
+
+import {
+ AfterContentParentComponent,
+ AfterContentComponent,
+ ChildComponent
+} from './after-content.component';
+
+import {
+ AfterViewParentComponent,
+ AfterViewComponent,
+ ChildViewComponent
+} from './after-view.component';
+
+import {
+ CounterParentComponent,
+ MyCounterComponent
+} from './counter.component';
+
+import {
+ DoCheckParentComponent,
+ DoCheckComponent
+} from './do-check.component';
+
+import {
+ OnChangesParentComponent,
+ OnChangesComponent
+} from './on-changes.component';
+
+import { PeekABooParentComponent } from './peek-a-boo-parent.component';
+import { PeekABooComponent } from './peek-a-boo.component';
+
+import { SpyParentComponent } from './spy.component';
+import { SpyDirective } from './spy.directive';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ FormsModule
+ ],
+ declarations: [
+ AppComponent,
+ AfterContentParentComponent,
+ AfterContentComponent,
+ ChildComponent,
+ AfterViewParentComponent,
+ AfterViewComponent,
+ ChildViewComponent,
+ CounterParentComponent,
+ MyCounterComponent,
+ DoCheckParentComponent,
+ DoCheckComponent,
+ OnChangesParentComponent,
+ OnChangesComponent,
+ PeekABooParentComponent,
+ PeekABooComponent,
+ SpyParentComponent,
+ SpyDirective
+ ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/lifecycle-hooks/ts/src/app/counter.component.ts b/public/docs/_examples/lifecycle-hooks/ts/src/app/counter.component.ts
new file mode 100644
index 0000000000..8efd1fbd52
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/ts/src/app/counter.component.ts
@@ -0,0 +1,84 @@
+// #docregion
+import {
+ Component, Input,
+ OnChanges, SimpleChanges,
+} from '@angular/core';
+
+import { LoggerService } from './logger.service';
+
+@Component({
+ selector: 'my-counter',
+ template: `
+
+ Counter = {{counter}}
+
+
-- Counter Change Log --
+
{{chg}}
+
+ `,
+ styles: ['.counter {background: LightYellow; padding: 8px; margin-top: 8px}']
+})
+export class MyCounterComponent implements OnChanges {
+ @Input() counter: number;
+ changeLog: string[] = [];
+
+ ngOnChanges(changes: SimpleChanges) {
+
+ // Empty the changeLog whenever counter goes to zero
+ // hint: this is a way to respond programmatically to external value changes.
+ if (this.counter === 0) {
+ this.changeLog.length = 0;
+ }
+
+ // A change to `counter` is the only change we care about
+ let chng = changes['counter'];
+ let cur = chng.currentValue;
+ let prev = JSON.stringify(chng.previousValue); // first time is {}; after is integer
+ this.changeLog.push(`counter: currentValue = ${cur}, previousValue = ${prev}`);
+ }
+}
+
+/***************************************/
+
+@Component({
+ selector: 'counter-parent',
+ template: `
+
+
Counter Spy
+
+
Update counter
+
Reset Counter
+
+
+
+
-- Spy Lifecycle Hook Log --
+
{{msg}}
+
+ `,
+ styles: ['.parent {background: gold;}'],
+ providers: [LoggerService]
+})
+export class CounterParentComponent {
+ value: number;
+ spyLog: string[] = [];
+
+ private logger: LoggerService;
+
+ constructor(logger: LoggerService) {
+ this.logger = logger;
+ this.spyLog = logger.logs;
+ this.reset();
+ }
+
+ updateCounter() {
+ this.value += 1;
+ this.logger.tick();
+ }
+
+ reset() {
+ this.logger.log('-- reset --');
+ this.value = 0;
+ this.logger.tick();
+ }
+}
+
diff --git a/public/docs/_examples/lifecycle-hooks/ts/src/app/do-check-parent.component.html b/public/docs/_examples/lifecycle-hooks/ts/src/app/do-check-parent.component.html
new file mode 100644
index 0000000000..cf7c2b91ce
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/ts/src/app/do-check-parent.component.html
@@ -0,0 +1,13 @@
+
+
{{title}}
+
+
+
Reset Log
+
+
+
+
+
diff --git a/public/docs/_examples/lifecycle-hooks/ts/src/app/do-check.component.ts b/public/docs/_examples/lifecycle-hooks/ts/src/app/do-check.component.ts
new file mode 100644
index 0000000000..6196dd8edd
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/ts/src/app/do-check.component.ts
@@ -0,0 +1,95 @@
+/* tslint:disable:forin */
+// #docregion
+import { Component, DoCheck, Input, ViewChild } from '@angular/core';
+
+class Hero {
+ constructor(public name: string) {}
+}
+
+@Component({
+ selector: 'do-check',
+ template: `
+
+
{{hero.name}} can {{power}}
+
+
-- Change Log --
+
{{chg}}
+
+ `,
+ styles: [
+ '.hero {background: LightYellow; padding: 8px; margin-top: 8px}',
+ 'p {background: Yellow; padding: 8px; margin-top: 8px}'
+ ]
+})
+export class DoCheckComponent implements DoCheck {
+ @Input() hero: Hero;
+ @Input() power: string;
+
+ changeDetected = false;
+ changeLog: string[] = [];
+ oldHeroName = '';
+ oldPower = '';
+ oldLogLength = 0;
+ noChangeCount = 0;
+
+ // #docregion ng-do-check
+ ngDoCheck() {
+
+ if (this.hero.name !== this.oldHeroName) {
+ this.changeDetected = true;
+ this.changeLog.push(`DoCheck: Hero name changed to "${this.hero.name}" from "${this.oldHeroName}"`);
+ this.oldHeroName = this.hero.name;
+ }
+
+ if (this.power !== this.oldPower) {
+ this.changeDetected = true;
+ this.changeLog.push(`DoCheck: Power changed to "${this.power}" from "${this.oldPower}"`);
+ this.oldPower = this.power;
+ }
+
+ if (this.changeDetected) {
+ this.noChangeCount = 0;
+ } else {
+ // log that hook was called when there was no relevant change.
+ let count = this.noChangeCount += 1;
+ let noChangeMsg = `DoCheck called ${count}x when no change to hero or power`;
+ if (count === 1) {
+ // add new "no change" message
+ this.changeLog.push(noChangeMsg);
+ } else {
+ // update last "no change" message
+ this.changeLog[this.changeLog.length - 1] = noChangeMsg;
+ }
+ }
+
+ this.changeDetected = false;
+ }
+ // #enddocregion ng-do-check
+
+ reset() {
+ this.changeDetected = true;
+ this.changeLog.length = 0;
+ }
+}
+
+/***************************************/
+
+@Component({
+ selector: 'do-check-parent',
+ templateUrl: './do-check-parent.component.html',
+ styles: ['.parent {background: Lavender}']
+})
+export class DoCheckParentComponent {
+ hero: Hero;
+ power: string;
+ title = 'DoCheck';
+ @ViewChild(DoCheckComponent) childView: DoCheckComponent;
+
+ constructor() { this.reset(); }
+
+ reset() {
+ this.hero = new Hero('Windstorm');
+ this.power = 'sing';
+ if (this.childView) { this.childView.reset(); }
+ }
+}
diff --git a/public/docs/_examples/lifecycle-hooks/ts/src/app/logger.service.ts b/public/docs/_examples/lifecycle-hooks/ts/src/app/logger.service.ts
new file mode 100644
index 0000000000..56ddaf9063
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/ts/src/app/logger.service.ts
@@ -0,0 +1,26 @@
+import { Injectable } from '@angular/core';
+
+@Injectable()
+export class LoggerService {
+ logs: string[] = [];
+ prevMsg = '';
+ prevMsgCount = 1;
+
+ log(msg: string) {
+ if (msg === this.prevMsg) {
+ // Repeat message; update last log entry with count.
+ this.logs[this.logs.length - 1] = msg + ` (${this.prevMsgCount += 1}x)`;
+ } else {
+ // New message; log it.
+ this.prevMsg = msg;
+ this.prevMsgCount = 1;
+ this.logs.push(msg);
+ }
+ }
+
+ clear() { this.logs.length = 0; }
+
+ // schedules a view refresh to ensure display catches up
+ tick() { this.tick_then(() => { }); }
+ tick_then(fn: () => any) { setTimeout(fn, 0); }
+}
diff --git a/public/docs/_examples/lifecycle-hooks/ts/src/app/on-changes-parent.component.html b/public/docs/_examples/lifecycle-hooks/ts/src/app/on-changes-parent.component.html
new file mode 100644
index 0000000000..a0fd404931
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/ts/src/app/on-changes-parent.component.html
@@ -0,0 +1,13 @@
+
+
{{title}}
+
+
+
Reset Log
+
+
+
+
+
diff --git a/public/docs/_examples/lifecycle-hooks/ts/src/app/on-changes.component.ts b/public/docs/_examples/lifecycle-hooks/ts/src/app/on-changes.component.ts
new file mode 100644
index 0000000000..a5a49a61e9
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/ts/src/app/on-changes.component.ts
@@ -0,0 +1,73 @@
+/* tslint:disable:forin */
+// #docregion
+import {
+ Component, Input, OnChanges,
+ SimpleChanges, ViewChild
+} from '@angular/core';
+
+class Hero {
+ constructor(public name: string) {}
+}
+
+@Component({
+ selector: 'on-changes',
+ template: `
+
+
{{hero.name}} can {{power}}
+
+
-- Change Log --
+
{{chg}}
+
+ `,
+ styles: [
+ '.hero {background: LightYellow; padding: 8px; margin-top: 8px}',
+ 'p {background: Yellow; padding: 8px; margin-top: 8px}'
+ ]
+})
+export class OnChangesComponent implements OnChanges {
+// #docregion inputs
+ @Input() hero: Hero;
+ @Input() power: string;
+// #enddocregion inputs
+
+ changeLog: string[] = [];
+
+ // #docregion ng-on-changes
+ ngOnChanges(changes: SimpleChanges) {
+ for (let propName in changes) {
+ let chng = changes[propName];
+ let cur = JSON.stringify(chng.currentValue);
+ let prev = JSON.stringify(chng.previousValue);
+ this.changeLog.push(`${propName}: currentValue = ${cur}, previousValue = ${prev}`);
+ }
+ }
+ // #enddocregion ng-on-changes
+
+ reset() { this.changeLog.length = 0; }
+}
+
+/***************************************/
+
+@Component({
+ selector: 'on-changes-parent',
+ templateUrl: './on-changes-parent.component.html',
+ styles: ['.parent {background: Lavender;}']
+})
+export class OnChangesParentComponent {
+ hero: Hero;
+ power: string;
+ title = 'OnChanges';
+ @ViewChild(OnChangesComponent) childView: OnChangesComponent;
+
+ constructor() {
+ this.reset();
+ }
+
+ reset() {
+ // new Hero object every time; triggers onChanges
+ this.hero = new Hero('Windstorm');
+ // setting power only triggers onChanges if this value is different
+ this.power = 'sing';
+ if (this.childView) { this.childView.reset(); }
+ }
+}
diff --git a/public/docs/_examples/lifecycle-hooks/ts/src/app/peek-a-boo-parent.component.ts b/public/docs/_examples/lifecycle-hooks/ts/src/app/peek-a-boo-parent.component.ts
new file mode 100644
index 0000000000..3f2bd8585d
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/ts/src/app/peek-a-boo-parent.component.ts
@@ -0,0 +1,53 @@
+// #docregion
+import { Component } from '@angular/core';
+
+import { LoggerService } from './logger.service';
+
+@Component({
+ selector: 'peek-a-boo-parent',
+ template: `
+
+
Peek-A-Boo
+
+
+ {{hasChild ? 'Destroy' : 'Create'}} PeekABooComponent
+
+
Update Hero
+
+
+
+
+
-- Lifecycle Hook Log --
+
{{msg}}
+
+ `,
+ styles: ['.parent {background: moccasin}'],
+ providers: [ LoggerService ]
+})
+export class PeekABooParentComponent {
+
+ hasChild = false;
+ hookLog: string[];
+
+ heroName = 'Windstorm';
+ private logger: LoggerService;
+
+ constructor(logger: LoggerService) {
+ this.logger = logger;
+ this.hookLog = logger.logs;
+ }
+
+ toggleChild() {
+ this.hasChild = !this.hasChild;
+ if (this.hasChild) {
+ this.heroName = 'Windstorm';
+ this.logger.clear(); // clear log on create
+ }
+ this.logger.tick();
+ }
+
+ updateHero() {
+ this.heroName += '!';
+ this.logger.tick();
+ }
+}
diff --git a/public/docs/_examples/lifecycle-hooks/ts/src/app/peek-a-boo.component.ts b/public/docs/_examples/lifecycle-hooks/ts/src/app/peek-a-boo.component.ts
new file mode 100644
index 0000000000..dcee428753
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/ts/src/app/peek-a-boo.component.ts
@@ -0,0 +1,85 @@
+import {
+ AfterContentChecked,
+ AfterContentInit,
+ AfterViewChecked,
+ AfterViewInit,
+ DoCheck,
+ OnChanges,
+ OnDestroy,
+ OnInit,
+ SimpleChanges
+} from '@angular/core';
+import { Component, Input } from '@angular/core';
+import { LoggerService } from './logger.service';
+
+let nextId = 1;
+
+// #docregion ngOnInit
+export class PeekABoo implements OnInit {
+ constructor(private logger: LoggerService) { }
+
+ // implement OnInit's `ngOnInit` method
+ ngOnInit() { this.logIt(`OnInit`); }
+
+ logIt(msg: string) {
+ this.logger.log(`#${nextId++} ${msg}`);
+ }
+}
+// #enddocregion ngOnInit
+
+@Component({
+ selector: 'peek-a-boo',
+ template: 'Now you see my hero, {{name}}
',
+ styles: ['p {background: LightYellow; padding: 8px}']
+})
+// Don't HAVE to mention the Lifecycle Hook interfaces
+// unless we want typing and tool support.
+export class PeekABooComponent extends PeekABoo implements
+ OnChanges, OnInit, DoCheck,
+ AfterContentInit, AfterContentChecked,
+ AfterViewInit, AfterViewChecked,
+ OnDestroy {
+ @Input() name: string;
+
+ private verb = 'initialized';
+
+ constructor(logger: LoggerService) {
+ super(logger);
+
+ let is = this.name ? 'is' : 'is not';
+ this.logIt(`name ${is} known at construction`);
+ }
+
+ // only called for/if there is an @input variable set by parent.
+ ngOnChanges(changes: SimpleChanges) {
+ let changesMsgs: string[] = [];
+ for (let propName in changes) {
+ if (propName === 'name') {
+ let name = changes['name'].currentValue;
+ changesMsgs.push(`name ${this.verb} to "${name}"`);
+ } else {
+ changesMsgs.push(propName + ' ' + this.verb);
+ }
+ }
+ this.logIt(`OnChanges: ${changesMsgs.join('; ')}`);
+ this.verb = 'changed'; // next time it will be a change
+ }
+
+ // Beware! Called frequently!
+ // Called in every change detection cycle anywhere on the page
+ ngDoCheck() { this.logIt(`DoCheck`); }
+
+ ngAfterContentInit() { this.logIt(`AfterContentInit`); }
+
+ // Beware! Called frequently!
+ // Called in every change detection cycle anywhere on the page
+ ngAfterContentChecked() { this.logIt(`AfterContentChecked`); }
+
+ ngAfterViewInit() { this.logIt(`AfterViewInit`); }
+
+ // Beware! Called frequently!
+ // Called in every change detection cycle anywhere on the page
+ ngAfterViewChecked() { this.logIt(`AfterViewChecked`); }
+
+ ngOnDestroy() { this.logIt(`OnDestroy`); }
+}
diff --git a/public/docs/_examples/lifecycle-hooks/ts/src/app/spy.component.html b/public/docs/_examples/lifecycle-hooks/ts/src/app/spy.component.html
new file mode 100644
index 0000000000..782435b961
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/ts/src/app/spy.component.html
@@ -0,0 +1,16 @@
+
+
Spy Directive
+
+
+
Add Hero
+
Reset Heroes
+
+
+
+
+ {{hero}}
+
+
+
-- Spy Lifecycle Hook Log --
+
{{msg}}
+
diff --git a/public/docs/_examples/lifecycle-hooks/ts/src/app/spy.component.ts b/public/docs/_examples/lifecycle-hooks/ts/src/app/spy.component.ts
new file mode 100644
index 0000000000..0f3b0d35f1
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/ts/src/app/spy.component.ts
@@ -0,0 +1,40 @@
+// #docregion
+import { Component } from '@angular/core';
+
+import { LoggerService } from './logger.service';
+
+@Component({
+ selector: 'spy-parent',
+ templateUrl: './spy.component.html',
+ styles: [
+ '.parent {background: khaki;}',
+ '.heroes {background: LightYellow; padding: 0 8px}'
+ ],
+ providers: [LoggerService]
+})
+export class SpyParentComponent {
+ newName = 'Herbie';
+ heroes: string[] = ['Windstorm', 'Magneta'];
+ spyLog: string[];
+
+ constructor(private logger: LoggerService) {
+ this.spyLog = logger.logs;
+ }
+
+ addHero() {
+ if (this.newName.trim()) {
+ this.heroes.push(this.newName.trim());
+ this.newName = '';
+ this.logger.tick();
+ }
+ }
+ removeHero(hero: string) {
+ this.heroes.splice(this.heroes.indexOf(hero), 1);
+ this.logger.tick();
+ }
+ reset() {
+ this.logger.log('-- reset --');
+ this.heroes.length = 0;
+ this.logger.tick();
+ }
+}
diff --git a/public/docs/_examples/lifecycle-hooks/ts/src/app/spy.directive.ts b/public/docs/_examples/lifecycle-hooks/ts/src/app/spy.directive.ts
new file mode 100644
index 0000000000..01f3f95880
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/ts/src/app/spy.directive.ts
@@ -0,0 +1,24 @@
+// #docregion
+import { Directive, OnInit, OnDestroy } from '@angular/core';
+
+import { LoggerService } from './logger.service';
+
+let nextId = 1;
+
+// #docregion spy-directive
+// Spy on any element to which it is applied.
+// Usage: ...
+@Directive({selector: '[mySpy]'})
+export class SpyDirective implements OnInit, OnDestroy {
+
+ constructor(private logger: LoggerService) { }
+
+ ngOnInit() { this.logIt(`onInit`); }
+
+ ngOnDestroy() { this.logIt(`onDestroy`); }
+
+ private logIt(msg: string) {
+ this.logger.log(`Spy #${nextId++} ${msg}`);
+ }
+}
+// #enddocregion spy-directive
diff --git a/public/docs/_examples/lifecycle-hooks/ts/src/index.html b/public/docs/_examples/lifecycle-hooks/ts/src/index.html
new file mode 100644
index 0000000000..cf7059f780
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/ts/src/index.html
@@ -0,0 +1,28 @@
+
+
+
+
+ Angular Lifecycle Hooks
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
diff --git a/public/docs/_examples/lifecycle-hooks/ts/src/main.ts b/public/docs/_examples/lifecycle-hooks/ts/src/main.ts
new file mode 100644
index 0000000000..f22933ba8e
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/ts/src/main.ts
@@ -0,0 +1,4 @@
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/lifecycle-hooks/ts/src/sample.css b/public/docs/_examples/lifecycle-hooks/ts/src/sample.css
new file mode 100644
index 0000000000..df17c897c6
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/ts/src/sample.css
@@ -0,0 +1,13 @@
+.parent {
+ color: #666;
+ margin: 14px 0;
+ padding: 8px;
+}
+input {
+ margin: 4px;
+ padding: 4px;
+}
+.comment {
+ color: red;
+ font-style: italic;
+}
diff --git a/public/docs/_examples/upgrade/ts/typescript-conversion/app/img/.gitkeep b/public/docs/_examples/ngcontainer/ts/example-config.json
similarity index 100%
rename from public/docs/_examples/upgrade/ts/typescript-conversion/app/img/.gitkeep
rename to public/docs/_examples/ngcontainer/ts/example-config.json
diff --git a/public/docs/_examples/ngcontainer/ts/plnkr.json b/public/docs/_examples/ngcontainer/ts/plnkr.json
new file mode 100644
index 0000000000..a6cdc4ba1a
--- /dev/null
+++ b/public/docs/_examples/ngcontainer/ts/plnkr.json
@@ -0,0 +1,11 @@
+{
+ "description": "",
+ "basePath": "src/",
+ "files": [
+ "!**/*.d.ts",
+ "!**/*.js"
+ ],
+ "tags": [
+ "ngcontainer", "structural", "directives"
+ ]
+}
diff --git a/public/docs/_examples/ngcontainer/ts/src/app/app.component.css b/public/docs/_examples/ngcontainer/ts/src/app/app.component.css
new file mode 100644
index 0000000000..953ed3c39d
--- /dev/null
+++ b/public/docs/_examples/ngcontainer/ts/src/app/app.component.css
@@ -0,0 +1,34 @@
+/* #docregion */
+button {
+ min-width: 100px;
+ font-size: 100%;
+}
+
+code, .code {
+ background-color: #eee;
+ color: black;
+ font-family: Courier, sans-serif;
+ font-size: 85%;
+}
+
+div.code {
+ width: 400px;
+}
+
+.heroic {
+ font-size: 150%;
+ font-weight: bold;
+}
+
+hr {
+ margin: 40px 0
+}
+
+td, th {
+ text-align: left;
+ vertical-align: top;
+}
+
+/* #docregion p-span */
+p span { color: red; font-size: 70%; }
+/* #enddocregion p-span */
diff --git a/public/docs/_examples/ngcontainer/ts/src/app/app.component.html b/public/docs/_examples/ngcontainer/ts/src/app/app.component.html
new file mode 100644
index 0000000000..afd0b00f36
--- /dev/null
+++ b/public/docs/_examples/ngcontainer/ts/src/app/app.component.html
@@ -0,0 +1,279 @@
+
+
+<ng-container>
+
+
+{{hero.name}}
+
+
+
+
+<ng-container> and CSS
+Examples demonstrating issues with rigid CSS styles.
+
+Toggle hero
+
+#1 <ng-container> and <p>
+
+
+ I turned the corner
+
+ and saw {{hero.name}}. I waved
+
+ and continued on my way.
+
+
+
+
+ I turned the corner
+
+ and saw {{hero.name}}. I waved
+
+ and continued on my way.
+
+
+
+#2 <ng-container> and <p>
+
+
+
+
+ {{hero.name}} is
+
+ ,
+ and
+ {{trait}}
+ .
+
+
+
+
+
+ {{hero.name}} is
+
+ ,
+ and
+ {{trait}}
+ .
+
+
+
+
+
+
#3 <ng-container> and <p>
+
+
+ Show ID
+
+
+
+
+ The
hero.id
in the <span>
+ is caught by the
p-span CSS:
+
+
+
+ Id: ({{hero.id}})
+
+ Name: {{hero.name}}
+
+
+
+
+
+ The
hero.id
in the <ng-container>
+ is unaffected by the
p-span CSS:
+
+
+ Id: ({{hero.id}})
+
+ Name: {{hero.name}}
+
+
+
+
+ The
hero.id
in the <template *ngIf> disappears:
+
+
+ Id: ({{hero.id}})
+
+ Name: {{hero.name}}
+
+
+
+
+ The
hero.id
in the <template [ngIf]>
+ is unaffected by the
p-span CSS:
+
+
+ Id: ({{hero.id}})
+
+ Name: {{hero.name}}
+
+
+
+
+
+
+
+<ng-container> and layout-sensitive elements
+
+ Examples demonstrating issues with layout-sensitive elements
+ such as <select> and <table>.
+
+
+#1 <ng-container> and <options>
+
+<select> with <span>
+
+ Pick your favorite hero
+ ( show sad )
+
+
+
+
+
+ {{h.name}} ({{h?.emotion}})
+
+
+
+
+
+<select> with <ng-container>
+
+ Pick your favorite hero
+ ( show sad )
+
+
+
+
+
+ {{h.name}} ({{h?.emotion}})
+
+
+
+
+
+
+
+#2 <ng-container> and <options>
+
+
+ Show default traits
+
+
+
+Options with <ng-container>
+
+
+
+
+
+ LOYAL
+ CLEAN
+ REVERENT
+
+
+ {{ trait | uppercase }}
+
+
+
+
+
+Options with <span>
+
+
+
+
+ LOYAL
+ CLEAN
+ REVERENT
+
+
+ {{ trait | uppercase }}
+
+
+
+
+
+
+<ng-container> and <table>
+
+ Attribute directives
+ Structural directives
+ div with *ngIf
+
+
+
+
+ Directive
+ Type
+ Description
+
+
+
+ NgClass A Add or remove multiple CSS classes.
+
+
+
+
+
+
+ xxx S div with *ngIf formats crazy.
+
+
+ yyy S div with *ngIf formats crazy.
+
+
+
+
+
+
+
+
+ NgFor S Repeat the template for each item in a list.
+
+
+ NgIf S Add or remove DOM elements.
+
+
+
+
+
+
+ NgStyle A Add or remove multiple style attributes.
+
+
+
+
+
+ NgSwitch S Include in DOM if case matches the switch value.
+
+
+
+
+
+
+
+Do not confuse <ng-container> with <ng-content>
+
+<ng-container>Inside ng-container</ng-container>
+
+Inside ng-container
+
+
+<ng-content>this is an Angular parse error</ng-content>
+
+
+
+Template parse errors:
+<ng-content> element cannot have content.
+
+Demo of </ng-content>
+
+
+ Projected content
+
+
diff --git a/public/docs/_examples/ngcontainer/ts/src/app/app.component.ts b/public/docs/_examples/ngcontainer/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..65c511acd2
--- /dev/null
+++ b/public/docs/_examples/ngcontainer/ts/src/app/app.component.ts
@@ -0,0 +1,24 @@
+// #docregion
+import { Component } from '@angular/core';
+
+import { heroes } from './hero';
+
+@Component({
+ selector: 'my-app',
+ templateUrl: './app.component.html',
+ styleUrls: [ './app.component.css' ]
+})
+export class AppComponent {
+ heroes = heroes;
+ hero = this.heroes[0];
+ heroTraits = [ 'honest', 'brave', 'considerate' ];
+
+ // flags for the table
+ attrDirs = true;
+ strucDirs = true;
+ divNgIf = false;
+
+ showId = true;
+ showDefaultTraits = true;
+ showSad = true;
+}
diff --git a/public/docs/_examples/ngcontainer/ts/src/app/app.module.ts b/public/docs/_examples/ngcontainer/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..57ac92f518
--- /dev/null
+++ b/public/docs/_examples/ngcontainer/ts/src/app/app.module.ts
@@ -0,0 +1,19 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+import { BrowserModule } from '@angular/platform-browser';
+
+import { AppComponent } from './app.component';
+import { ContentComponent } from './content.component';
+import { heroComponents } from './hero.components';
+
+@NgModule({
+ imports: [ BrowserModule, FormsModule ],
+ declarations: [
+ AppComponent,
+ ContentComponent,
+ heroComponents
+ ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/ngcontainer/ts/src/app/content.component.ts b/public/docs/_examples/ngcontainer/ts/src/app/content.component.ts
new file mode 100644
index 0000000000..63c5646f99
--- /dev/null
+++ b/public/docs/_examples/ngcontainer/ts/src/app/content.component.ts
@@ -0,0 +1,16 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'content-comp',
+ // #docregion template
+ template:
+ `
+
+
`,
+ // #enddocregion template
+ styles: [ `
+ div { border: medium dashed green; padding: 1em; width: 150px; text-align: center}
+ `]
+})
+export class ContentComponent { }
diff --git a/public/docs/_examples/ngcontainer/ts/src/app/hero.components.ts b/public/docs/_examples/ngcontainer/ts/src/app/hero.components.ts
new file mode 100644
index 0000000000..43e400ed8e
--- /dev/null
+++ b/public/docs/_examples/ngcontainer/ts/src/app/hero.components.ts
@@ -0,0 +1,43 @@
+// #docregion
+import { Component, Input } from '@angular/core';
+import { Hero } from './hero';
+
+@Component({
+ selector: 'happy-hero',
+ template: `Wow. You like {{hero.name}}. What a happy hero ... just like you.`
+})
+export class HappyHeroComponent {
+ @Input() hero: Hero;
+}
+
+@Component({
+ selector: 'sad-hero',
+ template: `You like {{hero.name}}? Such a sad hero. Are you sad too?`
+})
+export class SadHeroComponent {
+ @Input() hero: Hero;
+}
+
+@Component({
+ selector: 'confused-hero',
+ template: `Are you as confused as {{hero.name}}?`
+})
+export class ConfusedHeroComponent {
+ @Input() hero: Hero;
+}
+
+@Component({
+ selector: 'unknown-hero',
+ template: `{{message}}`
+})
+export class UnknownHeroComponent {
+ @Input() hero: Hero;
+ get message() {
+ return this.hero && this.hero.name ?
+ `${this.hero.name} is strange and mysterious.` :
+ 'Are you feeling indecisive?';
+ }
+}
+
+export const heroComponents =
+ [ HappyHeroComponent, SadHeroComponent, ConfusedHeroComponent, UnknownHeroComponent ];
diff --git a/public/docs/_examples/ngcontainer/ts/src/app/hero.ts b/public/docs/_examples/ngcontainer/ts/src/app/hero.ts
new file mode 100644
index 0000000000..a1de3b3b82
--- /dev/null
+++ b/public/docs/_examples/ngcontainer/ts/src/app/hero.ts
@@ -0,0 +1,13 @@
+// #docregion
+export class Hero {
+ id: number;
+ name: string;
+ emotion?: string;
+}
+
+export const heroes: Hero[] = [
+ { id: 1, name: 'Mr. Nice', emotion: 'happy'},
+ { id: 2, name: 'Narco', emotion: 'sad' },
+ { id: 3, name: 'Windstorm', emotion: 'confused' },
+ { id: 4, name: 'Magneta'}
+];
diff --git a/public/docs/_examples/ngcontainer/ts/src/index.html b/public/docs/_examples/ngcontainer/ts/src/index.html
new file mode 100644
index 0000000000..fc5ff417c3
--- /dev/null
+++ b/public/docs/_examples/ngcontainer/ts/src/index.html
@@ -0,0 +1,26 @@
+
+
+
+
+ Angular <ng-container>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
diff --git a/public/docs/_examples/ngcontainer/ts/src/main.ts b/public/docs/_examples/ngcontainer/ts/src/main.ts
new file mode 100644
index 0000000000..105b06712d
--- /dev/null
+++ b/public/docs/_examples/ngcontainer/ts/src/main.ts
@@ -0,0 +1,6 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
+
diff --git a/public/docs/_examples/ngmodule/e2e-spec.ts b/public/docs/_examples/ngmodule/e2e-spec.ts
new file mode 100644
index 0000000000..0fbce1213d
--- /dev/null
+++ b/public/docs/_examples/ngmodule/e2e-spec.ts
@@ -0,0 +1,223 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by } from 'protractor';
+
+describe('NgModule', function () {
+
+ // helpers
+ const gold = 'rgba(255, 215, 0, 1)';
+ const powderblue = 'rgba(176, 224, 230, 1)';
+ const lightgray = 'rgba(211, 211, 211, 1)';
+ const white = 'rgba(0, 0, 0, 0)';
+
+ function getCommonsSectionStruct() {
+ const buttons = element.all(by.css('nav a'));
+
+ return {
+ title: element.all(by.tagName('h1')).get(0),
+ subtitle: element.all(by.css('app-title p i')).get(0),
+ contactButton: buttons.get(0),
+ crisisButton: buttons.get(1),
+ heroesButton: buttons.get(2)
+ };
+ }
+
+ function getContactSectionStruct() {
+ const buttons = element.all(by.css('app-contact form button'));
+
+ return {
+ header: element.all(by.css('app-contact h2')).get(0),
+ popupMessage: element.all(by.css('app-contact div')).get(0),
+ contactNameHeader: element.all(by.css('app-contact form h3')).get(0),
+ input: element.all(by.css('app-contact form input')).get(0),
+ validationError: element.all(by.css('app-contact form .alert')).get(0),
+ saveButton: buttons.get(0), // can't be tested
+ nextContactButton: buttons.get(1),
+ newContactButton: buttons.get(2)
+ };
+ }
+
+ function getCrisisSectionStruct() {
+ return {
+ title: element.all(by.css('ng-component h3')).get(0),
+ items: element.all(by.css('ng-component a')),
+ itemId: element.all(by.css('ng-component div')).get(0),
+ listLink: element.all(by.css('ng-component a')).get(0),
+ };
+ }
+
+ function getHeroesSectionStruct() {
+ return {
+ header: element.all(by.css('ng-component h2')).get(0),
+ title: element.all(by.css('ng-component h3')).get(0),
+ items: element.all(by.css('ng-component a')),
+ itemId: element.all(by.css('ng-component ng-component div div')).get(0),
+ itemInput: element.all(by.css('ng-component ng-component input')).get(0),
+ listLink: element.all(by.css('ng-component ng-component a')).get(0),
+ };
+ }
+
+ // tests
+ function appTitleTests(color: string, name?: string) {
+ return function() {
+ it('should have a gray header', function() {
+ const commons = getCommonsSectionStruct();
+ expect(commons.title.getCssValue('backgroundColor')).toBe(color);
+ });
+
+ it('should welcome us', function () {
+ const commons = getCommonsSectionStruct();
+ expect(commons.subtitle.getText()).toBe('Welcome, ' + (name || 'Sherlock Holmes'));
+ });
+ };
+ }
+
+ function contactTests(color: string, name?: string) {
+ return function() {
+ it('shows the contact\'s owner', function() {
+ const contacts = getContactSectionStruct();
+ expect(contacts.header.getText()).toBe('Contact of ' + (name || 'Sherlock Holmes'));
+ });
+
+ it('can cycle between contacts', function () {
+ const contacts = getContactSectionStruct();
+ const nextButton = contacts.nextContactButton;
+ expect(contacts.contactNameHeader.getText()).toBe('Awesome Sam Spade');
+ expect(contacts.contactNameHeader.getCssValue('backgroundColor')).toBe(color);
+ nextButton.click().then(function () {
+ expect(contacts.contactNameHeader.getText()).toBe('Awesome Nick Danger');
+ return nextButton.click();
+ }).then(function () {
+ expect(contacts.contactNameHeader.getText()).toBe('Awesome Nancy Drew');
+ });
+ });
+
+ it('can change an existing contact', function () {
+ const contacts = getContactSectionStruct();
+ contacts.input.sendKeys('a');
+ expect(contacts.input.getCssValue('backgroundColor')).toBe(color);
+ expect(contacts.contactNameHeader.getText()).toBe('Awesome Sam Spadea');
+ });
+
+ it('can create a new contact', function () {
+ const contacts = getContactSectionStruct();
+ const newContactButton = contacts.newContactButton;
+ newContactButton.click().then(function () {
+ expect(contacts.validationError.getText()).toBe('Name is required');
+ contacts.input.sendKeys('John Doe');
+ expect(contacts.contactNameHeader.getText()).toBe('Awesome John Doe');
+ expect(contacts.validationError.getText()).toBe('');
+ });
+ });
+ };
+ }
+
+ describe('index.html', function () {
+ beforeEach(function () {
+ browser.get('');
+ });
+
+ describe('app-title', appTitleTests(white, 'Miss Marple'));
+
+ describe('contact', contactTests(lightgray, 'Miss Marple'));
+
+ describe('crisis center', function () {
+ beforeEach(function () {
+ getCommonsSectionStruct().crisisButton.click();
+ });
+
+ it('shows a list of crisis', function () {
+ const crisis = getCrisisSectionStruct();
+ expect(crisis.title.getText()).toBe('Crisis List');
+ expect(crisis.items.count()).toBe(4);
+ expect(crisis.items.get(0).getText()).toBe('1 - Dragon Burning Cities');
+ });
+
+ it('can navigate to one crisis details', function () {
+ const crisis = getCrisisSectionStruct();
+ crisis.items.get(0).click().then(function() {
+ expect(crisis.itemId.getText()).toBe('Crisis id: 1');
+ return crisis.listLink.click();
+ }).then(function () {
+ // We are back to the list
+ expect(crisis.items.count()).toBe(4);
+ });
+ });
+ });
+
+ describe('heroes', function () {
+ beforeEach(function () {
+ getCommonsSectionStruct().heroesButton.click();
+ });
+
+ it('shows a list of heroes', function() {
+ const heroes = getHeroesSectionStruct();
+ expect(heroes.header.getText()).toBe('Heroes of Miss Marple');
+ expect(heroes.title.getText()).toBe('Hero List');
+ expect(heroes.items.count()).toBe(6);
+ expect(heroes.items.get(0).getText()).toBe('11 - Mr. Nice');
+ });
+
+ it('can navigate and edit one hero details', function () {
+ const heroes = getHeroesSectionStruct();
+ heroes.items.get(0).click().then(function () {
+ expect(heroes.itemId.getText()).toBe('Id: 11');
+ heroes.itemInput.sendKeys(' try');
+ return heroes.listLink.click();
+ }).then(function () {
+ // We are back to the list
+ expect(heroes.items.count()).toBe(6);
+ expect(heroes.items.get(0).getText()).toBe('11 - Mr. Nice try');
+ });
+ });
+ });
+ });
+
+ describe('index.0.html', function() {
+ beforeEach(function () {
+ browser.get('index.0.html');
+ });
+
+ it('has a title', function () {
+ const title = element.all(by.tagName('h1')).get(0);
+ expect(title.getText()).toBe('Minimal NgModule');
+ });
+ });
+
+ describe('index.1.html', function () {
+ beforeEach(function () {
+ browser.get('index.1.html');
+ });
+
+ describe('app-title', appTitleTests(powderblue));
+ });
+
+ describe('index.1b.html', function () {
+ beforeEach(function () {
+ browser.get('index.1b.html');
+ });
+
+ describe('app-title', appTitleTests(powderblue));
+
+ describe('contact', contactTests(powderblue));
+ });
+
+ describe('index.2.html', function () {
+ beforeEach(function () {
+ browser.get('index.2.html');
+ });
+
+ describe('app-title', appTitleTests(gold));
+
+ describe('contact', contactTests(powderblue));
+ });
+
+ describe('index.3.html', function () {
+ beforeEach(function () {
+ browser.get('index.3.html');
+ });
+
+ describe('app-title', appTitleTests(gold));
+ });
+
+});
diff --git a/public/docs/_examples/ngmodule/ts/contact.1b.plnkr.json b/public/docs/_examples/ngmodule/ts/contact.1b.plnkr.json
new file mode 100644
index 0000000000..0f61c91f75
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/contact.1b.plnkr.json
@@ -0,0 +1,25 @@
+{
+ "description": "Contact NgModule v.1",
+ "basePath": "src/",
+ "files": [
+ "app/app.component.1b.ts",
+ "app/app.module.1b.ts",
+ "app/highlight.directive.ts",
+ "app/title.component.html",
+ "app/title.component.ts",
+ "app/user.service.ts",
+
+ "app/contact/awesome.pipe.ts",
+ "app/contact/contact.component.css",
+ "app/contact/contact.component.html",
+ "app/contact/contact.component.3.ts",
+ "app/contact/contact.service.ts",
+ "app/contact/highlight.directive.ts",
+
+ "main.1b.ts",
+ "styles.css",
+ "index.1b.html"
+ ],
+ "main": "index.1b.html",
+ "tags": ["NgModule"]
+}
diff --git a/public/docs/_examples/ngmodule/ts/contact.2.plnkr.json b/public/docs/_examples/ngmodule/ts/contact.2.plnkr.json
new file mode 100644
index 0000000000..6555b76dcd
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/contact.2.plnkr.json
@@ -0,0 +1,27 @@
+{
+ "description": "Contact NgModule v.2",
+ "basePath": "src/",
+ "files": [
+ "app/app.component.2.ts",
+ "app/app.module.2.ts",
+ "app/highlight.directive.ts",
+ "app/title.component.html",
+ "app/title.component.ts",
+ "app/user.service.ts",
+
+ "app/contact/contact.component.css",
+ "app/contact/contact.component.html",
+ "app/contact/contact.service.ts",
+
+ "app/contact/awesome.pipe.ts",
+ "app/contact/contact.component.3.ts",
+ "app/contact/contact.module.2.ts",
+ "app/contact/highlight.directive.ts",
+
+ "main.2.ts",
+ "styles.css",
+ "index.2.html"
+ ],
+ "main": "index.2.html",
+ "tags": ["NgModule"]
+}
diff --git a/public/docs/_examples/ngmodule/ts/example-config.json b/public/docs/_examples/ngmodule/ts/example-config.json
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/public/docs/_examples/ngmodule/ts/minimal.0.plnkr.json b/public/docs/_examples/ngmodule/ts/minimal.0.plnkr.json
new file mode 100644
index 0000000000..e5e37ac4ee
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/minimal.0.plnkr.json
@@ -0,0 +1,13 @@
+{
+ "description": "Minimal NgModule",
+ "basePath": "src/",
+ "files": [
+ "app/app.component.0.ts",
+ "app/app.module.0.ts",
+ "main.0.ts",
+ "styles.css",
+ "index.0.html"
+ ],
+ "main": "index.0.html",
+ "tags": ["NgModule"]
+}
diff --git a/public/docs/_examples/ngmodule/ts/plnkr.json b/public/docs/_examples/ngmodule/ts/plnkr.json
new file mode 100644
index 0000000000..4d9d2ec20b
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/plnkr.json
@@ -0,0 +1,41 @@
+{
+ "description": "NgModule Final",
+ "basePath": "src/",
+ "files": [
+ "app/app.component.ts",
+ "app/app.module.ts",
+ "app/app-routing.module.ts",
+
+ "app/contact/contact.component.css",
+ "app/contact/contact.component.html",
+ "app/contact/contact.service.ts",
+
+ "app/contact/contact.component.ts",
+ "app/contact/contact.module.ts",
+ "app/contact/contact-routing.module.ts",
+
+ "app/crisis/*.ts",
+
+ "app/hero/hero-detail.component.ts",
+ "app/hero/hero-list.component.ts",
+ "app/hero/hero.service.ts",
+
+ "app/hero/hero.component.ts",
+ "app/hero/hero.module.ts",
+ "app/hero/hero-routing.module.ts",
+
+ "app/core/*.css",
+ "app/core/*.html",
+ "app/core/*.ts",
+
+ "app/shared/*.css",
+ "app/shared/*.html",
+ "app/shared/*.ts",
+
+ "main.ts",
+ "styles.css",
+ "index.html"
+ ],
+ "main": "index.html",
+ "tags": ["NgModule"]
+}
diff --git a/public/docs/_examples/ngmodule/ts/pre-shared.3.plnkr.json b/public/docs/_examples/ngmodule/ts/pre-shared.3.plnkr.json
new file mode 100644
index 0000000000..9747801604
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/pre-shared.3.plnkr.json
@@ -0,0 +1,41 @@
+{
+ "description": "NgModule v.3",
+ "basePath": "src/",
+ "files": [
+ "app/app.component.3.ts",
+ "app/app.module.3.ts",
+ "app/app-routing.module.3.ts",
+
+ "app/highlight.directive.ts",
+ "app/title.component.html",
+ "app/title.component.ts",
+ "app/user.service.ts",
+
+ "app/contact/contact.component.css",
+ "app/contact/contact.component.html",
+ "app/contact/contact.service.ts",
+
+ "app/contact/awesome.pipe.ts",
+ "app/contact/contact.component.3.ts",
+ "app/contact/contact.module.3.ts",
+ "app/contact/contact-routing.module.3.ts",
+ "app/contact/highlight.directive.ts",
+
+ "app/crisis/*.ts",
+
+ "app/hero/hero-detail.component.ts",
+ "app/hero/hero-list.component.ts",
+ "app/hero/hero.service.ts",
+
+ "app/hero/hero.component.3.ts",
+ "app/hero/hero.module.3.ts",
+ "app/hero/hero-routing.module.3.ts",
+ "app/hero/highlight.directive.ts",
+
+ "main.3.ts",
+ "styles.css",
+ "index.3.html"
+ ],
+ "main": "index.3.html",
+ "tags": ["NgModule"]
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/app-routing.module.3.ts b/public/docs/_examples/ngmodule/ts/src/app/app-routing.module.3.ts
new file mode 100644
index 0000000000..1d53b708f8
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/app-routing.module.3.ts
@@ -0,0 +1,14 @@
+import { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+
+export const routes: Routes = [
+ { path: '', redirectTo: 'contact', pathMatch: 'full'},
+ { path: 'crisis', loadChildren: 'app/crisis/crisis.module#CrisisModule' },
+ { path: 'heroes', loadChildren: 'app/hero/hero.module.3#HeroModule' }
+];
+
+@NgModule({
+ imports: [RouterModule.forRoot(routes)],
+ exports: [RouterModule]
+})
+export class AppRoutingModule {}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/app-routing.module.ts b/public/docs/_examples/ngmodule/ts/src/app/app-routing.module.ts
new file mode 100644
index 0000000000..c753dcd488
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/app-routing.module.ts
@@ -0,0 +1,19 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+
+export const routes: Routes = [
+ { path: '', redirectTo: 'contact', pathMatch: 'full'},
+// #docregion lazy-routes
+ { path: 'crisis', loadChildren: 'app/crisis/crisis.module#CrisisModule' },
+ { path: 'heroes', loadChildren: 'app/hero/hero.module#HeroModule' }
+// #enddocregion lazy-routes
+];
+
+// #docregion forRoot
+@NgModule({
+ imports: [RouterModule.forRoot(routes)],
+ exports: [RouterModule]
+})
+export class AppRoutingModule {}
+// #enddocregion forRoot
diff --git a/public/docs/_examples/ngmodule/ts/src/app/app.component.0.ts b/public/docs/_examples/ngmodule/ts/src/app/app.component.0.ts
new file mode 100644
index 0000000000..4977890c3b
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/app.component.0.ts
@@ -0,0 +1,10 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ template: '{{title}} ',
+})
+export class AppComponent {
+ title = 'Minimal NgModule';
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/app.component.1.ts b/public/docs/_examples/ngmodule/ts/src/app/app.component.1.ts
new file mode 100644
index 0000000000..ccf44d4416
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/app.component.1.ts
@@ -0,0 +1,19 @@
+// #docplaster
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+// #enddocregion
+ /*
+ // #docregion template
+ template: '{{title}} '
+ // #enddocregion template
+ */
+// #docregion
+ template: ' '
+})
+export class AppComponent {
+ subtitle = '(v1)';
+}
+// #enddocregion
diff --git a/public/docs/_examples/ngmodule/ts/src/app/app.component.1b.ts b/public/docs/_examples/ngmodule/ts/src/app/app.component.1b.ts
new file mode 100644
index 0000000000..291bf0ac6b
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/app.component.1b.ts
@@ -0,0 +1,15 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ // #docregion template
+ template: `
+
+
+ `
+ // #enddocregion template
+})
+export class AppComponent {
+ subtitle = '(v1)';
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/app.component.2.ts b/public/docs/_examples/ngmodule/ts/src/app/app.component.2.ts
new file mode 100644
index 0000000000..a68b7d337d
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/app.component.2.ts
@@ -0,0 +1,12 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ template: `
+
+
+ `
+})
+export class AppComponent {
+ subtitle = '(v2)';
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/app.component.3.ts b/public/docs/_examples/ngmodule/ts/src/app/app.component.3.ts
new file mode 100644
index 0000000000..6d69a56f70
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/app.component.3.ts
@@ -0,0 +1,19 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ // #docregion template
+ template: `
+
+
+ Contact
+ Crisis Center
+ Heroes
+
+
+ `
+ // #enddocregion template
+})
+export class AppComponent {
+ subtitle = '(v3)';
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/app.component.ts b/public/docs/_examples/ngmodule/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..67336c8b08
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/app.component.ts
@@ -0,0 +1,19 @@
+// #docplaster
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ template: `
+
+
+ Contact
+ Crisis Center
+ Heroes
+
+
+ `
+})
+export class AppComponent {
+ subtitle = '(Final)';
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/app.module.0.ts b/public/docs/_examples/ngmodule/ts/src/app/app.module.0.ts
new file mode 100644
index 0000000000..144ad7bb50
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/app.module.0.ts
@@ -0,0 +1,23 @@
+// #docplaster
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+import
+// #enddocregion
+ { AppComponent } from './app.component.0';
+/*
+// #docregion
+ { AppComponent } from './app.component';
+// #enddocregion
+*/
+// #docregion
+
+@NgModule({
+// #docregion imports
+ imports: [ BrowserModule ],
+// #enddocregion imports
+ declarations: [ AppComponent ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/ngmodule/ts/src/app/app.module.1.ts b/public/docs/_examples/ngmodule/ts/src/app/app.module.1.ts
new file mode 100644
index 0000000000..f9f50e18d0
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/app.module.1.ts
@@ -0,0 +1,54 @@
+// #docplaster
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+import
+// #enddocregion
+ { AppComponent } from './app.component.1';
+/*
+// #docregion
+ { AppComponent } from './app.component';
+// #enddocregion
+*/
+// #docregion
+import { HighlightDirective } from './highlight.directive';
+import { TitleComponent } from './title.component';
+import { UserService } from './user.service';
+
+/* Contact Related Imports */
+import { FormsModule } from '@angular/forms';
+
+import { AwesomePipe } from './contact/awesome.pipe';
+import { ContactComponent } from './contact/contact.component.3';
+
+// #docregion import-contact-directive
+import {
+ HighlightDirective as ContactHighlightDirective
+} from './contact/highlight.directive';
+// #enddocregion import-contact-directive
+
+@NgModule({
+// #docregion imports
+ imports: [ BrowserModule, FormsModule ],
+// #enddocregion imports
+// #docregion declarations, directive, component
+ declarations: [
+ AppComponent,
+ HighlightDirective,
+// #enddocregion directive
+ TitleComponent,
+// #enddocregion component
+
+ AwesomePipe,
+ ContactComponent,
+ ContactHighlightDirective
+// #docregion directive, component
+ ],
+// #enddocregion declarations, directive, component
+// #docregion providers
+ providers: [ UserService ],
+// #enddocregion providers
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/ngmodule/ts/src/app/app.module.1b.ts b/public/docs/_examples/ngmodule/ts/src/app/app.module.1b.ts
new file mode 100644
index 0000000000..ae04326239
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/app.module.1b.ts
@@ -0,0 +1,53 @@
+// #docplaster
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+/* App Root */
+import
+// #enddocregion
+ { AppComponent } from './app.component.1b';
+/*
+// #docregion
+ { AppComponent } from './app.component';
+// #enddocregion
+*/
+// #docregion
+import { HighlightDirective } from './highlight.directive';
+import { TitleComponent } from './title.component';
+import { UserService } from './user.service';
+
+/* Contact Imports */
+import
+// #enddocregion
+ { ContactComponent } from './contact/contact.component.3';
+/*
+// #docregion
+ { ContactComponent } from './contact/contact.component';
+// #enddocregion
+*/
+// #docregion
+import { ContactService } from './contact/contact.service';
+import { AwesomePipe } from './contact/awesome.pipe';
+
+// #docregion import-alias
+import {
+ HighlightDirective as ContactHighlightDirective
+} from './contact/highlight.directive';
+// #enddocregion import-alias
+
+import { FormsModule } from '@angular/forms';
+
+@NgModule({
+ imports: [ BrowserModule, FormsModule ],
+// #docregion declarations
+ declarations: [
+ AppComponent, HighlightDirective, TitleComponent,
+ AwesomePipe, ContactComponent, ContactHighlightDirective
+ ],
+// #docregion providers
+ providers: [ ContactService, UserService ],
+// #enddocregion providers
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/ngmodule/ts/src/app/app.module.2.ts b/public/docs/_examples/ngmodule/ts/src/app/app.module.2.ts
new file mode 100644
index 0000000000..f00e9b5d27
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/app.module.2.ts
@@ -0,0 +1,37 @@
+// #docplaster
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+/* App Root */
+import
+// #enddocregion
+ { AppComponent } from './app.component.2';
+/*
+// #docregion
+ { AppComponent } from './app.component';
+// #enddocregion
+*/
+// #docregion
+import { HighlightDirective } from './highlight.directive';
+import { TitleComponent } from './title.component';
+import { UserService } from './user.service';
+
+/* Contact Imports */
+import
+// #enddocregion
+ { ContactModule } from './contact/contact.module.2';
+/*
+// #docregion
+ { ContactModule } from './contact/contact.module';
+// #enddocregion
+*/
+// #docregion
+
+@NgModule({
+ imports: [ BrowserModule, ContactModule ],
+ declarations: [ AppComponent, HighlightDirective, TitleComponent ],
+ providers: [ UserService ],
+ bootstrap: [ AppComponent ],
+})
+export class AppModule { }
diff --git a/public/docs/_examples/ngmodule/ts/src/app/app.module.3.ts b/public/docs/_examples/ngmodule/ts/src/app/app.module.3.ts
new file mode 100644
index 0000000000..8ca0a46d9a
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/app.module.3.ts
@@ -0,0 +1,30 @@
+// #docplaster
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+/* App Root */
+import { AppComponent } from './app.component.3';
+import { HighlightDirective } from './highlight.directive';
+import { TitleComponent } from './title.component';
+import { UserService } from './user.service';
+
+/* Feature Modules */
+import { ContactModule } from './contact/contact.module.3';
+
+/* Routing Module */
+import { AppRoutingModule } from './app-routing.module.3';
+
+@NgModule({
+// #docregion imports
+ imports: [
+ BrowserModule,
+ ContactModule,
+ AppRoutingModule
+ ],
+// #enddocregion imports
+ providers: [ UserService ],
+ declarations: [ AppComponent, HighlightDirective, TitleComponent ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/ngmodule/ts/src/app/app.module.ts b/public/docs/_examples/ngmodule/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..da03420804
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/app.module.ts
@@ -0,0 +1,40 @@
+// #docplaster
+// #docregion
+// #docregion v4
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+/* App Root */
+import { AppComponent } from './app.component';
+
+/* Feature Modules */
+import { ContactModule } from './contact/contact.module';
+import { CoreModule } from './core/core.module';
+
+/* Routing Module */
+import { AppRoutingModule } from './app-routing.module';
+
+@NgModule({
+ // #docregion import-for-root
+ imports: [
+ BrowserModule,
+ ContactModule,
+// #enddocregion v4
+// #enddocregion import-for-root
+/*
+// #docregion v4
+ CoreModule,
+// #enddocregion v4
+*/
+// #docregion import-for-root
+ CoreModule.forRoot({userName: 'Miss Marple'}),
+// #docregion v4
+ AppRoutingModule
+ ],
+ // #enddocregion import-for-root
+ declarations: [ AppComponent ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
+// #enddocregion v4
+// #enddocregion
diff --git a/public/docs/_examples/ngmodule/ts/src/app/contact/awesome.pipe.ts b/public/docs/_examples/ngmodule/ts/src/app/contact/awesome.pipe.ts
new file mode 100644
index 0000000000..d6dce99901
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/contact/awesome.pipe.ts
@@ -0,0 +1,10 @@
+// #docregion
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({ name: 'awesome' })
+/** Precede the input string with the word "Awesome " */
+export class AwesomePipe implements PipeTransform {
+ transform(phrase: string) {
+ return phrase ? 'Awesome ' + phrase : '';
+ }
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/contact/contact-routing.module.3.ts b/public/docs/_examples/ngmodule/ts/src/app/contact/contact-routing.module.3.ts
new file mode 100644
index 0000000000..27dfc232b7
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/contact/contact-routing.module.3.ts
@@ -0,0 +1,12 @@
+import { NgModule } from '@angular/core';
+import { RouterModule } from '@angular/router';
+
+import { ContactComponent } from './contact.component.3';
+
+@NgModule({
+ imports: [RouterModule.forChild([
+ { path: 'contact', component: ContactComponent}
+ ])],
+ exports: [RouterModule]
+})
+export class ContactRoutingModule {}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/contact/contact-routing.module.ts b/public/docs/_examples/ngmodule/ts/src/app/contact/contact-routing.module.ts
new file mode 100644
index 0000000000..2fa81af5a9
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/contact/contact-routing.module.ts
@@ -0,0 +1,14 @@
+import { NgModule } from '@angular/core';
+import { RouterModule } from '@angular/router';
+
+import { ContactComponent } from './contact.component';
+
+// #docregion routing
+@NgModule({
+ imports: [RouterModule.forChild([
+ { path: 'contact', component: ContactComponent }
+ ])],
+ exports: [RouterModule]
+})
+export class ContactRoutingModule {}
+// #enddocregion
diff --git a/public/docs/_examples/ngmodule/ts/src/app/contact/contact.component.3.ts b/public/docs/_examples/ngmodule/ts/src/app/contact/contact.component.3.ts
new file mode 100644
index 0000000000..ea6e9868ba
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/contact/contact.component.3.ts
@@ -0,0 +1,53 @@
+// #docregion
+import { Component, OnInit } from '@angular/core';
+
+import { Contact, ContactService } from './contact.service';
+import { UserService } from '../user.service';
+
+@Component({
+ selector: 'app-contact',
+ templateUrl: './contact.component.html',
+ styleUrls: [ './contact.component.css' ]
+})
+export class ContactComponent implements OnInit {
+ contact: Contact;
+ contacts: Contact[];
+
+ msg = 'Loading contacts ...';
+ userName = '';
+
+ constructor(private contactService: ContactService, userService: UserService) {
+ this.userName = userService.userName;
+ }
+
+ ngOnInit() {
+ this.contactService.getContacts().then(contacts => {
+ this.msg = '';
+ this.contacts = contacts;
+ this.contact = contacts[0];
+ });
+ }
+
+ next() {
+ let ix = 1 + this.contacts.indexOf(this.contact);
+ if (ix >= this.contacts.length) { ix = 0; }
+ this.contact = this.contacts[ix];
+ }
+
+ onSubmit() {
+ // POST-DEMO TODO: do something like save it
+ this.displayMessage('Saved ' + this.contact.name);
+ }
+
+ newContact() {
+ this.displayMessage('New contact');
+ this.contact = {id: 42, name: ''};
+ this.contacts.push(this.contact);
+ }
+
+ /** Display a message briefly, then remove it. */
+ displayMessage(msg: string) {
+ this.msg = msg;
+ setTimeout(() => this.msg = '', 1500);
+ }
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/contact/contact.component.css b/public/docs/_examples/ngmodule/ts/src/app/contact/contact.component.css
new file mode 100644
index 0000000000..45e8f6e76d
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/contact/contact.component.css
@@ -0,0 +1,29 @@
+/* #docregion */
+.ng-valid[required] {
+ border-left: 5px solid #42A948; /* green */
+}
+
+.ng-invalid {
+ border-left: 5px solid #a94442; /* red */
+}
+
+.alert {
+ padding: 15px;
+ margin: 8px 0;
+ border: 1px solid transparent;
+ border-radius: 4px;
+}
+.alert-danger {
+ color: #a94442;
+ background-color: #f2dede;
+ border-color: #ebccd1;
+}
+
+.msg {
+ color: blue;
+ background-color: whitesmoke;
+ border: 1px solid transparent;
+ border-radius: 4px;
+ margin-bottom: 20px;
+}
+
diff --git a/public/docs/_examples/ngmodule/ts/src/app/contact/contact.component.html b/public/docs/_examples/ngmodule/ts/src/app/contact/contact.component.html
new file mode 100644
index 0000000000..483480571e
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/contact/contact.component.html
@@ -0,0 +1,23 @@
+
+Contact of {{userName}}
+{{msg}}
+
+
+
diff --git a/public/docs/_examples/ngmodule/ts/src/app/contact/contact.component.ts b/public/docs/_examples/ngmodule/ts/src/app/contact/contact.component.ts
new file mode 100644
index 0000000000..d6dcbbc53f
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/contact/contact.component.ts
@@ -0,0 +1,54 @@
+// Exact copy except import UserService from core
+// #docregion
+import { Component, OnInit } from '@angular/core';
+
+import { Contact, ContactService } from './contact.service';
+import { UserService } from '../core/user.service';
+
+@Component({
+ selector: 'app-contact',
+ templateUrl: './contact.component.html',
+ styleUrls: [ './contact.component.css' ]
+})
+export class ContactComponent implements OnInit {
+ contact: Contact;
+ contacts: Contact[];
+
+ msg = 'Loading contacts ...';
+ userName = '';
+
+ constructor(private contactService: ContactService, userService: UserService) {
+ this.userName = userService.userName;
+ }
+
+ ngOnInit() {
+ this.contactService.getContacts().then(contacts => {
+ this.msg = '';
+ this.contacts = contacts;
+ this.contact = contacts[0];
+ });
+ }
+
+ next() {
+ let ix = 1 + this.contacts.indexOf(this.contact);
+ if (ix >= this.contacts.length) { ix = 0; }
+ this.contact = this.contacts[ix];
+ }
+
+ onSubmit() {
+ // POST-DEMO TODO: do something like save it
+ this.displayMessage('Saved ' + this.contact.name);
+ }
+
+ newContact() {
+ this.displayMessage('New contact');
+ this.contact = {id: 42, name: ''};
+ this.contacts.push(this.contact);
+ }
+
+ /** Display a message briefly, then remove it. */
+ displayMessage(msg: string) {
+ this.msg = msg;
+ setTimeout(() => this.msg = '', 1500);
+ }
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/contact/contact.module.2.ts b/public/docs/_examples/ngmodule/ts/src/app/contact/contact.module.2.ts
new file mode 100644
index 0000000000..f347bd3b51
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/contact/contact.module.2.ts
@@ -0,0 +1,30 @@
+// #docplaster
+// #docregion
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+
+import { AwesomePipe } from './awesome.pipe';
+
+import
+// #enddocregion
+ { ContactComponent } from './contact.component.3';
+/*
+// #docregion
+ { ContactComponent } from './contact.component';
+// #enddocregion
+*/
+// #docregion
+import { ContactService } from './contact.service';
+import { HighlightDirective } from './highlight.directive';
+
+// #docregion class
+@NgModule({
+ imports: [ CommonModule, FormsModule ],
+ declarations: [ ContactComponent, HighlightDirective, AwesomePipe ],
+ exports: [ ContactComponent ],
+ providers: [ ContactService ]
+})
+export class ContactModule { }
+// #enddocregion class
+// #enddocregion
diff --git a/public/docs/_examples/ngmodule/ts/src/app/contact/contact.module.3.ts b/public/docs/_examples/ngmodule/ts/src/app/contact/contact.module.3.ts
new file mode 100644
index 0000000000..ff70721b2f
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/contact/contact.module.3.ts
@@ -0,0 +1,22 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+
+import { AwesomePipe } from './awesome.pipe';
+
+import { ContactComponent } from './contact.component.3';
+import { ContactService } from './contact.service';
+import { HighlightDirective } from './highlight.directive';
+
+import { ContactRoutingModule } from './contact-routing.module.3';
+
+// #docregion class
+@NgModule({
+ imports: [ CommonModule, FormsModule, ContactRoutingModule ],
+ declarations: [ ContactComponent, HighlightDirective, AwesomePipe ],
+ providers: [ ContactService ]
+})
+export class ContactModule { }
+// #enddocregion class
+// #enddocregion
diff --git a/public/docs/_examples/ngmodule/ts/src/app/contact/contact.module.ts b/public/docs/_examples/ngmodule/ts/src/app/contact/contact.module.ts
new file mode 100644
index 0000000000..9456de7654
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/contact/contact.module.ts
@@ -0,0 +1,16 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { SharedModule } from '../shared/shared.module';
+
+import { ContactComponent } from './contact.component';
+import { ContactService } from './contact.service';
+import { ContactRoutingModule } from './contact-routing.module';
+
+// #docregion class
+@NgModule({
+ imports: [ SharedModule, ContactRoutingModule ],
+ declarations: [ ContactComponent ],
+ providers: [ ContactService ]
+})
+export class ContactModule { }
+// #enddocregion class
diff --git a/public/docs/_examples/ngmodule/ts/src/app/contact/contact.service.ts b/public/docs/_examples/ngmodule/ts/src/app/contact/contact.service.ts
new file mode 100644
index 0000000000..28b18bd84a
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/contact/contact.service.ts
@@ -0,0 +1,29 @@
+// #docregion
+import { Injectable } from '@angular/core';
+
+export class Contact {
+ constructor(public id: number, public name: string) { }
+}
+
+const CONTACTS: Contact[] = [
+ new Contact(21, 'Sam Spade'),
+ new Contact(22, 'Nick Danger'),
+ new Contact(23, 'Nancy Drew')
+];
+
+const FETCH_LATENCY = 500;
+
+@Injectable()
+export class ContactService {
+
+ getContacts() {
+ return new Promise(resolve => {
+ setTimeout(() => { resolve(CONTACTS); }, FETCH_LATENCY);
+ });
+ }
+
+ getContact(id: number | string) {
+ return this.getContacts()
+ .then(heroes => heroes.find(hero => hero.id === +id));
+ }
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/contact/highlight.directive.ts b/public/docs/_examples/ngmodule/ts/src/app/contact/highlight.directive.ts
new file mode 100644
index 0000000000..64338b1377
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/contact/highlight.directive.ts
@@ -0,0 +1,18 @@
+/* tslint:disable */
+// Same directive name and selector as
+// HighlightDirective in parent AppModule
+// It selects for both input boxes and 'highlight' attr
+// and it highlights in blue instead of gold
+
+// #docregion
+import { Directive, ElementRef } from '@angular/core';
+
+@Directive({ selector: '[highlight], input' })
+/** Highlight the attached element or an InputElement in blue */
+export class HighlightDirective {
+ constructor(el: ElementRef) {
+ el.nativeElement.style.backgroundColor = 'powderblue';
+ console.log(
+ `* Contact highlight called for ${el.nativeElement.tagName}`);
+ }
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/core/core.module.ts b/public/docs/_examples/ngmodule/ts/src/app/core/core.module.ts
new file mode 100644
index 0000000000..27cb9a2193
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/core/core.module.ts
@@ -0,0 +1,48 @@
+/* tslint:disable:member-ordering no-unused-variable */
+// #docplaster
+// #docregion
+// #docregion v4
+import {
+ ModuleWithProviders, NgModule,
+ Optional, SkipSelf } from '@angular/core';
+
+import { CommonModule } from '@angular/common';
+
+import { TitleComponent } from './title.component';
+import { UserService } from './user.service';
+// #enddocregion
+import { UserServiceConfig } from './user.service';
+
+// #docregion v4
+@NgModule({
+ imports: [ CommonModule ],
+ declarations: [ TitleComponent ],
+ exports: [ TitleComponent ],
+ providers: [ UserService ]
+})
+export class CoreModule {
+// #enddocregion v4
+
+ // #docregion ctor
+ constructor (@Optional() @SkipSelf() parentModule: CoreModule) {
+ if (parentModule) {
+ throw new Error(
+ 'CoreModule is already loaded. Import it in the AppModule only');
+ }
+ }
+ // #enddocregion ctor
+
+ // #docregion for-root
+ static forRoot(config: UserServiceConfig): ModuleWithProviders {
+ return {
+ ngModule: CoreModule,
+ providers: [
+ {provide: UserServiceConfig, useValue: config }
+ ]
+ };
+ }
+ // #enddocregion for-root
+// #docregion v4
+}
+// #enddocregion v4
+// #enddocregion
diff --git a/public/docs/_examples/ngmodule/ts/src/app/core/title.component.html b/public/docs/_examples/ngmodule/ts/src/app/core/title.component.html
new file mode 100644
index 0000000000..8ebd08ae43
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/core/title.component.html
@@ -0,0 +1,6 @@
+
+{{title}} {{subtitle}}
+
+ Welcome, {{user}}
+
+
diff --git a/public/docs/_examples/ngmodule/ts/src/app/core/title.component.ts b/public/docs/_examples/ngmodule/ts/src/app/core/title.component.ts
new file mode 100644
index 0000000000..b52a57aa13
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/core/title.component.ts
@@ -0,0 +1,17 @@
+// Exact copy of app/title.component.ts except import UserService from shared
+import { Component, Input } from '@angular/core';
+import { UserService } from '../core/user.service';
+
+@Component({
+ selector: 'app-title',
+ templateUrl: './title.component.html',
+})
+export class TitleComponent {
+ @Input() subtitle = '';
+ title = 'Angular Modules';
+ user = '';
+
+ constructor(userService: UserService) {
+ this.user = userService.userName;
+ }
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/core/user.service.ts b/public/docs/_examples/ngmodule/ts/src/app/core/user.service.ts
new file mode 100644
index 0000000000..8fe839075e
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/core/user.service.ts
@@ -0,0 +1,32 @@
+// Crazy copy of the app/user.service
+// Proves that UserService is an app-wide singleton and only instantiated once
+// IFF shared.module follows the `forRoot` pattern
+//
+// If it didn't, a new instance of UserService would be created
+// after each lazy load and the userName would double up.
+
+import { Injectable, Optional } from '@angular/core';
+
+let nextId = 1;
+
+export class UserServiceConfig {
+ userName = 'Philip Marlowe';
+}
+
+@Injectable()
+export class UserService {
+ id = nextId++;
+ private _userName = 'Sherlock Holmes';
+
+ // #docregion ctor
+ constructor(@Optional() config: UserServiceConfig) {
+ if (config) { this._userName = config.userName; }
+ }
+ // #enddocregion ctor
+
+ get userName() {
+ // Demo: add a suffix if this service has been created more than once
+ const suffix = this.id > 1 ? ` times ${this.id}` : '';
+ return this._userName + suffix;
+ }
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/crisis/crisis-detail.component.ts b/public/docs/_examples/ngmodule/ts/src/app/crisis/crisis-detail.component.ts
new file mode 100644
index 0000000000..9749029d62
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/crisis/crisis-detail.component.ts
@@ -0,0 +1,19 @@
+import { Component, OnInit } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+
+@Component({
+ template: `
+
Crisis Detail
+ Crisis id: {{id}}
+
+ Crisis List
+ `
+})
+export class CrisisDetailComponent implements OnInit {
+ id: number;
+ constructor(private route: ActivatedRoute) { }
+
+ ngOnInit() {
+ this.id = parseInt(this.route.snapshot.params['id'], 10);
+ }
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/crisis/crisis-list.component.ts b/public/docs/_examples/ngmodule/ts/src/app/crisis/crisis-list.component.ts
new file mode 100644
index 0000000000..ae459cdf1b
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/crisis/crisis-list.component.ts
@@ -0,0 +1,22 @@
+import { Component, OnInit } from '@angular/core';
+
+import { Crisis,
+ CrisisService } from './crisis.service';
+
+@Component({
+ template: `
+ Crisis List
+
+ `
+})
+export class CrisisListComponent implements OnInit {
+ crisises: Promise;
+
+ constructor(private crisisService: CrisisService) { }
+
+ ngOnInit() {
+ this.crisises = this.crisisService.getCrises();
+ }
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/crisis/crisis-routing.module.ts b/public/docs/_examples/ngmodule/ts/src/app/crisis/crisis-routing.module.ts
new file mode 100644
index 0000000000..c60efa8cb4
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/crisis/crisis-routing.module.ts
@@ -0,0 +1,18 @@
+import { NgModule } from '@angular/core';
+import { Routes,
+ RouterModule } from '@angular/router';
+
+import { CrisisListComponent } from './crisis-list.component';
+import { CrisisDetailComponent } from './crisis-detail.component';
+
+const routes: Routes = [
+ { path: '', redirectTo: 'list', pathMatch: 'full'},
+ { path: 'list', component: CrisisListComponent },
+ { path: ':id', component: CrisisDetailComponent }
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule]
+})
+export class CrisisRoutingModule {}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/crisis/crisis.module.ts b/public/docs/_examples/ngmodule/ts/src/app/crisis/crisis.module.ts
new file mode 100644
index 0000000000..f557bd6423
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/crisis/crisis.module.ts
@@ -0,0 +1,14 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { CrisisListComponent } from './crisis-list.component';
+import { CrisisDetailComponent } from './crisis-detail.component';
+import { CrisisService } from './crisis.service';
+import { CrisisRoutingModule } from './crisis-routing.module';
+
+@NgModule({
+ imports: [ CommonModule, CrisisRoutingModule ],
+ declarations: [ CrisisDetailComponent, CrisisListComponent ],
+ providers: [ CrisisService ]
+})
+export class CrisisModule {}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/crisis/crisis.service.ts b/public/docs/_examples/ngmodule/ts/src/app/crisis/crisis.service.ts
new file mode 100644
index 0000000000..419ee19b36
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/crisis/crisis.service.ts
@@ -0,0 +1,30 @@
+import { Injectable } from '@angular/core';
+
+export class Crisis {
+ constructor(public id: number, public name: string) { }
+}
+
+const CRISES: Crisis[] = [
+ new Crisis(1, 'Dragon Burning Cities'),
+ new Crisis(2, 'Sky Rains Great White Sharks'),
+ new Crisis(3, 'Giant Asteroid Heading For Earth'),
+ new Crisis(4, 'Procrastinators Meeting Delayed Again'),
+];
+
+const FETCH_LATENCY = 500;
+
+@Injectable()
+export class CrisisService {
+
+ getCrises() {
+ return new Promise(resolve => {
+ setTimeout(() => { resolve(CRISES); }, FETCH_LATENCY);
+ });
+ }
+
+ getCrisis(id: number | string) {
+ return this.getCrises()
+ .then(heroes => heroes.find(hero => hero.id === +id));
+ }
+
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/hero/hero-detail.component.ts b/public/docs/_examples/ngmodule/ts/src/app/hero/hero-detail.component.ts
new file mode 100644
index 0000000000..1478ad350c
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/hero/hero-detail.component.ts
@@ -0,0 +1,31 @@
+import { Component, OnInit } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+
+import { Hero,
+ HeroService } from './hero.service';
+
+@Component({
+ template: `
+ Hero Detail
+
+
Id: {{hero.id}}
+
Name:
+
+
+
+
+ Hero List
+ `
+})
+export class HeroDetailComponent implements OnInit {
+ hero: Hero;
+
+ constructor(
+ private route: ActivatedRoute,
+ private heroService: HeroService) { }
+
+ ngOnInit() {
+ let id = parseInt(this.route.snapshot.params['id'], 10);
+ this.heroService.getHero(id).then(hero => this.hero = hero);
+ }
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/hero/hero-list.component.ts b/public/docs/_examples/ngmodule/ts/src/app/hero/hero-list.component.ts
new file mode 100644
index 0000000000..5a4e9ef0c4
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/hero/hero-list.component.ts
@@ -0,0 +1,21 @@
+import { Component, OnInit } from '@angular/core';
+
+import { Hero,
+ HeroService } from './hero.service';
+
+@Component({
+ template: `
+ Hero List
+
+ `
+})
+export class HeroListComponent implements OnInit {
+ heroes: Promise;
+ constructor(private heroService: HeroService) { }
+
+ ngOnInit() {
+ this.heroes = this.heroService.getHeroes();
+ }
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/hero/hero-routing.module.3.ts b/public/docs/_examples/ngmodule/ts/src/app/hero/hero-routing.module.3.ts
new file mode 100644
index 0000000000..588ffd94be
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/hero/hero-routing.module.3.ts
@@ -0,0 +1,23 @@
+import { NgModule } from '@angular/core';
+import { Routes,
+ RouterModule } from '@angular/router';
+
+import { HeroComponent } from './hero.component.3';
+import { HeroListComponent } from './hero-list.component';
+import { HeroDetailComponent } from './hero-detail.component';
+
+const routes: Routes = [
+ { path: '',
+ component: HeroComponent,
+ children: [
+ { path: '', component: HeroListComponent },
+ { path: ':id', component: HeroDetailComponent }
+ ]
+ }
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule]
+})
+export class HeroRoutingModule {}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/hero/hero-routing.module.ts b/public/docs/_examples/ngmodule/ts/src/app/hero/hero-routing.module.ts
new file mode 100644
index 0000000000..d97aab3beb
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/hero/hero-routing.module.ts
@@ -0,0 +1,23 @@
+import { NgModule } from '@angular/core';
+import { Routes,
+ RouterModule } from '@angular/router';
+
+import { HeroComponent } from './hero.component';
+import { HeroListComponent } from './hero-list.component';
+import { HeroDetailComponent } from './hero-detail.component';
+
+const routes: Routes = [
+ { path: '',
+ component: HeroComponent,
+ children: [
+ { path: '', component: HeroListComponent },
+ { path: ':id', component: HeroDetailComponent }
+ ]
+ }
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule]
+})
+export class HeroRoutingModule {}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/hero/hero.component.3.ts b/public/docs/_examples/ngmodule/ts/src/app/hero/hero.component.3.ts
new file mode 100644
index 0000000000..d52bc253df
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/hero/hero.component.3.ts
@@ -0,0 +1,18 @@
+import { Component } from '@angular/core';
+
+import { HeroService } from './hero.service';
+import { UserService } from '../user.service';
+
+@Component({
+ template: `
+ Heroes of {{userName}}
+
+ `,
+ providers: [ HeroService ]
+})
+export class HeroComponent {
+ userName = '';
+ constructor(userService: UserService) {
+ this.userName = userService.userName;
+ }
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/hero/hero.component.ts b/public/docs/_examples/ngmodule/ts/src/app/hero/hero.component.ts
new file mode 100644
index 0000000000..86338fb0ae
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/hero/hero.component.ts
@@ -0,0 +1,19 @@
+// Exact copy except import UserService from core
+import { Component } from '@angular/core';
+
+import { HeroService } from './hero.service';
+import { UserService } from '../core/user.service';
+
+@Component({
+ template: `
+ Heroes of {{userName}}
+
+ `,
+ providers: [ HeroService ]
+})
+export class HeroComponent {
+ userName = '';
+ constructor(userService: UserService) {
+ this.userName = userService.userName;
+ }
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/hero/hero.module.3.ts b/public/docs/_examples/ngmodule/ts/src/app/hero/hero.module.3.ts
new file mode 100644
index 0000000000..c00f4eedd5
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/hero/hero.module.3.ts
@@ -0,0 +1,20 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+
+import { HeroComponent } from './hero.component.3';
+import { HeroDetailComponent } from './hero-detail.component';
+import { HeroListComponent } from './hero-list.component';
+import { HighlightDirective } from './highlight.directive';
+import { HeroRoutingModule } from './hero-routing.module.3';
+
+// #docregion class
+@NgModule({
+ imports: [ CommonModule, FormsModule, HeroRoutingModule ],
+ declarations: [
+ HeroComponent, HeroDetailComponent, HeroListComponent,
+ HighlightDirective
+ ]
+})
+export class HeroModule { }
+// #enddocregion class
diff --git a/public/docs/_examples/ngmodule/ts/src/app/hero/hero.module.ts b/public/docs/_examples/ngmodule/ts/src/app/hero/hero.module.ts
new file mode 100644
index 0000000000..98d7b76b00
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/hero/hero.module.ts
@@ -0,0 +1,16 @@
+import { NgModule } from '@angular/core';
+
+import { SharedModule } from '../shared/shared.module';
+
+import { HeroComponent } from './hero.component';
+import { HeroDetailComponent } from './hero-detail.component';
+import { HeroListComponent } from './hero-list.component';
+import { HeroRoutingModule } from './hero-routing.module';
+
+@NgModule({
+ imports: [ SharedModule, HeroRoutingModule ],
+ declarations: [
+ HeroComponent, HeroDetailComponent, HeroListComponent,
+ ]
+})
+export class HeroModule { }
diff --git a/public/docs/_examples/ngmodule/ts/src/app/hero/hero.service.ts b/public/docs/_examples/ngmodule/ts/src/app/hero/hero.service.ts
new file mode 100644
index 0000000000..bb7ff5fa5c
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/hero/hero.service.ts
@@ -0,0 +1,32 @@
+import { Injectable } from '@angular/core';
+
+export class Hero {
+ constructor(public id: number, public name: string) { }
+}
+
+const HEROES: Hero[] = [
+ new Hero(11, 'Mr. Nice'),
+ new Hero(12, 'Narco'),
+ new Hero(13, 'Bombasto'),
+ new Hero(14, 'Celeritas'),
+ new Hero(15, 'Magneta'),
+ new Hero(16, 'RubberMan')
+];
+
+const FETCH_LATENCY = 500;
+
+@Injectable()
+export class HeroService {
+
+ getHeroes() {
+ return new Promise(resolve => {
+ setTimeout(() => { resolve(HEROES); }, FETCH_LATENCY);
+ });
+ }
+
+ getHero(id: number | string) {
+ return this.getHeroes()
+ .then(heroes => heroes.find(hero => hero.id === +id));
+ }
+
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/hero/highlight.directive.ts b/public/docs/_examples/ngmodule/ts/src/app/hero/highlight.directive.ts
new file mode 100644
index 0000000000..d7e39afd05
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/hero/highlight.directive.ts
@@ -0,0 +1,14 @@
+// #docregion
+import { Directive, ElementRef } from '@angular/core';
+
+// Same directive name and selector as
+// HighlightDirective in parent AppRootModule
+// It selects for both input boxes and 'highlight' attr
+// and it highlights in beige instead of yellow
+@Directive({ selector: '[highlight]' })
+export class HighlightDirective {
+ constructor(el: ElementRef) {
+ el.nativeElement.style.backgroundColor = 'beige';
+ console.log(`* Hero highlight called for ${el.nativeElement.tagName}`);
+ }
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/highlight.directive.ts b/public/docs/_examples/ngmodule/ts/src/app/highlight.directive.ts
new file mode 100644
index 0000000000..df67a3ae89
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/highlight.directive.ts
@@ -0,0 +1,12 @@
+// #docregion
+import { Directive, ElementRef } from '@angular/core';
+
+@Directive({ selector: '[highlight]' })
+/** Highlight the attached element in gold */
+export class HighlightDirective {
+ constructor(el: ElementRef) {
+ el.nativeElement.style.backgroundColor = 'gold';
+ console.log(
+ `* AppRoot highlight called for ${el.nativeElement.tagName}`);
+ }
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/shared/awesome.pipe.ts b/public/docs/_examples/ngmodule/ts/src/app/shared/awesome.pipe.ts
new file mode 100644
index 0000000000..a1a0001d24
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/shared/awesome.pipe.ts
@@ -0,0 +1,10 @@
+// Exact copy of contact.awesome.pipe
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({ name: 'awesome' })
+/** Precede the input string with the word "Awesome " */
+export class AwesomePipe implements PipeTransform {
+ transform(phrase: string) {
+ return phrase ? 'Awesome ' + phrase : '';
+ }
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/shared/highlight.directive.ts b/public/docs/_examples/ngmodule/ts/src/app/shared/highlight.directive.ts
new file mode 100644
index 0000000000..63fbd4e488
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/shared/highlight.directive.ts
@@ -0,0 +1,13 @@
+/* tslint:disable */
+// Exact copy of contact/highlight.directive except for color and message
+import { Directive, ElementRef } from '@angular/core';
+
+@Directive({ selector: '[highlight], input' })
+/** Highlight the attached element or an InputElement in gray */
+export class HighlightDirective {
+ constructor(el: ElementRef) {
+ el.nativeElement.style.backgroundColor = 'lightgray';
+ console.log(
+ `* Shared highlight called for ${el.nativeElement.tagName}`);
+ }
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/app/shared/shared.module.ts b/public/docs/_examples/ngmodule/ts/src/app/shared/shared.module.ts
new file mode 100644
index 0000000000..2da7d7b2a5
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/shared/shared.module.ts
@@ -0,0 +1,18 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+
+import { AwesomePipe } from './awesome.pipe';
+import { HighlightDirective } from './highlight.directive';
+
+// #docregion module
+@NgModule({
+ imports: [ CommonModule ],
+ declarations: [ AwesomePipe, HighlightDirective ],
+ exports: [ AwesomePipe, HighlightDirective,
+ CommonModule, FormsModule ]
+})
+export class SharedModule { }
+// #enddocregion module
+// #enddocregion
diff --git a/public/docs/_examples/ngmodule/ts/src/app/title.component.html b/public/docs/_examples/ngmodule/ts/src/app/title.component.html
new file mode 100644
index 0000000000..3db364cd4b
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/title.component.html
@@ -0,0 +1,10 @@
+
+
+{{title}} {{subtitle}}
+
+
+
+ Welcome, {{user}}
+
+
+
diff --git a/public/docs/_examples/ngmodule/ts/src/app/title.component.ts b/public/docs/_examples/ngmodule/ts/src/app/title.component.ts
new file mode 100644
index 0000000000..9a2ef1c4b8
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/title.component.ts
@@ -0,0 +1,24 @@
+// #docplaster
+// #docregion
+// #docregion v1
+import { Component, Input } from '@angular/core';
+// #enddocregion v1
+import { UserService } from './user.service';
+// #docregion v1
+
+@Component({
+ selector: 'app-title',
+ templateUrl: './title.component.html',
+})
+export class TitleComponent {
+ @Input() subtitle = '';
+ title = 'Angular Modules';
+// #enddocregion v1
+ user = '';
+
+ constructor(userService: UserService) {
+ this.user = userService.userName;
+ }
+// #docregion v1
+}
+// #enddocregion v1
diff --git a/public/docs/_examples/ngmodule/ts/src/app/user.service.ts b/public/docs/_examples/ngmodule/ts/src/app/user.service.ts
new file mode 100644
index 0000000000..7d996b26fa
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/app/user.service.ts
@@ -0,0 +1,8 @@
+// #docregion
+import { Injectable } from '@angular/core';
+
+@Injectable()
+/** Dummy version of an authenticated user service */
+export class UserService {
+ userName = 'Sherlock Holmes';
+}
diff --git a/public/docs/_examples/ngmodule/ts/src/index.0.html b/public/docs/_examples/ngmodule/ts/src/index.0.html
new file mode 100644
index 0000000000..2281b9fecb
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/index.0.html
@@ -0,0 +1,24 @@
+
+
+
+
+ NgModule Minimal
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
diff --git a/public/docs/_examples/ngmodule/ts/src/index.1.html b/public/docs/_examples/ngmodule/ts/src/index.1.html
new file mode 100644
index 0000000000..65f7991a26
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/index.1.html
@@ -0,0 +1,24 @@
+
+
+
+
+ NgModule - Contact
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
diff --git a/public/docs/_examples/ngmodule/ts/src/index.1b.html b/public/docs/_examples/ngmodule/ts/src/index.1b.html
new file mode 100644
index 0000000000..b4a89d6549
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/index.1b.html
@@ -0,0 +1,24 @@
+
+
+
+
+ NgModule - Contact
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
diff --git a/public/docs/_examples/ngmodule/ts/src/index.2.html b/public/docs/_examples/ngmodule/ts/src/index.2.html
new file mode 100644
index 0000000000..72c545f1f3
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/index.2.html
@@ -0,0 +1,24 @@
+
+
+
+
+ NgModule - Contact
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
diff --git a/public/docs/_examples/ngmodule/ts/src/index.3.html b/public/docs/_examples/ngmodule/ts/src/index.3.html
new file mode 100644
index 0000000000..ec55dd984e
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/index.3.html
@@ -0,0 +1,24 @@
+
+
+
+
+ NgModule - Contact
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
diff --git a/public/docs/_examples/ngmodule/ts/src/index.html b/public/docs/_examples/ngmodule/ts/src/index.html
new file mode 100644
index 0000000000..9fc50c02a5
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/index.html
@@ -0,0 +1,25 @@
+
+
+
+
+ NgModule Deluxe
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
diff --git a/public/docs/_examples/ngmodule/ts/src/main-static.ts b/public/docs/_examples/ngmodule/ts/src/main-static.ts
new file mode 100644
index 0000000000..a1bcf466d2
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/main-static.ts
@@ -0,0 +1,13 @@
+// #docplaster
+/*
+// #docregion
+// The browser platform without a compiler
+import { platformBrowser } from '@angular/platform-browser';
+
+// The app module factory produced by the static offline compiler
+import { AppModuleNgFactory } from './app/app.module.ngfactory';
+
+// Launch with the app module factory.
+platformBrowser().bootstrapModuleFactory(AppModuleNgFactory);
+// #enddocregion
+*/
diff --git a/public/docs/_examples/ngmodule/ts/src/main.0.ts b/public/docs/_examples/ngmodule/ts/src/main.0.ts
new file mode 100644
index 0000000000..6d1d712f07
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/main.0.ts
@@ -0,0 +1,4 @@
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module.0';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/ngmodule/ts/src/main.1.ts b/public/docs/_examples/ngmodule/ts/src/main.1.ts
new file mode 100644
index 0000000000..48129f4cc9
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/main.1.ts
@@ -0,0 +1,4 @@
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module.1';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/ngmodule/ts/src/main.1b.ts b/public/docs/_examples/ngmodule/ts/src/main.1b.ts
new file mode 100644
index 0000000000..7a7bfae22f
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/main.1b.ts
@@ -0,0 +1,4 @@
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module.1b';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/ngmodule/ts/src/main.2.ts b/public/docs/_examples/ngmodule/ts/src/main.2.ts
new file mode 100644
index 0000000000..c535e2e775
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/main.2.ts
@@ -0,0 +1,4 @@
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module.2';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/ngmodule/ts/src/main.3.ts b/public/docs/_examples/ngmodule/ts/src/main.3.ts
new file mode 100644
index 0000000000..72f21dd142
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/main.3.ts
@@ -0,0 +1,4 @@
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module.3';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/ngmodule/ts/src/main.ts b/public/docs/_examples/ngmodule/ts/src/main.ts
new file mode 100644
index 0000000000..c8424d8c4c
--- /dev/null
+++ b/public/docs/_examples/ngmodule/ts/src/main.ts
@@ -0,0 +1,9 @@
+// #docregion
+// The browser platform with a compiler
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+// The app module
+import { AppModule } from './app/app.module';
+
+// Compile and launch the module
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/package.json b/public/docs/_examples/package.json
index 6bdf07a74e..41dc5e5b56 100644
--- a/public/docs/_examples/package.json
+++ b/public/docs/_examples/package.json
@@ -1,50 +1,89 @@
{
- "name": "angular2-examples-master",
+ "name": "angular-examples-master",
"version": "1.0.0",
- "description": "Master package.json, the superset of all dependencies for all of the _example package.json files.",
- "main": "index.js",
+ "private": true,
+ "description": "Master package.json, the superset of all dependencies for all of the _example package.json files. See _boilerplate/package.json for example npm scripts.",
"scripts": {
- "start": "concurrently \"npm run tsc:w\" \"npm run lite\" ",
- "tsc": "tsc",
- "tsc:w": "tsc -w",
- "lite": "lite-server",
- "live": "live-server",
- "test": "karma start karma.conf.js",
- "build-and-test": "npm run tsc && npm run test",
- "http-server": "tsc && http-server",
- "typings": "typings",
- "postinstall": "typings install"
+ "http-server": "http-server",
+ "protractor": "protractor",
+ "webdriver:update": "webdriver-manager update --standalone false --gecko false"
},
"keywords": [],
"author": "",
- "license": "ISC",
+ "license": "MIT",
"dependencies": {
- "angular2": "2.0.0-beta.8",
- "systemjs": "0.19.23",
- "es6-promise": "^3.0.2",
- "es6-shim": "^0.33.3",
- "reflect-metadata": "0.1.2",
- "rxjs": "5.0.0-beta.2",
- "zone.js": "0.5.15",
-
- "a2-in-memory-web-api": "^0.1.8",
- "bootstrap": "^3.3.6"
-
+ "@angular/animations": "~4.0.0",
+ "@angular/common": "~4.0.0",
+ "@angular/compiler": "~4.0.0",
+ "@angular/compiler-cli": "~4.0.0",
+ "@angular/core": "~4.0.0",
+ "@angular/forms": "~4.0.0",
+ "@angular/http": "~4.0.0",
+ "@angular/platform-browser": "~4.0.0",
+ "@angular/platform-browser-dynamic": "~4.0.0",
+ "@angular/platform-server": "~4.0.0",
+ "@angular/router": "~4.0.0",
+ "@angular/tsc-wrapped": "~4.0.0",
+ "@angular/upgrade": "~4.0.0",
+ "angular-in-memory-web-api": "~0.3.1",
+ "core-js": "^2.4.1",
+ "rxjs": "5.0.1",
+ "systemjs": "0.19.39",
+ "zone.js": "^0.8.4"
},
"devDependencies": {
- "concurrently": "^2.0.0",
+ "@angular/cli": "^1.0.0",
+ "@types/angular": "^1.5.16",
+ "@types/angular-animate": "^1.5.5",
+ "@types/angular-cookies": "^1.4.2",
+ "@types/angular-mocks": "^1.5.5",
+ "@types/angular-resource": "^1.5.6",
+ "@types/angular-route": "^1.3.2",
+ "@types/angular-sanitize": "^1.3.3",
+ "@types/jasmine": "2.5.36",
+ "@types/node": "^6.0.45",
+ "angular2-template-loader": "^0.6.0",
+ "awesome-typescript-loader": "^3.0.4",
+ "babel-cli": "^6.16.0",
+ "babel-preset-angular2": "^0.0.2",
+ "babel-preset-es2015": "^6.16.0",
+ "canonical-path": "0.0.2",
+ "concurrently": "^3.0.0",
+ "css-loader": "^0.26.1",
+ "extract-text-webpack-plugin": "2.0.0-beta.5",
+ "file-loader": "^0.9.0",
+ "html-loader": "^0.4.3",
+ "html-webpack-plugin": "^2.16.1",
"http-server": "^0.9.0",
+ "jasmine": "~2.4.1",
"jasmine-core": "~2.4.1",
- "karma": "^0.13.21",
- "karma-chrome-launcher": "^0.2.2",
- "karma-cli": "^0.1.2",
- "karma-jasmine": "^0.3.7",
- "lite-server": "^2.1.0",
- "live-server": "^0.9.2",
- "protractor": "^3.1.1",
- "rimraf": "^2.5.2",
- "typescript": "^1.8.7",
- "typings": "0.6.9"
+ "karma": "^1.3.0",
+ "karma-chrome-launcher": "^2.0.0",
+ "karma-cli": "^1.0.1",
+ "karma-jasmine": "^1.0.2",
+ "karma-jasmine-html-reporter": "^0.2.2",
+ "karma-phantomjs-launcher": "^1.0.2",
+ "karma-sourcemap-loader": "^0.3.7",
+ "karma-webpack": "^2.0.1",
+ "lite-server": "^2.2.2",
+ "lodash": "^4.16.2",
+ "null-loader": "^0.1.1",
+ "phantomjs-prebuilt": "^2.1.7",
+ "protractor": "~4.0.14",
+ "raw-loader": "^0.5.1",
+ "rimraf": "^2.5.4",
+ "rollup": "^0.41.6",
+ "rollup-plugin-commonjs": "^8.0.2",
+ "rollup-plugin-node-resolve": "2.0.0",
+ "rollup-plugin-uglify": "^1.0.1",
+ "source-map-explorer": "^1.3.2",
+ "style-loader": "^0.13.1",
+ "ts-node": "^1.3.0",
+ "tslint": "^3.15.1",
+ "typescript": "~2.2.0",
+ "webpack": "2.2.1",
+ "webpack-dev-server": "2.4.1",
+ "webpack-merge": "^3.0.0"
},
- "repository": { }
+ "repository": {}
}
diff --git a/public/docs/_examples/pipes/dart/lib/app_component.dart b/public/docs/_examples/pipes/dart/lib/app_component.dart
deleted file mode 100644
index 1edd92c0f4..0000000000
--- a/public/docs/_examples/pipes/dart/lib/app_component.dart
+++ /dev/null
@@ -1,21 +0,0 @@
-import 'package:angular2/angular2.dart';
-
-import 'hero_async_message_component.dart';
-import 'hero_birthday2_component.dart';
-import 'hero_list_component.dart';
-import 'power_booster.dart';
-import 'power_boost_calculator.dart';
-
-@Component(
- selector: 'my-app',
- templateUrl: 'app_component.html',
- directives: const [
- HeroAsyncMessageComponent,
- HeroBirthday,
- HeroListComponent,
- PowerBooster,
- PowerBoostCalculator
- ])
-class AppComponent {
- DateTime birthday = new DateTime(1988, 4, 15); // April 15, 1988
-}
diff --git a/public/docs/_examples/pipes/dart/lib/app_component.html b/public/docs/_examples/pipes/dart/lib/app_component.html
deleted file mode 100644
index feed0f1908..0000000000
--- a/public/docs/_examples/pipes/dart/lib/app_component.html
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
-The hero's birthday is {{ birthday | date }}
-
-The hero's birthday is {{ birthday | date:"MM/dd/yy" }}
-
-
-Hero Birthday v.2
-loading...
-
-
-
-
- The chained hero's birthday is
- {{ birthday | date | uppercase}}
-
-
-
- The chained hero's birthday is
- {{ birthday | date:'fullDate' | uppercase}}
-
-
- The chained hero's birthday is
- {{ ( birthday | date:'fullDate' ) | uppercase}}
-
-
-loading...
-
-
-loading ..
diff --git a/public/docs/_examples/pipes/dart/lib/exponential_strength_pipe.dart b/public/docs/_examples/pipes/dart/lib/exponential_strength_pipe.dart
deleted file mode 100644
index b84297950c..0000000000
--- a/public/docs/_examples/pipes/dart/lib/exponential_strength_pipe.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-import 'dart:math' as math;
-
-import 'package:angular2/angular2.dart';
-
-/*
-* Raise the value exponentially
-* Takes a value that defaults to 0 and an exponent argument that defaults to 1.
-* Checks for value to be a string or number.
-* Usage:
-* value | exponentialStrength:exponent
-* Example:
-* {{ 2 | exponentialStrength:10}}
-* formats to: 1024
-*/
-
-@Pipe(name: 'exponentialStrength')
-@Injectable()
-class ExponentialStrengthPipe extends PipeTransform {
- transform(dynamic value, [List args]) {
- var v = int.parse(value.toString(), onError: (source) => 0);
- var p = args.isEmpty
- ? 1
- : int.parse(args.first.toString(), onError: (source) => 1);
- return math.pow(v, p);
- }
-}
diff --git a/public/docs/_examples/pipes/dart/lib/fetch_json_pipe.dart b/public/docs/_examples/pipes/dart/lib/fetch_json_pipe.dart
deleted file mode 100644
index e07f58ff53..0000000000
--- a/public/docs/_examples/pipes/dart/lib/fetch_json_pipe.dart
+++ /dev/null
@@ -1,20 +0,0 @@
-import 'dart:html';
-import 'dart:async';
-import 'dart:convert';
-
-import 'package:angular2/angular2.dart';
-
-@Pipe(name: 'fetch', pure: false)
-@Injectable()
-class FetchJsonPipe extends PipeTransform {
- dynamic _fetchedValue;
- Future _fetchPromise;
- transform(dynamic value, [List args]) {
- if (_fetchPromise == null) {
- _fetchPromise = new Future(() async {
- _fetchedValue = JSON.decode(await HttpRequest.getString(value));
- });
- }
- return _fetchedValue;
- }
-}
diff --git a/public/docs/_examples/pipes/dart/lib/hero_async_message_component.dart b/public/docs/_examples/pipes/dart/lib/hero_async_message_component.dart
deleted file mode 100644
index 52d1851a86..0000000000
--- a/public/docs/_examples/pipes/dart/lib/hero_async_message_component.dart
+++ /dev/null
@@ -1,12 +0,0 @@
-import 'dart:async';
-
-import 'package:angular2/angular2.dart';
-
-@Component(
- selector: 'hero-message', template: 'Message: {{delayedMessage | async}}')
-class HeroAsyncMessageComponent {
- Future delayedMessage =
- new Future.delayed(new Duration(milliseconds: 500), () {
- return 'You are my Hero!';
- });
-}
diff --git a/public/docs/_examples/pipes/dart/lib/hero_birthday1_component.dart b/public/docs/_examples/pipes/dart/lib/hero_birthday1_component.dart
deleted file mode 100644
index 4b8f3a33f2..0000000000
--- a/public/docs/_examples/pipes/dart/lib/hero_birthday1_component.dart
+++ /dev/null
@@ -1,10 +0,0 @@
-import 'package:angular2/angular2.dart';
-
-@Component(
- selector: 'hero-birthday',
- template: '''
- The hero's birthday is {{ birthday | date }}
- ''')
-class HeroBirthday {
- DateTime birthday = new DateTime(1988, 4, 15); // April 15, 1988
-}
diff --git a/public/docs/_examples/pipes/dart/lib/hero_birthday2_component.dart b/public/docs/_examples/pipes/dart/lib/hero_birthday2_component.dart
deleted file mode 100644
index 032888080e..0000000000
--- a/public/docs/_examples/pipes/dart/lib/hero_birthday2_component.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-import 'package:angular2/angular2.dart';
-
-@Component(
- selector: 'hero-birthday',
- template: '''
- The hero's birthday is {{ birthday | date:format }}
- Toggle Format
- ''')
-class HeroBirthday {
- DateTime birthday = new DateTime(1988, 4, 15); // April 15, 1988
-
- bool toggle = true;
-
- get format => toggle ? 'shortDate' : 'fullDate';
-
- void toggleFormat() {
- toggle = !toggle;
- }
-}
diff --git a/public/docs/_examples/pipes/dart/lib/hero_list_component.dart b/public/docs/_examples/pipes/dart/lib/hero_list_component.dart
deleted file mode 100644
index 50ae1a5bf1..0000000000
--- a/public/docs/_examples/pipes/dart/lib/hero_list_component.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-import 'package:angular2/angular2.dart';
-
-import 'fetch_json_pipe.dart';
-
-@Component(
- selector: 'hero-list',
- template: '''
- Heroes from JSON File
-
-
- {{hero['name']}}
-
-
- Heroes as JSON:
- {{'heroes.json' | fetch | json}}
-
-''',
- pipes: const [FetchJsonPipe])
-class HeroListComponent {}
diff --git a/public/docs/_examples/pipes/dart/lib/power_boost_calculator.dart b/public/docs/_examples/pipes/dart/lib/power_boost_calculator.dart
deleted file mode 100644
index 1d7f9558cd..0000000000
--- a/public/docs/_examples/pipes/dart/lib/power_boost_calculator.dart
+++ /dev/null
@@ -1,21 +0,0 @@
-import 'package:angular2/angular2.dart';
-
-import 'exponential_strength_pipe.dart';
-
-@Component(
- selector: 'power-boost-calculator',
- template: '''
-Power Boost Calculator
-Normal power:
-Boost factor:
-
- Super Hero Power: {{power | exponentialStrength: factor}}
-
-''',
- pipes: const [ExponentialStrengthPipe],
- directives: const [COMMON_DIRECTIVES])
-class PowerBoostCalculator {
- // XXX: These should be ints, but that causes exceptions in checked mode.
- String power = '5';
- String factor = '1';
-}
diff --git a/public/docs/_examples/pipes/dart/lib/power_booster.dart b/public/docs/_examples/pipes/dart/lib/power_booster.dart
deleted file mode 100644
index 194abe1b0c..0000000000
--- a/public/docs/_examples/pipes/dart/lib/power_booster.dart
+++ /dev/null
@@ -1,13 +0,0 @@
-import 'package:angular2/angular2.dart';
-import 'exponential_strength_pipe.dart';
-
-@Component(
- selector: 'power-booster',
- template: '''
- Power Booster
-
- Super power boost: {{2 | exponentialStrength: 10}}
-
-''',
- pipes: const [ExponentialStrengthPipe])
-class PowerBooster {}
diff --git a/public/docs/_examples/pipes/dart/pubspec.yaml b/public/docs/_examples/pipes/dart/pubspec.yaml
deleted file mode 100644
index a0f3ba82ed..0000000000
--- a/public/docs/_examples/pipes/dart/pubspec.yaml
+++ /dev/null
@@ -1,16 +0,0 @@
-# #docregion
-name: pipe_examples
-description: Pipes Example
-version: 0.0.1
-environment:
- sdk: '>=1.13.0 <2.0.0'
-dependencies:
- angular2: 2.0.0-beta.8
- browser: ^0.10.0
- dart_to_js_script_rewriter: ^0.1.0
-transformers:
-- angular2:
- platform_directives: 'package:angular2/src/common/directives.dart#CORE_DIRECTIVES'
- platform_pipes: 'package:angular2/common.dart#COMMON_PIPES'
- entry_points: web/main.dart
-- dart_to_js_script_rewriter
diff --git a/public/docs/_examples/pipes/dart/web/heroes.json b/public/docs/_examples/pipes/dart/web/heroes.json
deleted file mode 100644
index 436b220d53..0000000000
--- a/public/docs/_examples/pipes/dart/web/heroes.json
+++ /dev/null
@@ -1,6 +0,0 @@
-[
- {"name": "Windstorm"},
- {"name": "Bombasto"},
- {"name": "Magneto"},
- {"name": "Tornado"}
-]
diff --git a/public/docs/_examples/pipes/dart/web/index.html b/public/docs/_examples/pipes/dart/web/index.html
deleted file mode 100644
index 483b9537ba..0000000000
--- a/public/docs/_examples/pipes/dart/web/index.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
- Pipes Example
-
-
-
-
-
-
- Hero Birthday v.1
- hero-birthday loading...
-
- my-app loading ...
-
-
-
diff --git a/public/docs/_examples/pipes/dart/web/main.dart b/public/docs/_examples/pipes/dart/web/main.dart
deleted file mode 100644
index 72e510805c..0000000000
--- a/public/docs/_examples/pipes/dart/web/main.dart
+++ /dev/null
@@ -1,8 +0,0 @@
-import 'package:angular2/bootstrap.dart';
-import 'package:pipe_examples/app_component.dart';
-import 'package:pipe_examples/hero_birthday1_component.dart';
-
-main() {
- bootstrap(AppComponent);
- bootstrap(HeroBirthday);
-}
diff --git a/public/docs/_examples/pipes/e2e-spec.js b/public/docs/_examples/pipes/e2e-spec.js
deleted file mode 100644
index a8637947d0..0000000000
--- a/public/docs/_examples/pipes/e2e-spec.js
+++ /dev/null
@@ -1,70 +0,0 @@
-describe('Pipes', function () {
-
- beforeAll(function () {
- browser.get('');
- });
-
- it('should open correctly', function () {
- expect(element.all(by.css('h4')).get(0).getText()).toEqual('Hero Birthday v.1');
- expect(element(by.css('body > hero-birthday p')).getText()).toEqual("The hero's birthday is Apr 15, 1988");
- });
-
- it('should show delayed message', function () {
- expect(element.all(by.css('hero-message')).get(0).getText()).toEqual('Message: You are my Hero!');
- });
-
- it('should show 4 heroes', function () {
- expect(element.all(by.css('hero-list div')).count()).toEqual(4);
- });
-
- it('should show 4 heroes in json', function () {
- expect(element(by.cssContainingText('hero-list p', 'Heroes as JSON')).getText()).toContain('Bombasto');
- });
-
- it('should show alternate birthday formats', function () {
- expect(element(by.cssContainingText('my-app > p', "The hero's birthday is Apr 15, 1988")).isDisplayed()).toBe(true);
- expect(element(by.cssContainingText('my-app > p', "The hero's birthday is 04/15/88")).isDisplayed()).toBe(true);
- });
-
- it('should be able to toggle birthday formats', function () {
- var birthDayEle = element(by.css('my-app > hero-birthday > p'));
- expect(birthDayEle.getText()).toEqual("The hero's birthday is 4/15/1988");
- var buttonEle = element(by.cssContainingText('my-app > hero-birthday > button', "Toggle Format"));
- expect(buttonEle.isDisplayed()).toBe(true);
- buttonEle.click().then(function() {
- expect(birthDayEle.getText()).toEqual("The hero's birthday is Friday, April 15, 1988");
- });
- });
-
- it('should be able to chain and compose pipes', function () {
- var chainedPipeEles = element.all(by.cssContainingText('my-app p', "The chained hero's"));
- expect(chainedPipeEles.count()).toBe(3, "should have 3 chained pipe examples");
- expect(chainedPipeEles.get(0).getText()).toContain('APR 15, 1988');
- expect(chainedPipeEles.get(1).getText()).toContain('FRIDAY, APRIL 15, 1988');
- expect(chainedPipeEles.get(2).getText()).toContain('FRIDAY, APRIL 15, 1988');
- });
-
- it('should be able to use ExponentialStrengthPipe pipe', function () {
- var ele = element(by.css('power-booster p'));
- expect(ele.getText()).toContain('Super power boost: 1024');
- });
-
- it('should be able to use the exponential calculator', function () {
- var eles = element.all(by.css('power-boost-calculator input'));
- var baseInputEle = eles.get(0);
- var factorInputEle = eles.get(1);
- var outputEle = element(by.css('power-boost-calculator p'));
- baseInputEle.clear().then(function() {
- return sendKeys(baseInputEle, "7");
- }).then(function() {
- return factorInputEle.clear();
- }).then(function() {
- return sendKeys(factorInputEle, "3");
- }).then(function() {
- expect(outputEle.getText()).toContain("343");
- });
- });
-
-
-
-});
diff --git a/public/docs/_examples/pipes/e2e-spec.ts b/public/docs/_examples/pipes/e2e-spec.ts
new file mode 100644
index 0000000000..00277e3657
--- /dev/null
+++ b/public/docs/_examples/pipes/e2e-spec.ts
@@ -0,0 +1,111 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by } from 'protractor';
+
+describe('Pipes', function () {
+
+ beforeAll(function () {
+ browser.get('');
+ });
+
+ it('should open correctly', function () {
+ expect(element.all(by.tagName('h1')).get(0).getText()).toEqual('Pipes');
+ expect(element(by.css('hero-birthday p')).getText()).toEqual(`The hero's birthday is Apr 15, 1988`);
+ });
+
+ it('should show 4 heroes', function () {
+ expect(element.all(by.css('hero-list div')).count()).toEqual(4);
+ });
+
+ it('should show a familiar hero in json', function () {
+ expect(element(by.cssContainingText('hero-list p', 'Heroes as JSON')).getText()).toContain('Bombasto');
+ });
+
+ it('should show alternate birthday formats', function () {
+ expect(element(by.cssContainingText('my-app > p', `The hero's birthday is Apr 15, 1988`)).isDisplayed()).toBe(true);
+ expect(element(by.cssContainingText('my-app > p', `The hero's birthday is 04/15/88`)).isDisplayed()).toBe(true);
+ });
+
+ it('should be able to toggle birthday formats', function () {
+ let birthDayEle = element(by.css('hero-birthday2 > p'));
+ expect(birthDayEle.getText()).toEqual(`The hero's birthday is 4/15/1988`);
+ let buttonEle = element(by.cssContainingText('hero-birthday2 > button', 'Toggle Format'));
+ expect(buttonEle.isDisplayed()).toBe(true);
+ buttonEle.click().then(function() {
+ expect(birthDayEle.getText()).toEqual(`The hero's birthday is Friday, April 15, 1988`);
+ });
+ });
+
+ it('should be able to chain and compose pipes', function () {
+ let chainedPipeEles = element.all(by.cssContainingText('my-app p', `The chained hero's`));
+ expect(chainedPipeEles.count()).toBe(3, 'should have 3 chained pipe examples');
+ expect(chainedPipeEles.get(0).getText()).toContain('APR 15, 1988');
+ expect(chainedPipeEles.get(1).getText()).toContain('FRIDAY, APRIL 15, 1988');
+ expect(chainedPipeEles.get(2).getText()).toContain('FRIDAY, APRIL 15, 1988');
+ });
+
+ it('should be able to use ExponentialStrengthPipe pipe', function () {
+ let ele = element(by.css('power-booster p'));
+ expect(ele.getText()).toContain('Super power boost: 1024');
+ });
+
+ it('should be able to use the exponential calculator', function () {
+ let eles = element.all(by.css('power-boost-calculator input'));
+ let baseInputEle = eles.get(0);
+ let factorInputEle = eles.get(1);
+ let outputEle = element(by.css('power-boost-calculator p'));
+ baseInputEle.clear().then(function() {
+ baseInputEle.sendKeys('7');
+ return factorInputEle.clear();
+ }).then(function() {
+ factorInputEle.sendKeys('3');
+ expect(outputEle.getText()).toContain('343');
+ });
+ });
+
+
+ it('should support flying heroes (pure) ', function () {
+ let nameEle = element(by.css('flying-heroes input[type="text"]'));
+ let canFlyCheckEle = element(by.css('flying-heroes #can-fly'));
+ let mutateCheckEle = element(by.css('flying-heroes #mutate'));
+ let resetEle = element(by.css('flying-heroes button'));
+ let flyingHeroesEle = element.all(by.css('flying-heroes #flyers div'));
+
+ expect(canFlyCheckEle.getAttribute('checked')).toEqual('true', 'should default to "can fly"');
+ expect(mutateCheckEle.getAttribute('checked')).toEqual('true', 'should default to mutating array');
+ expect(flyingHeroesEle.count()).toEqual(2, 'only two of the original heroes can fly');
+
+ nameEle.sendKeys('test1\n');
+ expect(flyingHeroesEle.count()).toEqual(2, 'no change while mutating array');
+ mutateCheckEle.click().then(function() {
+ nameEle.sendKeys('test2\n');
+ expect(flyingHeroesEle.count()).toEqual(4, 'not mutating; should see both adds');
+ expect(flyingHeroesEle.get(2).getText()).toContain('test1');
+ expect(flyingHeroesEle.get(3).getText()).toContain('test2');
+ return resetEle.click();
+ })
+ .then(function() {
+ expect(flyingHeroesEle.count()).toEqual(2, 'reset should restore orginal flying heroes');
+ });
+ });
+
+
+ it('should support flying heroes (impure) ', function () {
+ let nameEle = element(by.css('flying-heroes-impure input[type="text"]'));
+ let canFlyCheckEle = element(by.css('flying-heroes-impure #can-fly'));
+ let mutateCheckEle = element(by.css('flying-heroes-impure #mutate'));
+ let flyingHeroesEle = element.all(by.css('flying-heroes-impure #flyers div'));
+
+ expect(canFlyCheckEle.getAttribute('checked')).toEqual('true', 'should default to "can fly"');
+ expect(mutateCheckEle.getAttribute('checked')).toEqual('true', 'should default to mutating array');
+ expect(flyingHeroesEle.count()).toEqual(2, 'only two of the original heroes can fly');
+
+ nameEle.sendKeys('test1\n');
+ expect(flyingHeroesEle.count()).toEqual(3, 'new flying hero should show in mutating array');
+ });
+
+ it('should show an async hero message', function () {
+ expect(element.all(by.tagName('hero-message')).get(0).getText()).toContain('hero');
+ });
+
+});
diff --git a/public/docs/_examples/pipes/ts/.gitignore b/public/docs/_examples/pipes/ts/.gitignore
deleted file mode 100644
index 2cb7d2a2e9..0000000000
--- a/public/docs/_examples/pipes/ts/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-**/*.js
diff --git a/public/docs/_examples/pipes/ts/app/app.component.html b/public/docs/_examples/pipes/ts/app/app.component.html
deleted file mode 100644
index 7cbc969c84..0000000000
--- a/public/docs/_examples/pipes/ts/app/app.component.html
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
-
-
-
-
-
-
-
-The hero's birthday is {{ birthday | date }}
-
-
-
-The hero's birthday is {{ birthday | date:"MM/dd/yy" }}
-
-
-
-Hero Birthday v.2
-loading...
-
-
-
-
-
- The chained hero's birthday is
- {{ birthday | date | uppercase}}
-
-
-
-
-
- The chained hero's birthday is
- {{ birthday | date:'fullDate' | uppercase}}
-
-
-
-
- The chained hero's birthday is
- {{ ( birthday | date:'fullDate' ) | uppercase}}
-
-
-
-loading...
-
-
-loading ..
-
diff --git a/public/docs/_examples/pipes/ts/app/app.component.ts b/public/docs/_examples/pipes/ts/app/app.component.ts
deleted file mode 100644
index db6a0c7a81..0000000000
--- a/public/docs/_examples/pipes/ts/app/app.component.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-// #docregion
-import {Component} from 'angular2/core';
-import {HeroAsyncMessageComponent} from './hero-async-message.component';
-import {HeroBirthday} from './hero-birthday2.component';
-import {HeroListComponent} from './hero-list.component';
-import {PowerBooster} from './power-booster.component';
-import {PowerBoostCalculator} from './power-boost-calculator.component';
-
-@Component({
- selector: 'my-app',
- templateUrl: 'app/app.component.html',
- directives:[
- HeroAsyncMessageComponent,
- HeroBirthday,
- HeroListComponent,
- PowerBooster, PowerBoostCalculator
- ]
-})
-export class AppComponent {
- birthday = new Date(1988,3,15); // April 15, 1988
-}
diff --git a/public/docs/_examples/pipes/ts/app/exponential-strength.pipe.ts b/public/docs/_examples/pipes/ts/app/exponential-strength.pipe.ts
deleted file mode 100644
index 2907cd00dd..0000000000
--- a/public/docs/_examples/pipes/ts/app/exponential-strength.pipe.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-// #docregion
-import {Pipe, PipeTransform} from 'angular2/core';
-/*
- * Raise the value exponentially
- * Takes an exponent argument that defaults to 1.
- * Usage:
- * value | exponentialStrength:exponent
- * Example:
- * {{ 2 | exponentialStrength:10}}
- * formats to: 1024
-*/
-@Pipe({name: 'exponentialStrength'})
-export class ExponentialStrengthPipe implements PipeTransform {
-
- transform(value:number, args:string[]) : any {
- return Math.pow(value, parseInt(args[0] || '1', 10));
- }
-}
diff --git a/public/docs/_examples/pipes/ts/app/fetch-json.pipe.ts b/public/docs/_examples/pipes/ts/app/fetch-json.pipe.ts
deleted file mode 100644
index 9383ce0990..0000000000
--- a/public/docs/_examples/pipes/ts/app/fetch-json.pipe.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-///
-// #docregion
-import {Pipe, PipeTransform} from 'angular2/core';
-
-// #docregion pipe-metadata
-@Pipe({
- name: 'fetch',
- pure: false
-})
-// #enddocregion pipe-metadata
-export class FetchJsonPipe implements PipeTransform{
- private fetchedValue:any;
- private fetchPromise:Promise;
-
- transform(value:string, args:string[]):any {
- if (!this.fetchPromise) {
- this.fetchPromise = window.fetch(value)
- .then((result:any) => result.json())
- .then((json:any) => this.fetchedValue = json);
- }
-
- return this.fetchedValue;
- }
-}
\ No newline at end of file
diff --git a/public/docs/_examples/pipes/ts/app/hero-async-message.component.ts b/public/docs/_examples/pipes/ts/app/hero-async-message.component.ts
deleted file mode 100644
index 9303932d41..0000000000
--- a/public/docs/_examples/pipes/ts/app/hero-async-message.component.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-// #docregion
-import {Component} from 'angular2/core';
-
-// Initial view: "Message: "
-// After 500ms: Message: You are my Hero!"
-
-@Component({
- selector: 'hero-message',
- template: 'Message: {{delayedMessage | async}}',
-})
-export class HeroAsyncMessageComponent {
- delayedMessage:Promise = new Promise((resolve, reject) => {
- setTimeout(() => resolve('You are my Hero!'), 500);
- });
-}
diff --git a/public/docs/_examples/pipes/ts/app/hero-birthday1.component.ts b/public/docs/_examples/pipes/ts/app/hero-birthday1.component.ts
deleted file mode 100644
index e8ef259381..0000000000
--- a/public/docs/_examples/pipes/ts/app/hero-birthday1.component.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-// Version #1
-// #docregion
-import {Component} from 'angular2/core'
-
-@Component({
- selector: 'hero-birthday',
- // #docregion hero-birthday-template
- template: `The hero's birthday is {{ birthday | date }}
`
- // #enddocregion hero-birthday-template
-})
-export class HeroBirthday {
- birthday = new Date(1988,3,15); // April 15, 1988
-}
-// #enddocregion
\ No newline at end of file
diff --git a/public/docs/_examples/pipes/ts/app/hero-birthday2.component.ts b/public/docs/_examples/pipes/ts/app/hero-birthday2.component.ts
deleted file mode 100644
index e0b357c7f4..0000000000
--- a/public/docs/_examples/pipes/ts/app/hero-birthday2.component.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-// Version #2
-// #docregion
-import {Component} from 'angular2/core'
-
-@Component({
- selector: 'hero-birthday',
-// #docregion template
- template: `
- The hero's birthday is {{ birthday | date:format }}
- Toggle Format
- `
-// #enddocregion template
-})
-// #docregion class
-export class HeroBirthday {
- birthday = new Date(1988,3,15); // April 15, 1988
-
- toggle = true; // start with true == shortDate
-
- get format() { return this.toggle ? 'shortDate' : 'fullDate'}
-
- toggleFormat() { this.toggle = !this.toggle; }
-}
-// #enddocregion class
diff --git a/public/docs/_examples/pipes/ts/app/hero-list.component.ts b/public/docs/_examples/pipes/ts/app/hero-list.component.ts
deleted file mode 100644
index 169767eac1..0000000000
--- a/public/docs/_examples/pipes/ts/app/hero-list.component.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-// #docregion
-import {Component} from 'angular2/core';
-import {FetchJsonPipe} from './fetch-json.pipe';
-
-@Component({
- selector: 'hero-list',
- // #docregion template
- template: `
- Heroes from JSON File
-
-
- {{hero.name}}
-
-
- Heroes as JSON:
- {{'heroes.json' | fetch | json}}
-
- `,
- // #enddocregion template
- pipes: [FetchJsonPipe]
-})
-export class HeroListComponent {
- /* I've got nothing to do ;-) */
-}
diff --git a/public/docs/_examples/pipes/ts/app/main.ts b/public/docs/_examples/pipes/ts/app/main.ts
deleted file mode 100644
index 597ab3aa7c..0000000000
--- a/public/docs/_examples/pipes/ts/app/main.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import {bootstrap} from 'angular2/platform/browser';
-import {AppComponent} from './app.component';
-import {HeroBirthday} from './hero-birthday1.component';
-
-bootstrap(AppComponent);
-bootstrap(HeroBirthday); // v.1
\ No newline at end of file
diff --git a/public/docs/_examples/pipes/ts/app/power-boost-calculator.component.ts b/public/docs/_examples/pipes/ts/app/power-boost-calculator.component.ts
deleted file mode 100644
index 73151d5362..0000000000
--- a/public/docs/_examples/pipes/ts/app/power-boost-calculator.component.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-// #docregion
-import {Component} from 'angular2/core';
-import {ExponentialStrengthPipe} from './exponential-strength.pipe';
-
-@Component({
- selector: 'power-boost-calculator',
- template: `
- Power Boost Calculator
- Normal power:
- Boost factor:
-
- Super Hero Power: {{power | exponentialStrength: factor}}
-
- `,
- pipes: [ExponentialStrengthPipe]
-})
-export class PowerBoostCalculator {
- power = 5;
- factor = 1;
-}
diff --git a/public/docs/_examples/pipes/ts/app/power-booster.component.ts b/public/docs/_examples/pipes/ts/app/power-booster.component.ts
deleted file mode 100644
index 73d5c25ca0..0000000000
--- a/public/docs/_examples/pipes/ts/app/power-booster.component.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-// #docregion
-import {Component} from 'angular2/core';
-import {ExponentialStrengthPipe} from './exponential-strength.pipe';
-
-@Component({
- selector: 'power-booster',
- template: `
- Power Booster
-
- Super power boost: {{2 | exponentialStrength: 10}}
-
- `,
- pipes: [ExponentialStrengthPipe]
-})
-export class PowerBooster { }
diff --git a/public/docs/_examples/pipes/ts/app/window.extension.d.ts b/public/docs/_examples/pipes/ts/app/window.extension.d.ts
deleted file mode 100644
index 0a5a71bbf6..0000000000
--- a/public/docs/_examples/pipes/ts/app/window.extension.d.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-interface Window {
- fetch(url: string, options? : {}) : Promise
-}
diff --git a/public/docs/_examples/pipes/ts/heroes.json b/public/docs/_examples/pipes/ts/heroes.json
deleted file mode 100644
index 436b220d53..0000000000
--- a/public/docs/_examples/pipes/ts/heroes.json
+++ /dev/null
@@ -1,6 +0,0 @@
-[
- {"name": "Windstorm"},
- {"name": "Bombasto"},
- {"name": "Magneto"},
- {"name": "Tornado"}
-]
diff --git a/public/docs/_examples/pipes/ts/index.html b/public/docs/_examples/pipes/ts/index.html
deleted file mode 100644
index f11eba1c67..0000000000
--- a/public/docs/_examples/pipes/ts/index.html
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-
- Pipes
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Hero Birthday v.1
- hero-birthday loading...
-
- my-app loading ...
-
-
-
diff --git a/public/docs/_examples/pipes/ts/plnkr.json b/public/docs/_examples/pipes/ts/plnkr.json
index cc19097a4a..3c07266109 100644
--- a/public/docs/_examples/pipes/ts/plnkr.json
+++ b/public/docs/_examples/pipes/ts/plnkr.json
@@ -1,8 +1,8 @@
{
"description": "Pipes",
+ "basePath": "src/",
"files":[
"!**/*.d.ts",
- "!**/*.js",
- "!**/*.d.ts"],
+ "!**/*.js"],
"tags": ["pipe"]
-}
\ No newline at end of file
+}
diff --git a/public/docs/_examples/pipes/ts/src/app/app.component.html b/public/docs/_examples/pipes/ts/src/app/app.component.html
new file mode 100644
index 0000000000..a27d587fcd
--- /dev/null
+++ b/public/docs/_examples/pipes/ts/src/app/app.component.html
@@ -0,0 +1,83 @@
+
+Pipes
+Happy Birthday v1
+Birthday DatePipe
+Happy Birthday v2
+Birthday Pipe Chaining
+Power Booster custom pipe
+Power Boost Calculator custom pipe with params
+Flying Heroes filter pipe (pure)
+Flying Heroes filter pipe (impure)
+Async Hero Message and AsyncPipe
+Hero List with caching FetchJsonPipe
+
+
+
+
+Hero Birthday v1
+
+
+
+
+Birthday DatePipe
+
+The hero's birthday is {{ birthday | date }}
+
+
+
+The hero's birthday is {{ birthday | date:"MM/dd/yy" }}
+
+
+
+
+Hero Birthday v2
+
+
+
+
+Birthday Pipe Chaining
+
+
+ The chained hero's birthday is
+ {{ birthday | date | uppercase}}
+
+
+
+
+
+ The chained hero's birthday is
+ {{ birthday | date:'fullDate' | uppercase}}
+
+
+
+
+ The chained hero's birthday is
+ {{ ( birthday | date:'fullDate' ) | uppercase}}
+
+
+
+
+
+
+
+
+loading
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/public/docs/_examples/pipes/ts/src/app/app.component.ts b/public/docs/_examples/pipes/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..090eae7766
--- /dev/null
+++ b/public/docs/_examples/pipes/ts/src/app/app.component.ts
@@ -0,0 +1,10 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ templateUrl: './app.component.html'
+})
+export class AppComponent {
+ birthday = new Date(1988, 3, 15); // April 15, 1988
+}
diff --git a/public/docs/_examples/pipes/ts/src/app/app.module.ts b/public/docs/_examples/pipes/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..89a3a29505
--- /dev/null
+++ b/public/docs/_examples/pipes/ts/src/app/app.module.ts
@@ -0,0 +1,48 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { FormsModule } from '@angular/forms';
+import { HttpModule } from '@angular/http';
+
+import { AppComponent } from './app.component';
+import {
+ FlyingHeroesComponent,
+ FlyingHeroesImpureComponent
+} from './flying-heroes.component';
+import { HeroAsyncMessageComponent } from './hero-async-message.component';
+import { HeroBirthdayComponent } from './hero-birthday1.component';
+import { HeroBirthday2Component } from './hero-birthday2.component';
+import { HeroListComponent } from './hero-list.component';
+import { PowerBoosterComponent } from './power-booster.component';
+import { PowerBoostCalculatorComponent } from './power-boost-calculator.component';
+import {
+ FlyingHeroesPipe,
+ FlyingHeroesImpurePipe
+} from './flying-heroes.pipe';
+import { FetchJsonPipe } from './fetch-json.pipe';
+import { ExponentialStrengthPipe } from './exponential-strength.pipe';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ FormsModule,
+ HttpModule
+ ],
+ declarations: [
+ AppComponent,
+ FlyingHeroesComponent,
+ FlyingHeroesImpureComponent,
+ HeroAsyncMessageComponent,
+ HeroBirthdayComponent,
+ HeroBirthday2Component,
+ HeroListComponent,
+ PowerBoosterComponent,
+ PowerBoostCalculatorComponent,
+ FlyingHeroesPipe,
+ FlyingHeroesImpurePipe,
+ FetchJsonPipe,
+ ExponentialStrengthPipe
+ ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/pipes/ts/src/app/exponential-strength.pipe.ts b/public/docs/_examples/pipes/ts/src/app/exponential-strength.pipe.ts
new file mode 100644
index 0000000000..0a703d7016
--- /dev/null
+++ b/public/docs/_examples/pipes/ts/src/app/exponential-strength.pipe.ts
@@ -0,0 +1,18 @@
+// #docregion
+import { Pipe, PipeTransform } from '@angular/core';
+/*
+ * Raise the value exponentially
+ * Takes an exponent argument that defaults to 1.
+ * Usage:
+ * value | exponentialStrength:exponent
+ * Example:
+ * {{ 2 | exponentialStrength:10}}
+ * formats to: 1024
+*/
+@Pipe({name: 'exponentialStrength'})
+export class ExponentialStrengthPipe implements PipeTransform {
+ transform(value: number, exponent: string): number {
+ let exp = parseFloat(exponent);
+ return Math.pow(value, isNaN(exp) ? 1 : exp);
+ }
+}
diff --git a/public/docs/_examples/pipes/ts/src/app/fetch-json.pipe.ts b/public/docs/_examples/pipes/ts/src/app/fetch-json.pipe.ts
new file mode 100644
index 0000000000..4d56e865f3
--- /dev/null
+++ b/public/docs/_examples/pipes/ts/src/app/fetch-json.pipe.ts
@@ -0,0 +1,30 @@
+// #docregion
+import { Pipe, PipeTransform } from '@angular/core';
+import { Http } from '@angular/http';
+
+import 'rxjs/add/operator/map';
+
+// #docregion pipe-metadata
+@Pipe({
+ name: 'fetch',
+ pure: false
+})
+// #enddocregion pipe-metadata
+export class FetchJsonPipe implements PipeTransform {
+ private cachedData: any = null;
+ private cachedUrl = '';
+
+ constructor(private http: Http) { }
+
+ transform(url: string): any {
+ if (url !== this.cachedUrl) {
+ this.cachedData = null;
+ this.cachedUrl = url;
+ this.http.get(url)
+ .map( result => result.json() )
+ .subscribe( result => this.cachedData = result );
+ }
+
+ return this.cachedData;
+ }
+}
diff --git a/public/docs/_examples/pipes/ts/src/app/flying-heroes-impure.component.html b/public/docs/_examples/pipes/ts/src/app/flying-heroes-impure.component.html
new file mode 100644
index 0000000000..66bd86f81c
--- /dev/null
+++ b/public/docs/_examples/pipes/ts/src/app/flying-heroes-impure.component.html
@@ -0,0 +1,38 @@
+
+
+{{title}}
+
+
+New hero:
+
+
+ can fly
+
+
+ Mutate array
+
+ Reset
+
+
+
+Heroes who fly (piped)
+
+
+
+ {{hero.name}}
+
+
+
+
+All Heroes (no pipe)
+
+
+
+
+ {{hero.name}}
+
+
+
+
diff --git a/public/docs/_examples/pipes/ts/src/app/flying-heroes.component.html b/public/docs/_examples/pipes/ts/src/app/flying-heroes.component.html
new file mode 100644
index 0000000000..93e635b662
--- /dev/null
+++ b/public/docs/_examples/pipes/ts/src/app/flying-heroes.component.html
@@ -0,0 +1,38 @@
+
+
+{{title}}
+
+
+New hero:
+
+
+ can fly
+
+
+ Mutate array
+
+ Reset
+
+
+
+Heroes who fly (piped)
+
+
+
+ {{hero.name}}
+
+
+
+
+All Heroes (no pipe)
+
+
+
+
+ {{hero.name}}
+
+
+
+
diff --git a/public/docs/_examples/pipes/ts/src/app/flying-heroes.component.ts b/public/docs/_examples/pipes/ts/src/app/flying-heroes.component.ts
new file mode 100644
index 0000000000..e4abb09a2f
--- /dev/null
+++ b/public/docs/_examples/pipes/ts/src/app/flying-heroes.component.ts
@@ -0,0 +1,61 @@
+// #docplaster
+// #docregion
+import { Component } from '@angular/core';
+
+import { HEROES } from './heroes';
+
+@Component({
+ selector: 'flying-heroes',
+ templateUrl: './flying-heroes.component.html',
+ styles: ['#flyers, #all {font-style: italic}']
+})
+// #docregion v1
+export class FlyingHeroesComponent {
+ heroes: any[] = [];
+ canFly = true;
+// #enddocregion v1
+ mutate = true;
+ title = 'Flying Heroes (pure pipe)';
+
+// #docregion v1
+ constructor() { this.reset(); }
+
+ addHero(name: string) {
+ name = name.trim();
+ if (!name) { return; }
+ let hero = {name, canFly: this.canFly};
+// #enddocregion v1
+ if (this.mutate) {
+ // Pure pipe won't update display because heroes array reference is unchanged
+ // Impure pipe will display
+// #docregion v1
+// #docregion push
+ this.heroes.push(hero);
+// #enddocregion push
+// #enddocregion v1
+ } else {
+ // Pipe updates display because heroes array is a new object
+// #docregion concat
+ this.heroes = this.heroes.concat(hero);
+// #enddocregion concat
+ }
+// #docregion v1
+ }
+
+ reset() { this.heroes = HEROES.slice(); }
+}
+// #enddocregion v1
+
+////// Identical except for impure pipe //////
+// #docregion impure-component
+@Component({
+ selector: 'flying-heroes-impure',
+ templateUrl: './flying-heroes-impure.component.html',
+// #enddocregion impure-component
+ styles: ['.flyers, .all {font-style: italic}'],
+// #docregion impure-component
+})
+export class FlyingHeroesImpureComponent extends FlyingHeroesComponent {
+ title = 'Flying Heroes (impure pipe)';
+}
+// #enddocregion impure-component
diff --git a/public/docs/_examples/pipes/ts/src/app/flying-heroes.pipe.ts b/public/docs/_examples/pipes/ts/src/app/flying-heroes.pipe.ts
new file mode 100644
index 0000000000..87db9c277e
--- /dev/null
+++ b/public/docs/_examples/pipes/ts/src/app/flying-heroes.pipe.ts
@@ -0,0 +1,27 @@
+/* tslint:disable use-pipe-transform-interface */
+// #docregion
+// #docregion pure
+import { Pipe, PipeTransform } from '@angular/core';
+
+import { Flyer } from './heroes';
+
+@Pipe({ name: 'flyingHeroes' })
+export class FlyingHeroesPipe implements PipeTransform {
+ transform(allHeroes: Flyer[]) {
+ // #docregion filter
+ return allHeroes.filter(hero => hero.canFly);
+ // #enddocregion filter
+ }
+}
+// #enddocregion pure
+
+/////// Identical except for the pure flag
+// #docregion impure
+// #docregion pipe-decorator
+@Pipe({
+ name: 'flyingHeroesImpure',
+ pure: false
+})
+// #enddocregion pipe-decorator
+export class FlyingHeroesImpurePipe extends FlyingHeroesPipe {}
+// #enddocregion impure
diff --git a/public/docs/_examples/pipes/ts/src/app/hero-async-message.component.ts b/public/docs/_examples/pipes/ts/src/app/hero-async-message.component.ts
new file mode 100644
index 0000000000..d5bbd9fb0e
--- /dev/null
+++ b/public/docs/_examples/pipes/ts/src/app/hero-async-message.component.ts
@@ -0,0 +1,38 @@
+// #docregion
+import { Component } from '@angular/core';
+
+import { Observable } from 'rxjs/Observable';
+import 'rxjs/add/observable/interval';
+import 'rxjs/add/operator/map';
+import 'rxjs/add/operator/take';
+
+@Component({
+ selector: 'hero-message',
+ template: `
+ Async Hero Message and AsyncPipe
+ Message: {{ message$ | async }}
+ Resend `,
+})
+export class HeroAsyncMessageComponent {
+ message$: Observable;
+
+ private messages = [
+ 'You are my hero!',
+ 'You are the best hero!',
+ 'Will you be my hero?'
+ ];
+
+ constructor() { this.resend(); }
+
+ resend() {
+ this.message$ = Observable.interval(500)
+ .map(i => this.messages[i])
+ .take(this.messages.length);
+ }
+}
+// #enddocregion
+
+// Alternative message$ formula:
+// this.message$ = Observable.fromArray(this.messages)
+// .map(message => Observable.timer(500).map(() => message))
+// .concatAll();
diff --git a/public/docs/_examples/pipes/ts/src/app/hero-birthday1.component.ts b/public/docs/_examples/pipes/ts/src/app/hero-birthday1.component.ts
new file mode 100644
index 0000000000..a670a807a8
--- /dev/null
+++ b/public/docs/_examples/pipes/ts/src/app/hero-birthday1.component.ts
@@ -0,0 +1,12 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'hero-birthday',
+ // #docregion hero-birthday-template
+ template: `The hero's birthday is {{ birthday | date }}
`
+ // #enddocregion hero-birthday-template
+})
+export class HeroBirthdayComponent {
+ birthday = new Date(1988, 3, 15); // April 15, 1988
+}
diff --git a/public/docs/_examples/pipes/ts/src/app/hero-birthday2.component.ts b/public/docs/_examples/pipes/ts/src/app/hero-birthday2.component.ts
new file mode 100644
index 0000000000..87481aa121
--- /dev/null
+++ b/public/docs/_examples/pipes/ts/src/app/hero-birthday2.component.ts
@@ -0,0 +1,20 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'hero-birthday2',
+ // #docregion template
+ template: `
+ The hero's birthday is {{ birthday | date:format }}
+ Toggle Format
+ `
+ // #enddocregion template
+})
+// #docregion class
+export class HeroBirthday2Component {
+ birthday = new Date(1988, 3, 15); // April 15, 1988
+ toggle = true; // start with true == shortDate
+
+ get format() { return this.toggle ? 'shortDate' : 'fullDate'; }
+ toggleFormat() { this.toggle = !this.toggle; }
+}
diff --git a/public/docs/_examples/pipes/ts/src/app/hero-list.component.ts b/public/docs/_examples/pipes/ts/src/app/hero-list.component.ts
new file mode 100644
index 0000000000..df231120ce
--- /dev/null
+++ b/public/docs/_examples/pipes/ts/src/app/hero-list.component.ts
@@ -0,0 +1,17 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'hero-list',
+ template: `
+ Heroes from JSON File
+
+
+ {{hero.name}}
+
+
+ Heroes as JSON:
+ {{'heroes.json' | fetch | json}}
+
`
+})
+export class HeroListComponent { }
diff --git a/public/docs/_examples/pipes/ts/src/app/heroes.ts b/public/docs/_examples/pipes/ts/src/app/heroes.ts
new file mode 100644
index 0000000000..b2edabe0da
--- /dev/null
+++ b/public/docs/_examples/pipes/ts/src/app/heroes.ts
@@ -0,0 +1,7 @@
+export interface Flyer { canFly: boolean; }
+export const HEROES = [
+ {name: 'Windstorm', canFly: true},
+ {name: 'Bombasto', canFly: false},
+ {name: 'Magneto', canFly: false},
+ {name: 'Tornado', canFly: true}
+];
diff --git a/public/docs/_examples/pipes/ts/src/app/power-boost-calculator.component.ts b/public/docs/_examples/pipes/ts/src/app/power-boost-calculator.component.ts
new file mode 100644
index 0000000000..e65e29ad4c
--- /dev/null
+++ b/public/docs/_examples/pipes/ts/src/app/power-boost-calculator.component.ts
@@ -0,0 +1,18 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'power-boost-calculator',
+ template: `
+ Power Boost Calculator
+ Normal power:
+ Boost factor:
+
+ Super Hero Power: {{power | exponentialStrength: factor}}
+
+ `
+})
+export class PowerBoostCalculatorComponent {
+ power = 5;
+ factor = 1;
+}
diff --git a/public/docs/_examples/pipes/ts/src/app/power-booster.component.ts b/public/docs/_examples/pipes/ts/src/app/power-booster.component.ts
new file mode 100644
index 0000000000..08e3e24c7b
--- /dev/null
+++ b/public/docs/_examples/pipes/ts/src/app/power-booster.component.ts
@@ -0,0 +1,11 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'power-booster',
+ template: `
+ Power Booster
+ Super power boost: {{2 | exponentialStrength: 10}}
+ `
+})
+export class PowerBoosterComponent { }
diff --git a/public/docs/_examples/pipes/ts/src/heroes.json b/public/docs/_examples/pipes/ts/src/heroes.json
new file mode 100644
index 0000000000..e5f0b77262
--- /dev/null
+++ b/public/docs/_examples/pipes/ts/src/heroes.json
@@ -0,0 +1,6 @@
+[
+ {"name": "Windstorm", "canFly": true},
+ {"name": "Bombasto", "canFly": false},
+ {"name": "Magneto", "canFly": false},
+ {"name": "Tornado", "canFly": true}
+]
diff --git a/public/docs/_examples/pipes/ts/src/index.html b/public/docs/_examples/pipes/ts/src/index.html
new file mode 100644
index 0000000000..fedb5c2e5e
--- /dev/null
+++ b/public/docs/_examples/pipes/ts/src/index.html
@@ -0,0 +1,26 @@
+
+
+
+ Pipes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ my-app loading ...
+
+
+
diff --git a/public/docs/_examples/pipes/ts/src/main.ts b/public/docs/_examples/pipes/ts/src/main.ts
new file mode 100644
index 0000000000..6b6532d428
--- /dev/null
+++ b/public/docs/_examples/pipes/ts/src/main.ts
@@ -0,0 +1,5 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/protractor-conf.old.js b/public/docs/_examples/protractor-conf.old.js
deleted file mode 100644
index 12dd89ab9f..0000000000
--- a/public/docs/_examples/protractor-conf.old.js
+++ /dev/null
@@ -1,24 +0,0 @@
-exports.config = {
- onPrepare: function() {
- patchProtractorWait(browser);
- },
- seleniumAddress: 'http://localhost:4444/wd/hub',
- baseUrl: 'http://localhost:8080/',
- specs: [
- '**/*e2e-spec.js'
- ]
-};
-
-// Disable waiting for Angular as we don't have an integration layer yet...
-// TODO(tbosch): Implement a proper debugging API for Ng2.0, remove this here
-// and the sleeps in all tests.
-function patchProtractorWait(browser) {
- browser.ignoreSynchronization = true;
- var _get = browser.get;
- var sleepInterval = process.env.TRAVIS || process.env.JENKINS_URL ? 14000 : 8000;
- browser.get = function() {
- var result = _get.apply(this, arguments);
- browser.sleep(sleepInterval);
- return result;
- }
-}
diff --git a/public/docs/_examples/protractor-helpers.ts b/public/docs/_examples/protractor-helpers.ts
new file mode 100644
index 0000000000..61af74ba30
--- /dev/null
+++ b/public/docs/_examples/protractor-helpers.ts
@@ -0,0 +1,35 @@
+import { browser } from 'protractor';
+
+export var appLang = {
+ appIsTs: false,
+ appIsJs: false,
+ appIsDart: false,
+ appIsUnknown: false
+};
+
+export function describeIf(cond: boolean, name: string, func: () => void): void {
+ if (cond) {
+ describe(name, func);
+ } else {
+ xdescribe(name, func);
+ }
+}
+
+export function itIf(cond: boolean, name: string, func: (done: DoneFn) => void): void {
+ if (cond) {
+ it(name, func);
+ } else {
+ xit(name, func);
+ }
+}
+
+// protractor.config.js is set to ng2 mode by default, so we must manually
+// change it for upgradeAdapter tests
+export function setProtractorToNg1Mode(): void {
+ browser.rootEl = 'body';
+}
+
+export function setProtractorToHybridMode() {
+ setProtractorToNg1Mode();
+ browser.ng12Hybrid = true;
+}
diff --git a/public/docs/_examples/protractor.config.js b/public/docs/_examples/protractor.config.js
index 1a128f4ca9..92b5e1fda5 100644
--- a/public/docs/_examples/protractor.config.js
+++ b/public/docs/_examples/protractor.config.js
@@ -1,9 +1,14 @@
-// TO RUN THE TESTS
-//
-// The first time, run:
+// FIRST TIME ONLY- run:
// ./node_modules/.bin/webdriver-manager update
-// Make sure the test server is running. Then do.
-// ./node_modules/.bin/protractor protractor.config.js
+//
+// Try: `npm run webdriver:update`
+//
+// AND THEN EVERYTIME ...
+// 1. Compile with `tsc`
+// 2. Make sure the test server (e.g., http-server: localhost:8080) is running.
+// 3. ./node_modules/.bin/protractor protractor.config.js
+//
+// To do all steps, try: `npm run e2e`
var fs = require('fs');
var path = require('canonical-path');
@@ -21,18 +26,15 @@ exports.config = {
// Framework to use. Jasmine is recommended.
framework: 'jasmine',
- // Spec patterns are relative to this config file
- specs: ['**/*e2e-spec.js' ],
-
-
- // For angular2 tests
+ // For angular tests
useAllAngular2AppRoots: true,
+ // Base URL for application server
baseUrl: 'http://localhost:8080',
// doesn't seem to work.
// resultJsonOutputFile: "foo.json",
-
+
onPrepare: function() {
//// SpecReporter
//var SpecReporter = require('jasmine-spec-reporter');
@@ -41,25 +43,23 @@ exports.config = {
// debugging
// console.log('browser.params:' + JSON.stringify(browser.params));
+ var protractorHelpers = require('./protractor-helpers.ts');
var appDir = browser.params.appDir;
if (appDir) {
if (appDir.match('/ts') != null) {
- browser.appIsTs = true;
+ protractorHelpers.appLang.appIsTs = true;
} else if (appDir.match('/js') != null) {
- browser.appIsJs = true;
+ protractorHelpers.appLang.appIsJs = true;
} else if (appDir.match('/dart') != null) {
- browser.appIsDart = true;
+ protractorHelpers.appLang.appIsDart = true;
} else {
- browser.appIsUnknown = true;
+ protractorHelpers.appLang.appIsUnknown = true;
}
} else {
- browser.appIsUnknown = true;
+ protractorHelpers.appLang.appIsUnknown = true;
}
- jasmine.getEnv().addReporter(new Reporter( browser.params )) ;
- global.describeIf = describeIf;
- global.itIf = itIf;
- global.sendKeys = sendKeys;
+ jasmine.getEnv().addReporter(new Reporter( browser.params ));
},
jasmineNodeOpts: {
@@ -67,38 +67,19 @@ exports.config = {
defaultTimeoutInterval: 10000,
showTiming: true,
print: function() {}
- }
-};
-
-function describeIf(cond, name, func) {
- if (cond) {
- describe(name, func);
- } else {
- xdescribe(name, func);
- }
-}
-
-function itIf(cond, name, func) {
- if (cond) {
- it(name, func);
- } else {
- xit(name, func);
- }
-}
+ },
-// Hack - because of bug with send keys
-function sendKeys(element, str) {
- return str.split('').reduce(function (promise, char) {
- return promise.then(function () {
- return element.sendKeys(char);
+ beforeLaunch: function() {
+ // add TS support for specs
+ require('ts-node').register({
+ project: './tsconfig.json'
});
- }, element.getAttribute('value'));
- // better to create a resolved promise here but ... don't know how with protractor;
-}
-
+ }
+};
+// See http://jasmine.github.io/2.1/custom_reporter.html
function Reporter(options) {
- var _defaultOutputFile = path.resolve(process.cwd(), "../../", 'protractor-results.txt');
+ var _defaultOutputFile = path.resolve(process.cwd(), "../../../", 'protractor-results.txt');
options.outputFile = options.outputFile || _defaultOutputFile;
var _root = { appDir: options.appDir, suites: [] };
@@ -136,6 +117,11 @@ function Reporter(options) {
_currentSuite.specs.push(currentSpec);
log(spec.status + ' - ' + spec.description);
+ if (spec.status === 'failed') {
+ spec.failedExpectations.forEach(function(err) {
+ log(err.message);
+ });
+ }
};
this.jasmineDone = function() {
@@ -187,4 +173,3 @@ function Reporter(options) {
}
}
-
diff --git a/public/docs/_examples/quickstart/dart/ex1/pubspec.yaml b/public/docs/_examples/quickstart/dart/ex1/pubspec.yaml
deleted file mode 100644
index c1be565dad..0000000000
--- a/public/docs/_examples/quickstart/dart/ex1/pubspec.yaml
+++ /dev/null
@@ -1,12 +0,0 @@
-# #docregion
-name: angular2_getting_started
-description: QuickStart
-version: 0.0.1
-environment:
- sdk: '>=1.13.0 <2.0.0'
-dependencies:
- angular2: 2.0.0-beta.8
- browser: ^0.10.0
-transformers:
-- angular2:
- entry_points: web/main.dart
diff --git a/public/docs/_examples/quickstart/dart/ex1/web/index.html b/public/docs/_examples/quickstart/dart/ex1/web/index.html
deleted file mode 100644
index a1e925b8fb..0000000000
--- a/public/docs/_examples/quickstart/dart/ex1/web/index.html
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
- Getting Started
-
-
-
-
-
-
-
-
- Loading...
-
-
diff --git a/public/docs/_examples/quickstart/dart/ex1/web/main.dart b/public/docs/_examples/quickstart/dart/ex1/web/main.dart
deleted file mode 100644
index e6836148a3..0000000000
--- a/public/docs/_examples/quickstart/dart/ex1/web/main.dart
+++ /dev/null
@@ -1,10 +0,0 @@
-// #docregion
-import 'package:angular2/angular2.dart';
-import 'package:angular2/bootstrap.dart';
-
-@Component(selector: 'my-app', template: 'My First Angular 2 App ')
-class AppComponent {}
-
-main() {
- bootstrap(AppComponent);
-}
diff --git a/public/docs/_examples/quickstart/dart/ex2/pubspec.yaml b/public/docs/_examples/quickstart/dart/ex2/pubspec.yaml
deleted file mode 100644
index ce8c66ece3..0000000000
--- a/public/docs/_examples/quickstart/dart/ex2/pubspec.yaml
+++ /dev/null
@@ -1,14 +0,0 @@
-# #docregion
-name: angular2_getting_started
-description: QuickStart
-version: 0.0.1
-environment:
- sdk: '>=1.13.0 <2.0.0'
-dependencies:
- angular2: 2.0.0-beta.8
- browser: ^0.10.0
- dart_to_js_script_rewriter: ^0.1.0
-transformers:
-- angular2:
- entry_points: web/main.dart
-- dart_to_js_script_rewriter
diff --git a/public/docs/_examples/quickstart/dart/ex2/web/index.html b/public/docs/_examples/quickstart/dart/ex2/web/index.html
deleted file mode 100644
index a1e925b8fb..0000000000
--- a/public/docs/_examples/quickstart/dart/ex2/web/index.html
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
- Getting Started
-
-
-
-
-
-
-
-
- Loading...
-
-
diff --git a/public/docs/_examples/quickstart/dart/ex2/web/main.dart b/public/docs/_examples/quickstart/dart/ex2/web/main.dart
deleted file mode 100644
index e6836148a3..0000000000
--- a/public/docs/_examples/quickstart/dart/ex2/web/main.dart
+++ /dev/null
@@ -1,10 +0,0 @@
-// #docregion
-import 'package:angular2/angular2.dart';
-import 'package:angular2/bootstrap.dart';
-
-@Component(selector: 'my-app', template: 'My First Angular 2 App ')
-class AppComponent {}
-
-main() {
- bootstrap(AppComponent);
-}
diff --git a/public/docs/_examples/quickstart/e2e-spec.js b/public/docs/_examples/quickstart/e2e-spec.js
deleted file mode 100644
index 52bb8ec7af..0000000000
--- a/public/docs/_examples/quickstart/e2e-spec.js
+++ /dev/null
@@ -1,15 +0,0 @@
-
-describe('QuickStart E2E Tests', function () {
-
- var expectedMsg = 'My First Angular 2 App';
-
-
- beforeEach(function () {
- browser.get('');
- });
-
- it('should display: ' + expectedMsg, function () {
- expect(element(by.css('h1')).getText()).toEqual(expectedMsg);
- });
-
-});
diff --git a/public/docs/_examples/quickstart/e2e-spec.ts b/public/docs/_examples/quickstart/e2e-spec.ts
new file mode 100644
index 0000000000..73921707ee
--- /dev/null
+++ b/public/docs/_examples/quickstart/e2e-spec.ts
@@ -0,0 +1,17 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by } from 'protractor';
+
+describe('QuickStart E2E Tests', function () {
+
+ let expectedMsg = 'Hello Angular';
+
+ beforeEach(function () {
+ browser.get('');
+ });
+
+ it(`should display: ${expectedMsg}`, function () {
+ expect(element(by.css('h1')).getText()).toEqual(expectedMsg);
+ });
+
+});
diff --git a/public/docs/_examples/quickstart/js/app/app.component.js b/public/docs/_examples/quickstart/js/app/app.component.js
deleted file mode 100644
index f86b3bde46..0000000000
--- a/public/docs/_examples/quickstart/js/app/app.component.js
+++ /dev/null
@@ -1,27 +0,0 @@
-// #docplaster
-// #docregion
-// #docregion iife
-(function(app) {
- // #enddocregion iife
- // #docregion ng-namespace-funcs, export
- app.AppComponent =
- // #enddocregion export
- // #docregion component
- ng.core.Component({
- // #enddocregion ng-namespace-funcs
- selector: 'my-app',
- template: 'My First Angular 2 App '
- // #docregion ng-namespace-funcs
- })
- // #enddocregion component
- // #docregion class
- .Class({
- // #enddocregion ng-namespace-funcs
- constructor: function() {}
- // #docregion ng-namespace-funcs
- });
- // #enddocregion class
- // #enddocregion ng-namespace-funcs
-// #docregion iife
-})(window.app || (window.app = {}));
-// #enddocregion iife
diff --git a/public/docs/_examples/quickstart/js/app/main.js b/public/docs/_examples/quickstart/js/app/main.js
deleted file mode 100644
index d003119574..0000000000
--- a/public/docs/_examples/quickstart/js/app/main.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// #docregion
-(function(app) {
- document.addEventListener('DOMContentLoaded', function() {
- // #docregion import
- ng.platform.browser.bootstrap(app.AppComponent);
- // #enddocregion import
- });
-})(window.app || (window.app = {}));
diff --git a/public/docs/_examples/quickstart/js/bs-config.1.json b/public/docs/_examples/quickstart/js/bs-config.1.json
new file mode 100644
index 0000000000..4e58595267
--- /dev/null
+++ b/public/docs/_examples/quickstart/js/bs-config.1.json
@@ -0,0 +1,8 @@
+{
+ "server": {
+ "baseDir": "src",
+ "routes": {
+ "/node_modules": "node_modules"
+ }
+ }
+}
diff --git a/public/docs/_examples/quickstart/js/example-config.json b/public/docs/_examples/quickstart/js/example-config.json
index e69de29bb2..81f31aaf0d 100644
--- a/public/docs/_examples/quickstart/js/example-config.json
+++ b/public/docs/_examples/quickstart/js/example-config.json
@@ -0,0 +1,3 @@
+{
+ "build": "build:babel"
+}
diff --git a/public/docs/_examples/quickstart/js/index.html b/public/docs/_examples/quickstart/js/index.html
deleted file mode 100644
index 1e66047c46..0000000000
--- a/public/docs/_examples/quickstart/js/index.html
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
-
- Angular 2 QuickStart
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Loading...
-
-
-
-
diff --git a/public/docs/_examples/quickstart/js/package.1.json b/public/docs/_examples/quickstart/js/package.1.json
index c41de3b0a9..28aee2b92e 100644
--- a/public/docs/_examples/quickstart/js/package.1.json
+++ b/public/docs/_examples/quickstart/js/package.1.json
@@ -1,21 +1,29 @@
{
- "name": "angular2-quickstart",
+ "name": "angular-quickstart",
"version": "1.0.0",
"scripts": {
"start": "npm run lite",
"lite": "lite-server"
},
- "license": "ISC",
+ "license": "MIT",
"dependencies": {
- "angular2": "2.0.0-beta.8",
- "es6-promise": "^3.0.2",
- "es6-shim": "^0.33.3",
- "reflect-metadata": "0.1.2",
- "rxjs": "5.0.0-beta.2",
- "zone.js": "0.5.15"
+ "@angular/common": "~2.4.0",
+ "@angular/compiler": "~2.4.0",
+ "@angular/core": "~2.4.0",
+ "@angular/forms": "~2.4.0",
+ "@angular/http": "~2.4.0",
+ "@angular/platform-browser": "~2.4.0",
+ "@angular/platform-browser-dynamic": "~2.4.0",
+ "@angular/router": "~3.4.0",
+ "@angular/upgrade": "~2.4.0",
+
+ "angular-in-memory-web-api": "~0.3.1",
+ "core-js": "^2.4.1",
+ "rxjs": "5.0.1",
+ "zone.js": "^0.8.4"
},
"devDependencies": {
- "concurrently": "^2.0.0",
- "lite-server": "^2.1.0"
+ "concurrently": "^3.0.0",
+ "lite-server": "^2.2.2"
}
}
diff --git a/public/docs/_examples/quickstart/js/plnkr.json b/public/docs/_examples/quickstart/js/plnkr.json
index 16a1c9a6c0..5e24ad9790 100644
--- a/public/docs/_examples/quickstart/js/plnkr.json
+++ b/public/docs/_examples/quickstart/js/plnkr.json
@@ -1,5 +1,6 @@
{
"description": "QuickStart",
+ "basePath": "src/",
"files": [
"!**/*.[1].*"
],
diff --git a/public/docs/_examples/quickstart/js/spec.js b/public/docs/_examples/quickstart/js/spec.js
deleted file mode 100644
index 83f3eaea94..0000000000
--- a/public/docs/_examples/quickstart/js/spec.js
+++ /dev/null
@@ -1,9 +0,0 @@
-describe("Jasmine sample test", function() {
-
- it("1+1 should be 2", function() {
-
- var result = 1 + 1;
-
- expect(result).toBe(2);
- });
-});
\ No newline at end of file
diff --git a/public/docs/_examples/quickstart/js/src/app/app.component.js b/public/docs/_examples/quickstart/js/src/app/app.component.js
new file mode 100644
index 0000000000..26ba116efe
--- /dev/null
+++ b/public/docs/_examples/quickstart/js/src/app/app.component.js
@@ -0,0 +1,27 @@
+// #docplaster
+// #docregion
+// #docregion iife
+(function(app) {
+ // #enddocregion iife
+ // #docregion ng-namespace-funcs, export
+ app.AppComponent =
+ // #enddocregion export
+ // #docregion component
+ ng.core.Component({
+ // #enddocregion ng-namespace-funcs
+ selector: 'my-app',
+ template: 'Hello Angular '
+ // #docregion ng-namespace-funcs
+ })
+ // #enddocregion component
+ // #docregion class
+ .Class({
+ // #enddocregion ng-namespace-funcs
+ constructor: function() {}
+ // #docregion ng-namespace-funcs
+ });
+ // #enddocregion class
+ // #enddocregion ng-namespace-funcs
+// #docregion iife
+})(window.app || (window.app = {}));
+// #enddocregion iife
diff --git a/public/docs/_examples/quickstart/js/src/app/app.module.js b/public/docs/_examples/quickstart/js/src/app/app.module.js
new file mode 100644
index 0000000000..0f3d5f82cf
--- /dev/null
+++ b/public/docs/_examples/quickstart/js/src/app/app.module.js
@@ -0,0 +1,15 @@
+// #docplaster
+// #docregion
+(function(app) {
+ app.AppModule =
+ ng.core.NgModule({
+ imports: [ ng.platformBrowser.BrowserModule ],
+ // #docregion import
+ declarations: [ app.AppComponent ],
+ // #enddocregion import
+ bootstrap: [ app.AppComponent ]
+ })
+ .Class({
+ constructor: function() {}
+ });
+})(window.app || (window.app = {}));
diff --git a/public/docs/_examples/quickstart/js/src/index.html b/public/docs/_examples/quickstart/js/src/index.html
new file mode 100644
index 0000000000..43d63e9c83
--- /dev/null
+++ b/public/docs/_examples/quickstart/js/src/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+ Angular QuickStart JS
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
+
diff --git a/public/docs/_examples/quickstart/js/src/main.js b/public/docs/_examples/quickstart/js/src/main.js
new file mode 100644
index 0000000000..785823fa84
--- /dev/null
+++ b/public/docs/_examples/quickstart/js/src/main.js
@@ -0,0 +1,8 @@
+// #docregion
+(function(app) {
+ document.addEventListener('DOMContentLoaded', function() {
+ ng.platformBrowserDynamic
+ .platformBrowserDynamic()
+ .bootstrapModule(app.AppModule);
+ });
+})(window.app || (window.app = {}));
diff --git a/public/docs/_examples/quickstart/js/src/styles.1.css b/public/docs/_examples/quickstart/js/src/styles.1.css
new file mode 100644
index 0000000000..fbc30e2c9e
--- /dev/null
+++ b/public/docs/_examples/quickstart/js/src/styles.1.css
@@ -0,0 +1,14 @@
+/* #docregion */
+h1 {
+ color: #369;
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 250%;
+}
+body {
+ margin: 2em;
+}
+
+ /*
+ * See https://github.com/angular/angular.io/blob/master/public/docs/_examples/styles.css
+ * for the full set of master styles used by the documentation samples
+ */
diff --git a/public/docs/_examples/quickstart/ts/.gitignore b/public/docs/_examples/quickstart/ts/.gitignore
deleted file mode 100644
index 2cb7d2a2e9..0000000000
--- a/public/docs/_examples/quickstart/ts/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-**/*.js
diff --git a/public/docs/_examples/quickstart/ts/app/app.component.ts b/public/docs/_examples/quickstart/ts/app/app.component.ts
deleted file mode 100644
index 0d6e66d2aa..0000000000
--- a/public/docs/_examples/quickstart/ts/app/app.component.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-// #docregion
-// #docregion import
-import {Component} from 'angular2/core';
-// #enddocregion import
-
-// #docregion metadata
-@Component({
- selector: 'my-app',
- template: 'My First Angular 2 App '
-})
-// #enddocregion metadata
-// #docregion export
-export class AppComponent { }
-// #enddocregion export
\ No newline at end of file
diff --git a/public/docs/_examples/quickstart/ts/app/main.ts b/public/docs/_examples/quickstart/ts/app/main.ts
deleted file mode 100644
index effe7c896f..0000000000
--- a/public/docs/_examples/quickstart/ts/app/main.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// #docregion
-import {bootstrap} from 'angular2/platform/browser'
-// #docregion app-component
-import {AppComponent} from './app.component'
-// #enddocregion app-component
-
-bootstrap(AppComponent);
diff --git a/public/docs/_examples/quickstart/ts/bs-config.1.json b/public/docs/_examples/quickstart/ts/bs-config.1.json
new file mode 100644
index 0000000000..4e58595267
--- /dev/null
+++ b/public/docs/_examples/quickstart/ts/bs-config.1.json
@@ -0,0 +1,8 @@
+{
+ "server": {
+ "baseDir": "src",
+ "routes": {
+ "/node_modules": "node_modules"
+ }
+ }
+}
diff --git a/public/docs/_examples/quickstart/ts/index.html b/public/docs/_examples/quickstart/ts/index.html
deleted file mode 100644
index 21b3a60713..0000000000
--- a/public/docs/_examples/quickstart/ts/index.html
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
-
-
- Angular 2 QuickStart
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Loading...
-
-
-
diff --git a/public/docs/_examples/quickstart/ts/package.1.json b/public/docs/_examples/quickstart/ts/package.1.json
deleted file mode 100644
index 5160703dcf..0000000000
--- a/public/docs/_examples/quickstart/ts/package.1.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "name": "angular2-quickstart",
- "version": "1.0.0",
- "scripts": {
- "start": "concurrently \"npm run tsc:w\" \"npm run lite\" ",
- "tsc": "tsc",
- "tsc:w": "tsc -w",
- "lite": "lite-server",
- "typings": "typings",
- "postinstall": "typings install"
- },
- "license": "ISC",
- "dependencies": {
- "angular2": "2.0.0-beta.8",
- "systemjs": "0.19.22",
- "es6-promise": "^3.0.2",
- "es6-shim": "^0.33.3",
- "reflect-metadata": "0.1.2",
- "rxjs": "5.0.0-beta.2",
- "zone.js": "0.5.15"
- },
- "devDependencies": {
- "concurrently": "^2.0.0",
- "lite-server": "^2.1.0",
- "typescript": "^1.8.2",
- "typings":"^0.6.8"
- }
-}
diff --git a/public/docs/_examples/quickstart/ts/plnkr.json b/public/docs/_examples/quickstart/ts/plnkr.json
index a4449b444f..8edf7c25ea 100644
--- a/public/docs/_examples/quickstart/ts/plnkr.json
+++ b/public/docs/_examples/quickstart/ts/plnkr.json
@@ -1,9 +1,12 @@
{
"description": "QuickStart",
+ "basePath": "src/",
"files": [
- "!**/*.d.ts",
- "!**/*.js",
- "!**/*.[1].*"
+ "app/app.component.ts",
+ "app/app.module.ts",
+ "main.ts",
+ "index.html"
],
+ "open": "app/app.component.ts",
"tags": ["quickstart"]
-}
\ No newline at end of file
+}
diff --git a/public/docs/_examples/quickstart/ts/src/app/app.component.ts b/public/docs/_examples/quickstart/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..1ef28fc5c4
--- /dev/null
+++ b/public/docs/_examples/quickstart/ts/src/app/app.component.ts
@@ -0,0 +1,8 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ template: `Hello {{name}} `
+})
+export class AppComponent { name = 'Angular'; }
diff --git a/public/docs/_examples/quickstart/ts/src/app/app.module.ts b/public/docs/_examples/quickstart/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..50a0e6eb47
--- /dev/null
+++ b/public/docs/_examples/quickstart/ts/src/app/app.module.ts
@@ -0,0 +1,11 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { AppComponent } from './app.component';
+
+@NgModule({
+ imports: [ BrowserModule ],
+ declarations: [ AppComponent ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/quickstart/ts/src/index.html b/public/docs/_examples/quickstart/ts/src/index.html
new file mode 100644
index 0000000000..21fb56edb9
--- /dev/null
+++ b/public/docs/_examples/quickstart/ts/src/index.html
@@ -0,0 +1,31 @@
+
+
+
+ Angular Quickstart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading AppComponent content here ...
+
+
+
+
diff --git a/public/docs/_examples/quickstart/ts/src/main.ts b/public/docs/_examples/quickstart/ts/src/main.ts
new file mode 100644
index 0000000000..311c44b76d
--- /dev/null
+++ b/public/docs/_examples/quickstart/ts/src/main.ts
@@ -0,0 +1,5 @@
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/quickstart/ts/src/tsconfig.1.json b/public/docs/_examples/quickstart/ts/src/tsconfig.1.json
new file mode 100644
index 0000000000..2c7260d1bc
--- /dev/null
+++ b/public/docs/_examples/quickstart/ts/src/tsconfig.1.json
@@ -0,0 +1,13 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "module": "commonjs",
+ "moduleResolution": "node",
+ "sourceMap": true,
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "lib": [ "es2015", "dom" ],
+ "noImplicitAny": true,
+ "suppressImplicitAnyIndexErrors": true
+ }
+}
diff --git a/public/docs/_examples/quickstart/ts/tsconfig.1.json b/public/docs/_examples/quickstart/ts/tsconfig.1.json
deleted file mode 100644
index 9be71e4c6e..0000000000
--- a/public/docs/_examples/quickstart/ts/tsconfig.1.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "compilerOptions": {
- "target": "es5",
- "module": "system",
- "moduleResolution": "node",
- "sourceMap": true,
- "emitDecoratorMetadata": true,
- "experimentalDecorators": true,
- "removeComments": false,
- "noImplicitAny": false
- },
- "exclude": [
- "node_modules",
- "typings/main",
- "typings/main.d.ts"
- ]
-}
diff --git a/public/docs/_examples/quickstart/ts/typings.1.json b/public/docs/_examples/quickstart/ts/typings.1.json
deleted file mode 100644
index f10b7c5416..0000000000
--- a/public/docs/_examples/quickstart/ts/typings.1.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "ambientDependencies": {
- "es6-shim": "github:DefinitelyTyped/DefinitelyTyped/es6-shim/es6-shim.d.ts#4de74cb527395c13ba20b438c3a7a419ad931f1c",
- "jasmine": "github:DefinitelyTyped/DefinitelyTyped/jasmine/jasmine.d.ts#bc92442c075929849ec41d28ab618892ba493504"
- }
-}
diff --git a/public/docs/_examples/reactive-forms/e2e-spec.ts b/public/docs/_examples/reactive-forms/e2e-spec.ts
new file mode 100644
index 0000000000..bb788397ef
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/e2e-spec.ts
@@ -0,0 +1,1020 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by } from 'protractor';
+
+function finalDemoAddressForm(element: any, index: number) {
+ let form = {
+ street: element.all(by.css('input[formcontrolname=street]')).get(index).getAttribute('value'),
+ city: element.all(by.css('input[formcontrolname=city]')).get(index).getAttribute('value'),
+ state: element.all(by.css('select[formcontrolname=state]')).get(index).getAttribute('value'),
+ zip: element.all(by.css('input[formcontrolname=zip]')).get(index).getAttribute('value')
+ };
+ return form;
+}
+
+describe('Reactive forms', function() {
+ let select: any;
+
+ beforeEach(function() {
+ browser.get('');
+ select = element(by.css('.container > h4 > select'));
+ });
+
+ describe('navigation', function() {
+ it('should display the title', function() {
+ let title = element(by.css('.container > h1'));
+ expect(title.getText()).toBe('Reactive Forms');
+ });
+
+ it('should contain a dropdown with each example', function() {
+ expect(select.isDisplayed()).toBe(true);
+ });
+
+ it('should have 9 options for different demos', function() {
+ let options = select.all(by.tagName('option'));
+ expect(options.count()).toBe(9);
+ });
+
+ it('should start with Final Demo', function() {
+ select.getAttribute('value').then(function(demo: string) {
+ expect(demo).toBe('Final Demo');
+ });
+ });
+ });
+
+// *************Begin Final Demo test*******************************
+
+ describe('final demo', function() {
+ it('does not select any hero by default', function() {
+ let heroSection = element(by.css('hero-list > div'));
+ expect(heroSection.isPresent()).toBe(false);
+ });
+
+ it('refreshes the page upon button click', function() {
+ // We move to another page...
+ let whirlwindButton = element.all(by.css('nav a')).get(0);
+ whirlwindButton.click();
+ let refresh = element(by.css('button'));
+ refresh.click();
+ let heroSection = element(by.css('hero-list > div'));
+ expect(heroSection.isPresent()).toBe(false);
+ });
+
+ describe('Whirlwind form', function() {
+ beforeEach(function() {
+ let whirlwindButton = element.all(by.css('nav a')).get(0);
+ whirlwindButton.click();
+ });
+
+ it('should show a hero information when the button is clicked', function() {
+ let editMessage = element(by.css('hero-list > div > h3'));
+ expect(editMessage.getText()).toBe('Editing: Whirlwind');
+ });
+
+ it('should show a form with the selected hero information', function() {
+ let nameInput = element(by.css('input[formcontrolname=name]'));
+ expect(nameInput.getAttribute('value')).toBe('Whirlwind');
+ let address1 = finalDemoAddressForm(element, 0);
+ expect(address1.street).toBe('123 Main');
+ expect(address1.state).toBe('CA');
+ expect(address1.zip).toBe('94801');
+ expect(address1.city).toBe('Anywhere');
+ let address2 = finalDemoAddressForm(element, 1);
+ expect(address2.street).toBe('456 Maple');
+ expect(address2.state).toBe('VA');
+ expect(address2.zip).toBe('23226');
+ expect(address2.city).toBe('Somewhere');
+ });
+
+ it('shows a json output from the form', function() {
+ let json = element(by.css('hero-detail > p'));
+ expect(json.getText()).toContain('Whirlwind');
+ expect(json.getText()).toContain('Anywhere');
+ expect(json.getText()).toContain('Somewhere');
+ expect(json.getText()).toContain('VA');
+ });
+
+ it('has two disabled buttons by default', function() {
+ let buttons = element.all(by.css('hero-detail > form > div > button'));
+ expect(buttons.get(0).getAttribute('disabled')).toBe('true');
+ expect(buttons.get(1).getAttribute('disabled')).toBe('true');
+ });
+
+ it('enables the buttons after we edit the form', function() {
+ let nameInput = element(by.css('input[formcontrolname=name]'));
+ nameInput.sendKeys('a');
+ let buttons = element.all(by.css('hero-detail > form > div > button'));
+ expect(buttons.get(0).getAttribute('disabled')).toBeNull();
+ expect(buttons.get(1).getAttribute('disabled')).toBeNull();
+ });
+
+ it('saves the changes when the save button is clicked', function() {
+ let nameInput = element(by.css('input[formcontrolname=name]'));
+ nameInput.sendKeys('a');
+ let save = element.all(by.css('hero-detail > form > div > button')).get(0);
+ save.click();
+ let editMessage = element(by.css('hero-list > div > h3'));
+ expect(editMessage.getText()).toBe('Editing: Whirlwinda');
+ });
+
+ it('reverts the changes when the revert button is clicked', function() {
+ let nameInput = element(by.css('input[formcontrolname=name]'));
+ nameInput.sendKeys('a');
+ let revert = element.all(by.css('hero-detail > form > div > button')).get(1);
+ revert.click();
+ let editMessage = element(by.css('hero-list > div > h3'));
+ expect(editMessage.getText()).toBe('Editing: Whirlwind');
+ expect(nameInput.getAttribute('value')).toBe('Whirlwind');
+ });
+
+ it('is able to add a new empty address', function() {
+ let newLairButton = element.all(by.css('button')).get(3);
+ newLairButton.click();
+ let address3 = finalDemoAddressForm(element, 2);
+ expect(address3.street).toBe('');
+ expect(address3.state).toBe('');
+ expect(address3.zip).toBe('');
+ expect(address3.city).toBe('');
+ });
+
+ it('should show three radio buttons', function() {
+ let radioButtons = element.all(by.css('input[formcontrolname=power]'));
+ expect(radioButtons.get(0).getAttribute('value')).toBe('flight');
+ expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision');
+ expect(radioButtons.get(2).getAttribute('value')).toBe('strength');
+ });
+
+ it('should show a checkbox', function() {
+ let checkbox = element(by.css('input[formcontrolname=sidekick]'));
+ expect(checkbox.getAttribute('checked')).toBe(null);
+ });
+ });
+
+ describe('Bombastic form', function() {
+ beforeEach(function() {
+ let bombastaButton = element.all(by.css('nav a')).get(1);
+ bombastaButton.click();
+ });
+
+ it('should show a hero information when the button is clicked', function() {
+ let editMessage = element(by.css('hero-list > div > h3'));
+ expect(editMessage.getText()).toBe('Editing: Bombastic');
+ });
+
+ it('should show a form with the selected hero information', function() {
+ let nameInput = element(by.css('input[formcontrolname=name]'));
+ expect(nameInput.getAttribute('value')).toBe('Bombastic');
+ let address1 = finalDemoAddressForm(element, 0);
+ expect(address1.street).toBe('789 Elm');
+ // expect(address1.state).toBe('OH');
+ expect(address1.zip).toBe('04501');
+ expect(address1.city).toBe('Smallville');
+ });
+
+ it('shows a json output from the form', function() {
+ let json = element(by.css('hero-detail > p'));
+ expect(json.getText()).toContain('Bombastic');
+ expect(json.getText()).toContain('Smallville');
+ expect(json.getText()).toContain('OH');
+ expect(json.getText()).toContain('04501');
+ });
+
+ it('has two disabled buttons by default', function() {
+ let buttons = element.all(by.css('hero-detail > form > div > button'));
+ expect(buttons.get(0).getAttribute('disabled')).toBe('true');
+ expect(buttons.get(1).getAttribute('disabled')).toBe('true');
+ });
+
+ it('enables the buttons after we edit the form', function() {
+ let nameInput = element(by.css('input[formcontrolname=name]'));
+ nameInput.sendKeys('a');
+ let buttons = element.all(by.css('hero-detail > form > div > button'));
+ expect(buttons.get(0).getAttribute('disabled')).toBeNull();
+ expect(buttons.get(1).getAttribute('disabled')).toBeNull();
+ });
+
+ it('saves the changes when the save button is clicked', function() {
+ let nameInput = element(by.css('input[formcontrolname=name]'));
+ nameInput.sendKeys('a');
+ let save = element.all(by.css('hero-detail > form > div > button')).get(0);
+ save.click();
+ let editMessage = element(by.css('hero-list > div > h3'));
+ expect(editMessage.getText()).toBe('Editing: Bombastica');
+ });
+
+ it('reverts the changes when the revert button is clicked', function() {
+ let nameInput = element(by.css('input[formcontrolname=name]'));
+ nameInput.sendKeys('a');
+ let revert = element.all(by.css('hero-detail > form > div > button')).get(1);
+ revert.click();
+ let editMessage = element(by.css('hero-list > div > h3'));
+ expect(editMessage.getText()).toBe('Editing: Bombastic');
+ expect(nameInput.getAttribute('value')).toBe('Bombastic');
+ });
+
+ it('is able to add a new empty address', function() {
+ let newLairButton = element.all(by.css('button')).get(3);
+ newLairButton.click();
+ let address2 = finalDemoAddressForm(element, 1);
+ expect(address2.street).toBe('');
+ expect(address2.state).toBe('');
+ expect(address2.zip).toBe('');
+ expect(address2.city).toBe('');
+ });
+
+ it('should show three radio buttons', function() {
+ let radioButtons = element.all(by.css('input[formcontrolname=power]'));
+ expect(radioButtons.get(0).getAttribute('value')).toBe('flight');
+ expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision');
+ expect(radioButtons.get(2).getAttribute('value')).toBe('strength');
+ });
+
+ it('should show a checbox', function() {
+ let checkbox = element(by.css('input[formcontrolname=sidekick]'));
+ expect(checkbox.getAttribute('checked')).toBe(null);
+ });
+ });
+
+ describe('Magneta form', function() {
+
+ beforeEach(function() {
+ let magnetaButton = element.all(by.css('nav a')).get(2);
+ magnetaButton.click();
+ });
+
+ it('should show hero information when the button is clicked', function() {
+ let editMessage = element(by.css('hero-list > div > h3'));
+ expect(editMessage.getText()).toBe('Editing: Magneta');
+ });
+
+ it('should show a form with the selected hero information', function() {
+ let nameInput = element(by.css('input[formcontrolname=name]'));
+ expect(nameInput.getAttribute('value')).toBe('Magneta');
+ });
+
+ it('shows a json output from the form', function() {
+ let json = element(by.css('hero-detail > p'));
+ expect(json.getText()).toContain('Magneta');
+ });
+
+ it('has two disabled buttons by default', function() {
+ let buttons = element.all(by.css('hero-detail > form > div > button'));
+ expect(buttons.get(0).getAttribute('disabled')).toBe('true');
+ expect(buttons.get(1).getAttribute('disabled')).toBe('true');
+ });
+
+ it('enables the buttons after we edit the form', function() {
+ let nameInput = element(by.css('input[formcontrolname=name]'));
+ nameInput.sendKeys('a');
+ let buttons = element.all(by.css('hero-detail > form > div > button'));
+ expect(buttons.get(0).getAttribute('disabled')).toBeNull();
+ expect(buttons.get(1).getAttribute('disabled')).toBeNull();
+ });
+
+ it('saves the changes when the save button is clicked', function() {
+ let nameInput = element(by.css('input[formcontrolname=name]'));
+ nameInput.sendKeys('a');
+ let save = element.all(by.css('hero-detail > form > div > button')).get(0);
+ save.click();
+ let editMessage = element(by.css('hero-list > div > h3'));
+ expect(editMessage.getText()).toBe('Editing: Magnetaa');
+ });
+
+ it('reverts the changes when the revert button is clicked', function() {
+ let nameInput = element(by.css('input[formcontrolname=name]'));
+ nameInput.sendKeys('a');
+ let revert = element.all(by.css('hero-detail > form > div > button')).get(1);
+ revert.click();
+ let editMessage = element(by.css('hero-list > div > h3'));
+ expect(editMessage.getText()).toBe('Editing: Magneta');
+ expect(nameInput.getAttribute('value')).toBe('Magneta');
+ });
+
+ it('is able to add a new empty address', function() {
+ let newLairButton = element.all(by.css('button')).get(3);
+ newLairButton.click();
+ let address = finalDemoAddressForm(element, 0);
+ expect(address.street).toBe('');
+ expect(address.state).toBe('');
+ expect(address.zip).toBe('');
+ expect(address.city).toBe('');
+ });
+
+ it('should show three radio buttons', function() {
+ let radioButtons = element.all(by.css('input[formcontrolname=power]'));
+ expect(radioButtons.get(0).getAttribute('value')).toBe('flight');
+ expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision');
+ expect(radioButtons.get(2).getAttribute('value')).toBe('strength');
+ });
+
+ it('should show a checkbox', function() {
+ let checkbox = element(by.css('input[formcontrolname=sidekick]'));
+ expect(checkbox.getAttribute('checked')).toBe(null);
+ });
+ });
+ }); // final demo
+
+// *************Begin FormArray Demo test*******************************
+
+
+ describe('formArray demo', function() {
+ beforeEach(function() {
+ let FormArrayOption = element.all(by.css('select option')).get(7);
+ FormArrayOption.click();
+ });
+
+ it('should show FormArray Demo', function() {
+ select.getAttribute('value').then(function(demo: string) {
+ expect(demo).toBe('FormArray Demo');
+ });
+ });
+
+ it('does not select any hero by default', function() {
+ let heroSection = element(by.css('hero-list > div'));
+ expect(heroSection.isPresent()).toBe(false);
+ });
+
+ it('refreshes the page upon button click', function() {
+ // We move to another page...
+ let whirlwindButton = element.all(by.css('nav a')).get(0);
+ whirlwindButton.click();
+ let refresh = element(by.css('button'));
+ refresh.click();
+ let heroSection = element(by.css('hero-list > div'));
+ expect(heroSection.isPresent()).toBe(false);
+ });
+
+ describe('Whirlwind form', function() {
+ beforeEach(function() {
+ let whirlwindButton = element.all(by.css('nav a')).get(0);
+ whirlwindButton.click();
+ });
+
+ it('should show hero information when the button is clicked', function() {
+ let editMessage = element(by.css('div.demo > div > div > h3'));
+ expect(editMessage.getText()).toBe('Editing: Whirlwind');
+ });
+
+ it('should show a form with the selected hero information', function() {
+ let nameInput = element(by.css('input[formcontrolname=name]'));
+ expect(nameInput.getAttribute('value')).toBe('Whirlwind');
+ let address1 = finalDemoAddressForm(element, 0);
+ expect(address1.street).toBe('123 Main');
+ expect(address1.state).toBe('CA');
+ expect(address1.zip).toBe('94801');
+ expect(address1.city).toBe('Anywhere');
+ let address2 = finalDemoAddressForm(element, 1);
+ expect(address2.street).toBe('456 Maple');
+ expect(address2.state).toBe('VA');
+ expect(address2.zip).toBe('23226');
+ expect(address2.city).toBe('Somewhere');
+ });
+ it('shows a json output from the form', function() {
+ let json = element(by.css('hero-detail-8 > p'));
+ expect(json.getText()).toContain('Whirlwind');
+ expect(json.getText()).toContain('Anywhere');
+ expect(json.getText()).toContain('Somewhere');
+ expect(json.getText()).toContain('VA');
+ });
+
+ it('is able to add a new empty address', function() {
+ let newLairButton = element.all(by.css('button')).get(1);
+ newLairButton.click();
+ let address2 = finalDemoAddressForm(element, 2);
+ expect(address2.street).toBe('');
+ expect(address2.state).toBe('');
+ expect(address2.zip).toBe('');
+ expect(address2.city).toBe('');
+ });
+
+ it('should show three radio buttons', function() {
+ let radioButtons = element.all(by.css('input[formcontrolname=power]'));
+ expect(radioButtons.get(0).getAttribute('value')).toBe('flight');
+ expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision');
+ expect(radioButtons.get(2).getAttribute('value')).toBe('strength');
+ });
+
+ it('should show a checkbox', function() {
+ let checkbox = element(by.css('input[formcontrolname=sidekick]'));
+ expect(checkbox.getAttribute('checked')).toBe(null);
+ });
+
+ }); // Whirlwind form
+
+ describe('Bombastic FormArray form', function() {
+ beforeEach(function() {
+ let bombasticButton = element.all(by.css('nav a')).get(1);
+ bombasticButton.click();
+ });
+
+ it('should show a hero information when the button is clicked', function() {
+ let editMessage = element(by.css('div.demo > div > div > h3'));
+ expect(editMessage.getText()).toBe('Editing: Bombastic');
+ });
+
+ it('should show a form with the selected hero information', function() {
+ let nameInput = element(by.css('input[formcontrolname=name]'));
+ // nameInput.getAttribute('value').then(function(name: string) {
+ // expect(name).toBe('Whirlwind');
+ // });
+ expect(nameInput.getAttribute('value')).toBe('Bombastic');
+ let address1 = finalDemoAddressForm(element, 0);
+ expect(address1.street).toBe('789 Elm');
+ // expect(address1.state).toBe('OH');
+ // This select should be OH not CA, which it shows in the UI, the JSON shows OH.
+ expect(address1.zip).toBe('04501');
+ expect(address1.city).toBe('Smallville');
+ });
+
+ it('shows a json output from the form', function() {
+ let json = element(by.css('hero-detail-8 > p'));
+ expect(json.getText()).toContain('Bombastic');
+ expect(json.getText()).toContain('Smallville');
+ expect(json.getText()).toContain('04501');
+ expect(json.getText()).toContain('789 Elm');
+ });
+
+ it('is able to add a new empty address', function() {
+ let newLairButton = element.all(by.css('button')).get(1);
+ newLairButton.click();
+ let address1 = finalDemoAddressForm(element, 1);
+ expect(address1.street).toBe('');
+ expect(address1.state).toBe('');
+ expect(address1.zip).toBe('');
+ expect(address1.city).toBe('');
+ });
+
+ it('should show three radio buttons', function() {
+ let radioButtons = element.all(by.css('input[formcontrolname=power]'));
+ expect(radioButtons.get(0).getAttribute('value')).toBe('flight');
+ expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision');
+ expect(radioButtons.get(2).getAttribute('value')).toBe('strength');
+ });
+
+ it('should show a checkbox', function() {
+ let checkbox = element(by.css('input[formcontrolname=sidekick]'));
+ expect(checkbox.getAttribute('checked')).toBe(null);
+ });
+
+ }); // Bombastic FormArray form
+
+ describe('Magneta FormArray form', function() {
+ beforeEach(function() {
+ let magnetaButton = element.all(by.css('nav a')).get(2);
+ magnetaButton.click();
+ });
+
+ it('should show a hero information when the button is clicked', function() {
+ let editMessage = element(by.css('div.demo > div > div > h3'));
+ expect(editMessage.getText()).toBe('Editing: Magneta');
+ });
+
+ it('should show a form with the selected hero information', function() {
+ let nameInput = element(by.css('input[formcontrolname=name]'));
+ expect(nameInput.getAttribute('value')).toBe('Magneta');
+ });
+
+ it('shows a json output from the form', function() {
+ let json = element(by.css('hero-detail-8 > p'));
+ expect(json.getText()).toContain('Magneta');
+ });
+
+ it('is able to add a new empty address', function() {
+ let newLairButton = element.all(by.css('button')).get(1);
+ newLairButton.click();
+ let address1 = finalDemoAddressForm(element, 0);
+ expect(address1.street).toBe('');
+ expect(address1.state).toBe('');
+ expect(address1.zip).toBe('');
+ expect(address1.city).toBe('');
+ });
+
+ it('should show three radio buttons', function() {
+ let radioButtons = element.all(by.css('input[formcontrolname=power]'));
+ expect(radioButtons.get(0).getAttribute('value')).toBe('flight');
+ expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision');
+ expect(radioButtons.get(2).getAttribute('value')).toBe('strength');
+ });
+
+ it('should show a checkbox', function() {
+ let checkbox = element(by.css('input[formcontrolname=sidekick]'));
+ expect(checkbox.getAttribute('checked')).toBe(null);
+ });
+
+ }); // Magneta FormArray form
+
+ }); // formArray demo
+
+
+// *************Begin SetValue Demo test*******************************
+
+ describe('SetValue demo', function() {
+ beforeEach(function() {
+ let SetValueOption = element.all(by.css('select option')).get(6);
+ SetValueOption.click();
+ });
+
+ it('should show SetValue Demo', function() {
+ select.getAttribute('value').then(function(demo: string) {
+ expect(demo).toBe('SetValue Demo');
+ });
+ });
+
+ it('does not select any hero by default', function() {
+ let heroSection = element(by.css('hero-list > div'));
+ expect(heroSection.isPresent()).toBe(false);
+ });
+
+ it('refreshes the page upon button click', function() {
+ // We move to another page...
+ let whirlwindButton = element.all(by.css('nav a')).get(0);
+ whirlwindButton.click();
+ let refresh = element(by.css('button'));
+ refresh.click();
+ let heroSection = element(by.css('hero-list > div'));
+ expect(heroSection.isPresent()).toBe(false);
+ });
+
+ describe('Whirlwind setValue form', function() {
+ beforeEach(function() {
+ let whirlwindButton = element.all(by.css('nav a')).get(0);
+ whirlwindButton.click();
+ });
+
+ it('should show a hero information when the button is clicked', function() {
+ let editMessage = element(by.css('.demo > div > div > h3'));
+ expect(editMessage.getText()).toBe('Editing: Whirlwind');
+ });
+
+ it('should show a form with the selected hero information', function() {
+ let nameInput = element(by.css('input[formcontrolname=name]'));
+ expect(nameInput.getAttribute('value')).toBe('Whirlwind');
+ let address1 = finalDemoAddressForm(element, 0);
+ expect(address1.street).toBe('123 Main');
+ expect(address1.state).toBe('CA');
+ expect(address1.zip).toBe('94801');
+ expect(address1.city).toBe('Anywhere');
+ });
+
+ it('shows a json output from the form', function() {
+ let json = element(by.css('hero-detail-7 > p'));
+ expect(json.getText()).toContain('Whirlwind');
+ expect(json.getText()).toContain('Anywhere');
+ let nameOutput = element(by.css('hero-detail-7 > p ~ p'));
+ expect(nameOutput.getText()).toContain('Name value: Whirlwind');
+ let streetOutput = element(by.css('hero-detail-7 > p ~ p ~ p'));
+ expect(streetOutput.getText()).toContain('Street value: 123 Main');
+ });
+
+ it('should show three radio buttons', function() {
+ let radioButtons = element.all(by.css('input[formcontrolname=power]'));
+ expect(radioButtons.get(0).getAttribute('value')).toBe('flight');
+ expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision');
+ expect(radioButtons.get(2).getAttribute('value')).toBe('strength');
+ });
+
+ it('should show a checkbox', function() {
+ let checkbox = element(by.css('input[formcontrolname=sidekick]'));
+ expect(checkbox.getAttribute('checked')).toBe(null);
+ });
+
+ }); // Whirlwind setValue form
+
+ describe('Bombastic setValue form', function() {
+ beforeEach(function() {
+ let bombasticButton = element.all(by.css('nav a')).get(1);
+ bombasticButton.click();
+ });
+
+ it('should show a hero information when the button is clicked', function() {
+ let editMessage = element(by.css('.demo > div > div > h3'));
+ expect(editMessage.getText()).toBe('Editing: Bombastic');
+ });
+
+ it('should show a form with the selected hero information', function() {
+ let nameInput = element(by.css('input[formcontrolname=name]'));
+ expect(nameInput.getAttribute('value')).toBe('Bombastic');
+ let address1 = finalDemoAddressForm(element, 0);
+ expect(address1.street).toBe('789 Elm');
+ expect(address1.state).toBe('OH');
+ expect(address1.zip).toBe('04501');
+ expect(address1.city).toBe('Smallville');
+ });
+
+ it('shows a json output from the form', function() {
+ let json = element(by.css('hero-detail-7 > p'));
+ expect(json.getText()).toContain('Bombastic');
+ expect(json.getText()).toContain('Smallville');
+ expect(json.getText()).toContain('04501');
+ expect(json.getText()).toContain('789 Elm');
+ let nameOutput = element(by.css('hero-detail-7 > p ~ p'));
+ expect(nameOutput.getText()).toContain('Name value: Bombastic');
+ let streetOutput = element(by.css('hero-detail-7 > p ~ p ~ p'));
+ expect(streetOutput.getText()).toContain('Street value: 789 Elm');
+ });
+
+ it('should show three radio buttons', function() {
+ let radioButtons = element.all(by.css('input[formcontrolname=power]'));
+ expect(radioButtons.get(0).getAttribute('value')).toBe('flight');
+ expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision');
+ expect(radioButtons.get(2).getAttribute('value')).toBe('strength');
+ });
+
+ it('should show a checkbox', function() {
+ let checkbox = element(by.css('input[formcontrolname=sidekick]'));
+ expect(checkbox.getAttribute('checked')).toBe(null);
+ });
+
+ }); // Bombastic setValue form
+
+ describe('Magneta setValue form', function() {
+ beforeEach(function() {
+ let magnetaButton = element.all(by.css('nav a')).get(2);
+ magnetaButton.click();
+ });
+
+ it('should show a hero information when the button is clicked', function() {
+ let editMessage = element(by.css('.demo > div > div > h3'));
+ expect(editMessage.getText()).toBe('Editing: Magneta');
+ });
+
+ it('should show a form with the selected hero information', function() {
+ let nameInput = element(by.css('input[formcontrolname=name]'));
+ expect(nameInput.getAttribute('value')).toBe('Magneta');
+ });
+
+ it('should show three radio buttons', function() {
+ let radioButtons = element.all(by.css('input[formcontrolname=power]'));
+ expect(radioButtons.get(0).getAttribute('value')).toBe('flight');
+ expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision');
+ expect(radioButtons.get(2).getAttribute('value')).toBe('strength');
+ });
+
+ it('should show a checkbox', function() {
+ let checkbox = element(by.css('input[formcontrolname=sidekick]'));
+ expect(checkbox.getAttribute('checked')).toBe(null);
+ });
+
+ it('shows a json output from the form', function() {
+ let json = element(by.css('hero-detail-7 > p'));
+ expect(json.getText()).toContain('Magneta');
+ let nameOutput = element(by.css('hero-detail-7 > p ~ p'));
+ expect(nameOutput.getText()).toContain('Name value: Magneta');
+ let streetOutput = element(by.css('hero-detail-7 > p ~ p ~ p'));
+ expect(streetOutput.getText()).toContain('Street value:');
+ });
+
+ }); // Magneta setValue form
+ }); // SetValue demo
+
+// *************Begin patchValue Demo test*******************************
+
+ describe('patchValue demo', function() {
+ beforeEach(function() {
+ let SetValueOption = element.all(by.css('select option')).get(5);
+ SetValueOption.click();
+ });
+
+ it('should show patchValue Demo', function() {
+ select.getAttribute('value').then(function(demo: string) {
+ expect(demo).toBe('PatchValue Demo');
+ });
+ });
+
+ it('does not select any hero by default', function() {
+ let heroSection = element(by.css('.demo > div > div'));
+ expect(heroSection.isPresent()).toBe(false);
+ });
+
+ it('refreshes the page upon button click', function() {
+ // We move to another page...
+ let whirlwindButton = element.all(by.css('nav a')).get(0);
+ whirlwindButton.click();
+ let refresh = element(by.css('button'));
+ refresh.click();
+ let heroSection = element(by.css('.demo > div > div'));
+ expect(heroSection.isPresent()).toBe(false);
+ });
+
+ describe('Whirlwind patchValue form', function() {
+ beforeEach(function() {
+ let whirlwindButton = element.all(by.css('nav a')).get(0);
+ whirlwindButton.click();
+ });
+
+ it('should show a hero information when the button is clicked', function() {
+ let editMessage = element(by.css('h2 ~ h3'));
+ expect(editMessage.getText()).toBe('Editing: Whirlwind');
+ });
+
+ it('should show a form with the selected hero information', function() {
+ let nameInput = element(by.css('input[formcontrolname=name]'));
+ expect(nameInput.getAttribute('value')).toBe('Whirlwind');
+ let address1 = finalDemoAddressForm(element, 0);
+ expect(address1.street).toBe('');
+ expect(address1.state).toBe('');
+ expect(address1.zip).toBe('');
+ expect(address1.city).toBe('');
+ });
+
+ it('should show three radio buttons', function() {
+ let radioButtons = element.all(by.css('input[formcontrolname=power]'));
+ expect(radioButtons.get(0).getAttribute('value')).toBe('flight');
+ expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision');
+ expect(radioButtons.get(2).getAttribute('value')).toBe('strength');
+ });
+
+ it('should show a checkbox', function() {
+ let checkbox = element(by.css('input[formcontrolname=sidekick]'));
+ expect(checkbox.getAttribute('checked')).toBe(null);
+ });
+
+ it('shows a json output from the form', function() {
+ let json = element(by.css('hero-detail-6 > p'));
+ expect(json.getText()).toContain('Whirlwind');
+ let nameOutput = element(by.css('hero-detail-6 > p ~ p'));
+ expect(nameOutput.getText()).toContain('Name value: Whirlwind');
+ let streetOutput = element(by.css('hero-detail-6 > p ~ p ~ p'));
+ expect(streetOutput.getText()).toContain('Street value:');
+ });
+
+
+ }); // Bombastic patchValue form
+ describe('Bombastic patchValue form', function() {
+ beforeEach(function() {
+ let bombasticButton = element.all(by.css('nav a')).get(1);
+ bombasticButton.click();
+ });
+
+ it('should show a hero information when the button is clicked', function() {
+ let editMessage = element(by.css('h2 ~ h3'));
+ expect(editMessage.getText()).toBe('Editing: Bombastic');
+ });
+
+ it('should show a form with the selected hero information', function() {
+ let nameInput = element(by.css('input[formcontrolname=name]'));
+ expect(nameInput.getAttribute('value')).toBe('Bombastic');
+ let address1 = finalDemoAddressForm(element, 0);
+ expect(address1.street).toBe('');
+ expect(address1.state).toBe('');
+ expect(address1.zip).toBe('');
+ expect(address1.city).toBe('');
+ });
+
+ it('should show three radio buttons', function() {
+ let radioButtons = element.all(by.css('input[formcontrolname=power]'));
+ expect(radioButtons.get(0).getAttribute('value')).toBe('flight');
+ expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision');
+ expect(radioButtons.get(2).getAttribute('value')).toBe('strength');
+ });
+
+ it('should show a checkbox', function() {
+ let checkbox = element(by.css('input[formcontrolname=sidekick]'));
+ expect(checkbox.getAttribute('checked')).toBe(null);
+ });
+
+ it('shows a json output from the form', function() {
+ let json = element(by.css('hero-detail-6 > p'));
+ expect(json.getText()).toContain('Bombastic');
+ let nameOutput = element(by.css('hero-detail-6 > p ~ p'));
+ expect(nameOutput.getText()).toContain('Name value: Bombastic');
+ let streetOutput = element(by.css('hero-detail-6 > p ~ p ~ p'));
+ expect(streetOutput.getText()).toContain('Street value:');
+ });
+ }); // Bombastic patchValue form
+
+ describe('Magneta patchValue form', function() {
+ beforeEach(function() {
+ let magnetaButton = element.all(by.css('nav a')).get(2);
+ magnetaButton.click();
+ });
+
+ it('should show a hero information when the button is clicked', function() {
+ let editMessage = element(by.css('h2 ~ h3'));
+ expect(editMessage.getText()).toBe('Editing: Magneta');
+ });
+
+ it('should show a form with the selected hero information', function() {
+ let nameInput = element(by.css('input[formcontrolname=name]'));
+ expect(nameInput.getAttribute('value')).toBe('Magneta');
+ let address1 = finalDemoAddressForm(element, 0);
+ expect(address1.street).toBe('');
+ expect(address1.state).toBe('');
+ expect(address1.zip).toBe('');
+ expect(address1.city).toBe('');
+ });
+
+ it('should show three radio buttons', function() {
+ let radioButtons = element.all(by.css('input[formcontrolname=power]'));
+ expect(radioButtons.get(0).getAttribute('value')).toBe('flight');
+ expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision');
+ expect(radioButtons.get(2).getAttribute('value')).toBe('strength');
+ });
+
+ it('should show a checkbox', function() {
+ let checkbox = element(by.css('input[formcontrolname=sidekick]'));
+ expect(checkbox.getAttribute('checked')).toBe(null);
+ });
+
+ it('shows a json output from the form', function() {
+ let json = element(by.css('hero-detail-6 > p'));
+ expect(json.getText()).toContain('Magneta');
+ let nameOutput = element(by.css('hero-detail-6 > p ~ p'));
+ expect(nameOutput.getText()).toContain('Name value: Magneta');
+ let streetOutput = element(by.css('hero-detail-6 > p ~ p ~ p'));
+ expect(streetOutput.getText()).toContain('Street value:');
+ });
+
+ }); // Magneta patchValue form
+ }); // PatchValue demo
+
+
+
+// *************Begin Nested FormBuilder Demo test*******************************
+
+ describe('Nested FormBuilder demo', function() {
+ beforeEach(function() {
+ let NestedFormBuilderOption = element.all(by.css('select option')).get(4);
+ NestedFormBuilderOption.click();
+ });
+
+ it('should show Nested FormBuilder Demo', function() {
+ select.getAttribute('value').then(function(demo: string) {
+ expect(demo).toBe('Nested FormBuilder group Demo');
+ });
+ });
+
+ it('should show a form for hero information', function() {
+ let nameInput = element(by.css('input[formcontrolname=name]'));
+ expect(nameInput.getAttribute('value')).toBe('');
+ let address1 = finalDemoAddressForm(element, 0);
+ expect(address1.street).toBe('');
+ expect(address1.state).toBe('');
+ expect(address1.zip).toBe('');
+ expect(address1.city).toBe('');
+ });
+
+ it('should show three radio buttons', function() {
+ let radioButtons = element.all(by.css('input[formcontrolname=power]'));
+ expect(radioButtons.get(0).getAttribute('value')).toBe('flight');
+ expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision');
+ expect(radioButtons.get(2).getAttribute('value')).toBe('strength');
+ });
+
+ it('should show a checkbox', function() {
+ let checkbox = element(by.css('input[formcontrolname=sidekick]'));
+ expect(checkbox.getAttribute('checked')).toBe(null);
+ });
+
+ it('shows a json output from the form', function() {
+ let json = element(by.css('hero-detail-5 > p'));
+ expect(json.getText()).toContain('address');
+ let nameOutput = element(by.css('hero-detail-5 > p ~ p'));
+ expect(nameOutput.getText()).toContain('Name value:');
+ let streetOutput = element(by.css('hero-detail-5 > p ~ p ~ p'));
+ expect(streetOutput.getText()).toContain('Street value:');
+ });
+
+ }); // Nested FormBuilder demo
+
+// *************Begin Group with multiple controls Demo test*******************************
+
+ describe('Group with multiple controls demo', function() {
+ beforeEach(function() {
+ let NestedFormBuilderOption = element.all(by.css('select option')).get(3);
+ NestedFormBuilderOption.click();
+ });
+
+ it('should show Group with multiple controls Demo', function() {
+ select.getAttribute('value').then(function(demo: string) {
+ expect(demo).toBe('Group with multiple controls Demo');
+ });
+ });
+
+ it('should show header', function() {
+ let header = element(by.css('hero-detail-4 > h3'));
+ expect(header.getText()).toBe('A FormGroup with multiple FormControls');
+ });
+
+ it('should show a form for hero information', function() {
+ let nameInput = element(by.css('input[formcontrolname=name]'));
+ expect(nameInput.getAttribute('value')).toBe('');
+ let address1 = finalDemoAddressForm(element, 0);
+ expect(address1.street).toBe('');
+ expect(address1.state).toBe('');
+ expect(address1.zip).toBe('');
+ expect(address1.city).toBe('');
+ });
+
+ it('should show three radio buttons', function() {
+ let radioButtons = element.all(by.css('input[formcontrolname=power]'));
+ expect(radioButtons.get(0).getAttribute('value')).toBe('flight');
+ expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision');
+ expect(radioButtons.get(2).getAttribute('value')).toBe('strength');
+ });
+ it('should show a checkbox', function() {
+ let checkbox = element(by.css('input[formcontrolname=sidekick]'));
+ expect(checkbox.getAttribute('checked')).toBe(null);
+ });
+ it('shows a json output from the form', function() {
+ let json = element(by.css('hero-detail-4 > p'));
+ expect(json.getText()).toContain('power');
+ });
+
+}); // Group with multiple controls demo
+
+
+
+// *************Begin Group with multiple controls Demo test*******************************
+
+ describe('Simple FormBuilder Group demo', function() {
+ beforeEach(function() {
+ let SimpleFormBuilderOption = element.all(by.css('select option')).get(2);
+ SimpleFormBuilderOption.click();
+ });
+
+ it('should show Simple FormBuilder group Demo', function() {
+ select.getAttribute('value').then(function(demo: string) {
+ expect(demo).toBe('Simple FormBuilder group Demo');
+ });
+ });
+
+ it('should show header', function() {
+ let header = element(by.css('hero-detail-3 > h3'));
+ expect(header.getText()).toBe('A FormGroup with a single FormControl using FormBuilder');
+ });
+
+ it('should show a form for hero information', function() {
+ let nameInput = element(by.css('input[formcontrolname=name]'));
+ expect(nameInput.getAttribute('value')).toBe('');
+ });
+
+ it('shows a json output from the form', function() {
+ let json = element(by.css('hero-detail-3 > p'));
+ expect(json.getText()).toContain('name');
+ let validStatus = element(by.css('hero-detail-3 > p ~ p'));
+ expect(validStatus.getText()).toContain('INVALID');
+ });
+
+}); // Group with multiple controls demo
+
+
+// *************Begin FormControl in a FormGroup Demo test*******************************
+
+ describe('FormControl in a FormGroup demo', function() {
+ beforeEach(function() {
+ let SimpleFormBuilderOption = element.all(by.css('select option')).get(1);
+ SimpleFormBuilderOption.click();
+ });
+
+ it('should show FormControl in a FormGroup Demo', function() {
+ select.getAttribute('value').then(function(demo: string) {
+ expect(demo).toBe('FormControl in a FormGroup Demo');
+ });
+ });
+
+ it('should show header', function() {
+ let header = element(by.css('hero-detail-2 > h3'));
+ expect(header.getText()).toBe('FormControl in a FormGroup');
+ });
+
+ it('should show a form for hero information', function() {
+ let nameInput = element(by.css('input[formcontrolname=name]'));
+ expect(nameInput.getAttribute('value')).toBe('');
+ });
+
+ it('shows a json output from the form', function() {
+ let json = element(by.css('hero-detail-2 > p'));
+ expect(json.getText()).toContain('name');
+ });
+
+}); // Group with multiple controls demo
+
+// *************Begin Just A FormControl Demo test*******************************
+
+ describe('Just a FormControl demo', function() {
+ beforeEach(function() {
+ let FormControlOption = element.all(by.css('select option')).get(0);
+ FormControlOption.click();
+ });
+
+ it('should show Just a FormControl demo', function() {
+ select.getAttribute('value').then(function(demo: string) {
+ expect(demo).toBe('Just a FormControl Demo');
+ });
+ });
+
+ it('should show header', function() {
+ let header = element(by.css('hero-detail-1 > h3'));
+ expect(header.getText()).toBe('Just a FormControl');
+ });
+
+ it('should show a form for hero information', function() {
+ let nameInput = element(by.css('input'));
+ expect(nameInput.getAttribute('value')).toBe('');
+ });
+
+ }); // Just a FormControl demo test
+
+
+}); // reactive forms
diff --git a/public/docs/_examples/reactive-forms/ts/example-config.json b/public/docs/_examples/reactive-forms/ts/example-config.json
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/public/docs/_examples/reactive-forms/ts/final.plnkr.json b/public/docs/_examples/reactive-forms/ts/final.plnkr.json
new file mode 100644
index 0000000000..41481acc99
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/final.plnkr.json
@@ -0,0 +1,21 @@
+{
+ "description": "Angular Reactive Forms (final)",
+ "basePath": "src/",
+ "files":[
+ "styles.css",
+
+ "app/app.component.ts",
+ "app/app.module.ts",
+ "app/data-model.ts",
+ "app/hero.service.ts",
+ "app/hero-detail.component.html",
+ "app/hero-detail.component.ts",
+ "app/hero-list.component.html",
+ "app/hero-list.component.ts",
+
+ "main-final.ts",
+ "index-final.html"
+ ],
+ "main": "index-final.html",
+ "tags": ["reactive", "forms"]
+}
diff --git a/public/docs/_examples/reactive-forms/ts/plnkr.json b/public/docs/_examples/reactive-forms/ts/plnkr.json
new file mode 100644
index 0000000000..f0daeb4aad
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/plnkr.json
@@ -0,0 +1,15 @@
+{
+ "description": "Angular Reactive Forms (Demo runner)",
+ "basePath": "src/",
+ "files":[
+ "!**/*.d.ts",
+ "!**/*.js",
+
+ "!app/app.component.1.ts",
+ "!app/hero-list.component.1.html",
+
+ "!app/main-final.ts",
+ "!index-final.html"
+ ],
+ "tags": ["reactive", "forms"]
+}
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/app.component.1.ts b/public/docs/_examples/reactive-forms/ts/src/app/app.component.1.ts
new file mode 100644
index 0000000000..3023618334
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/app.component.1.ts
@@ -0,0 +1,12 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ template: `
+
+
Reactive Forms
+
+
`
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/app.component.ts b/public/docs/_examples/reactive-forms/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..d30a38e979
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/app.component.ts
@@ -0,0 +1,12 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ template: `
+
+
Reactive Forms
+
+ `
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/app.module.ts b/public/docs/_examples/reactive-forms/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..b9f2ea8f99
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/app.module.ts
@@ -0,0 +1,39 @@
+// #docplaster
+// #docregion
+// #docregion v1
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { ReactiveFormsModule } from '@angular/forms'; // <-- #1 import module
+
+import { AppComponent } from './app.component';
+import { HeroDetailComponent } from './hero-detail.component'; // <-- #1 import component
+// #enddocregion v1
+import { HeroListComponent } from './hero-list.component';
+
+import { HeroService } from './hero.service'; // <-- #1 import service
+// #docregion v1
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ ReactiveFormsModule // <-- #2 add to Angular module imports
+ ],
+ declarations: [
+ AppComponent,
+ HeroDetailComponent, // <-- #3 declare app component
+// #enddocregion v1
+ HeroListComponent
+// #docregion v1
+ ],
+// #enddocregion v1
+ exports: [ // export for the DemoModule
+ AppComponent,
+ HeroDetailComponent,
+ HeroListComponent
+ ],
+ providers: [ HeroService ], // <-- #4 provide HeroService
+// #docregion v1
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
+// #enddocregion v1
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/data-model.ts b/public/docs/_examples/reactive-forms/ts/src/app/data-model.ts
new file mode 100644
index 0000000000..ad01ddee56
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/data-model.ts
@@ -0,0 +1,40 @@
+// #docregion
+// #docregion model-classes
+export class Hero {
+ id = 0;
+ name = '';
+ addresses: Address[];
+}
+
+export class Address {
+ street = '';
+ city = '';
+ state = '';
+ zip = '';
+}
+// #enddocregion model-classes
+
+export const heroes: Hero[] = [
+ {
+ id: 1,
+ name: 'Whirlwind',
+ addresses: [
+ {street: '123 Main', city: 'Anywhere', state: 'CA', zip: '94801'},
+ {street: '456 Maple', city: 'Somewhere', state: 'VA', zip: '23226'},
+ ]
+ },
+ {
+ id: 2,
+ name: 'Bombastic',
+ addresses: [
+ {street: '789 Elm', city: 'Smallville', state: 'OH', zip: '04501'},
+ ]
+ },
+ {
+ id: 3,
+ name: 'Magneta',
+ addresses: [ ]
+ },
+];
+
+export const states = ['CA', 'MD', 'OH', 'VA'];
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/demo.component.html b/public/docs/_examples/reactive-forms/ts/src/app/demo.component.html
new file mode 100644
index 0000000000..1caae127af
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/demo.component.html
@@ -0,0 +1,40 @@
+
+
Reactive Forms
+
Pick a demo:
+
+ {{demo}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
= 6 && demo !== final" >
+
+
Loading heroes ...
+
Select a hero:
+
+
+ Refresh
+ {{hero.name}}
+
+
+
+
+ Hero Detail
+ Editing: {{selectedHero.name}}
+
+
+
+
+
+
+
+
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/demo.component.ts b/public/docs/_examples/reactive-forms/ts/src/app/demo.component.ts
new file mode 100644
index 0000000000..181726eb66
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/demo.component.ts
@@ -0,0 +1,47 @@
+/* tslint:disable:member-ordering */
+import { Component } from '@angular/core';
+import { Observable } from 'rxjs/Observable';
+
+import { Hero } from './data-model';
+import { HeroService } from './hero.service';
+
+@Component({
+ selector: 'my-app',
+ templateUrl: './demo.component.html'
+})
+export class DemoComponent {
+
+ demos: string[] = [
+ 'Just a FormControl',
+ 'FormControl in a FormGroup',
+ 'Simple FormBuilder group',
+ 'Group with multiple controls',
+ 'Nested FormBuilder group',
+ 'PatchValue',
+ 'SetValue',
+ 'FormArray',
+ 'Final'].map(n => n + ' Demo');
+
+ final = this.demos.length;
+ demo = this.final; // current demo
+
+ heroes: Observable;
+ isLoading = false;
+ selectedHero: Hero;
+
+ constructor(private heroService: HeroService) { }
+
+ getHeroes() {
+ this.isLoading = true;
+ this.heroes = this.heroService.getHeroes()
+ .finally(() => this.isLoading = false);
+ this.selectedHero = undefined;
+ }
+
+ select(hero: Hero) { this.selectedHero = hero; }
+
+ selectDemo(demo: number) {
+ this.demo = demo + 1;
+ this.getHeroes();
+ }
+}
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/demo.module.ts b/public/docs/_examples/reactive-forms/ts/src/app/demo.module.ts
new file mode 100644
index 0000000000..dac9145ca9
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/demo.module.ts
@@ -0,0 +1,33 @@
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { ReactiveFormsModule } from '@angular/forms';
+
+import { AppModule } from './app.module';
+import { DemoComponent } from './demo.component';
+import { HeroDetailComponent1 } from './hero-detail-1.component';
+import { HeroDetailComponent2 } from './hero-detail-2.component';
+import { HeroDetailComponent3 } from './hero-detail-3.component';
+import { HeroDetailComponent4 } from './hero-detail-4.component';
+import { HeroDetailComponent5 } from './hero-detail-5.component';
+import { HeroDetailComponent6 } from './hero-detail-6.component';
+import { HeroDetailComponent7 } from './hero-detail-7.component';
+import { HeroDetailComponent8 } from './hero-detail-8.component';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ ReactiveFormsModule,
+ AppModule,
+ ],
+ declarations: [ DemoComponent,
+ HeroDetailComponent1,
+ HeroDetailComponent2,
+ HeroDetailComponent3,
+ HeroDetailComponent4,
+ HeroDetailComponent5,
+ HeroDetailComponent6,
+ HeroDetailComponent7,
+ HeroDetailComponent8],
+ bootstrap: [ DemoComponent ]
+})
+export class DemoModule { }
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-1.component.html b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-1.component.html
new file mode 100644
index 0000000000..7217708d22
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-1.component.html
@@ -0,0 +1,8 @@
+
+Hero Detail
+Just a FormControl
+Name:
+
+
+
+
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-1.component.ts b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-1.component.ts
new file mode 100644
index 0000000000..318dfff145
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-1.component.ts
@@ -0,0 +1,14 @@
+/* tslint:disable:component-class-suffix */
+// #docregion imports
+import { Component } from '@angular/core';
+import { FormControl } from '@angular/forms';
+// #enddocregion
+
+@Component({
+ selector: 'hero-detail-1',
+ templateUrl: './hero-detail-1.component.html'
+})
+// #docregion v1
+export class HeroDetailComponent1 {
+ name = new FormControl();
+}
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-2.component.html b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-2.component.html
new file mode 100644
index 0000000000..1e98354842
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-2.component.html
@@ -0,0 +1,18 @@
+
+Hero Detail
+FormControl in a FormGroup
+
+
+
+
+Form value: {{ heroForm.value | json }}
+
+
+
+
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-2.component.ts b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-2.component.ts
new file mode 100644
index 0000000000..6aa3c1ed3a
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-2.component.ts
@@ -0,0 +1,17 @@
+/* tslint:disable:component-class-suffix */
+// #docregion imports
+import { Component } from '@angular/core';
+import { FormControl, FormGroup } from '@angular/forms';
+// #enddocregion imports
+
+@Component({
+ selector: 'hero-detail-2',
+ templateUrl: './hero-detail-2.component.html'
+})
+// #docregion v2
+export class HeroDetailComponent2 {
+ heroForm = new FormGroup ({
+ name: new FormControl()
+ });
+}
+// #enddocregion v2
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-3.component.html b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-3.component.html
new file mode 100644
index 0000000000..8edc544dd4
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-3.component.html
@@ -0,0 +1,16 @@
+
+Hero Detail
+A FormGroup with a single FormControl using FormBuilder
+
+
+
+
+Form value: {{ heroForm.value | json }}
+Form status: {{ heroForm.status | json }}
+
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-3.component.ts b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-3.component.ts
new file mode 100644
index 0000000000..54a4e93361
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-3.component.ts
@@ -0,0 +1,27 @@
+/* tslint:disable:component-class-suffix */
+// #docregion imports
+import { Component } from '@angular/core';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+// #enddocregion imports
+
+@Component({
+ selector: 'hero-detail-3',
+ templateUrl: './hero-detail-3.component.html'
+})
+// #docregion v3
+export class HeroDetailComponent3 {
+ heroForm: FormGroup; // <--- heroForm is of type FormGroup
+
+ constructor(private fb: FormBuilder) { // <--- inject FormBuilder
+ this.createForm();
+ }
+
+ createForm() {
+ // #docregion required
+ this.heroForm = this.fb.group({
+ name: ['', Validators.required ],
+ });
+ // #enddocregion required
+ }
+}
+// #enddocregion v3
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-3a.component.ts b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-3a.component.ts
new file mode 100644
index 0000000000..2347869967
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-3a.component.ts
@@ -0,0 +1,25 @@
+/* tslint:disable:component-class-suffix */
+// #docregion imports
+import { Component } from '@angular/core';
+import { FormBuilder, FormGroup } from '@angular/forms';
+// #enddocregion imports
+
+@Component({
+ selector: 'hero-detail-3',
+ templateUrl: './hero-detail-3.component.html'
+})
+// #docregion v3a
+export class HeroDetailComponent3 {
+ heroForm: FormGroup; // <--- heroForm is of type FormGroup
+
+ constructor(private fb: FormBuilder) { // <--- inject FormBuilder
+ this.createForm();
+ }
+
+ createForm() {
+ this.heroForm = this.fb.group({
+ name: '', // <--- the FormControl called "name"
+ });
+ }
+}
+// #enddocregion v3a
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-4.component.html b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-4.component.html
new file mode 100644
index 0000000000..30529868e9
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-4.component.html
@@ -0,0 +1,46 @@
+
+Hero Detail
+A FormGroup with multiple FormControls
+
+
+
+Form value: {{ heroForm.value | json }}
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-4.component.ts b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-4.component.ts
new file mode 100644
index 0000000000..d2f1ea2f96
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-4.component.ts
@@ -0,0 +1,34 @@
+/* tslint:disable:component-class-suffix */
+// #docregion imports
+import { Component } from '@angular/core';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+
+import { states } from './data-model';
+// #enddocregion imports
+
+@Component({
+ selector: 'hero-detail-4',
+ templateUrl: './hero-detail-4.component.html'
+})
+// #docregion v4
+export class HeroDetailComponent4 {
+ heroForm: FormGroup;
+ states = states;
+
+ constructor(private fb: FormBuilder) {
+ this.createForm();
+ }
+
+ createForm() {
+ this.heroForm = this.fb.group({
+ name: ['', Validators.required ],
+ street: '',
+ city: '',
+ state: '',
+ zip: '',
+ power: '',
+ sidekick: ''
+ });
+ }
+}
+// #enddocregion v4
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-5.component.html b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-5.component.html
new file mode 100644
index 0000000000..2a41b4f2f9
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-5.component.html
@@ -0,0 +1,56 @@
+
+
+
+heroForm value: {{ heroForm.value | json}}
+Extra info for the curious:
+
+Name value: {{ heroForm.get('name').value }}
+
+
+
+Street value: {{ heroForm.get('address.street').value}}
+
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-5.component.ts b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-5.component.ts
new file mode 100644
index 0000000000..f4be33389f
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-5.component.ts
@@ -0,0 +1,35 @@
+/* tslint:disable:component-class-suffix */
+import { Component } from '@angular/core';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+
+import { states } from './data-model';
+
+@Component({
+ selector: 'hero-detail-5',
+ templateUrl: './hero-detail-5.component.html'
+})
+// #docregion v5
+export class HeroDetailComponent5 {
+ heroForm: FormGroup;
+ states = states;
+
+ constructor(private fb: FormBuilder) {
+ this.createForm();
+ }
+
+ createForm() {
+ this.heroForm = this.fb.group({ // <-- the parent FormGroup
+ name: ['', Validators.required ],
+ address: this.fb.group({ // <-- the child FormGroup
+ street: '',
+ city: '',
+ state: '',
+ zip: ''
+ }),
+ power: '',
+ sidekick: ''
+ });
+ }
+}
+// #enddocregion v5
+
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-6.component.html b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-6.component.html
new file mode 100644
index 0000000000..4c8b5c9e05
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-6.component.html
@@ -0,0 +1,46 @@
+
+Hero Detail
+PatchValue to initialize a value
+
+
+
+Form value: {{ heroForm.value | json }}
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-6.component.ts b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-6.component.ts
new file mode 100644
index 0000000000..d5136822d1
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-6.component.ts
@@ -0,0 +1,58 @@
+/* tslint:disable:component-class-suffix */
+// #docregion import-input
+import { Component, Input, OnChanges } from '@angular/core';
+// #enddocregion import-input
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+
+// #docregion import-hero
+import { Hero, states } from './data-model';
+// #enddocregion import-hero
+
+////////// 6 ////////////////////
+
+@Component({
+ selector: 'hero-detail-6',
+ templateUrl: './hero-detail-5.component.html'
+})
+// #docregion v6
+export class HeroDetailComponent6 implements OnChanges {
+ // #docregion hero
+ @Input() hero: Hero;
+ // #enddocregion hero
+
+ heroForm: FormGroup;
+ states = states;
+
+ constructor(private fb: FormBuilder) {
+ this.createForm();
+ }
+
+ createForm() {
+ // #docregion hero-form-model
+ this.heroForm = this.fb.group({
+ name: ['', Validators.required ],
+ address: this.fb.group({
+ street: '',
+ city: '',
+ state: '',
+ zip: ''
+ }),
+ power: '',
+ sidekick: ''
+ });
+ // #enddocregion hero-form-model
+ }
+
+ // #docregion patch-value-on-changes
+ ngOnChanges() { // <-- wrap patchValue in ngOnChanges
+ this.heroForm.reset();
+ // #docregion patch-value
+ this.heroForm.patchValue({
+ name: this.hero.name
+ });
+ // #enddocregion patch-value
+ }
+ // #enddocregion patch-value-on-changes
+}
+
+// #enddocregion v6
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-7.component.html b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-7.component.html
new file mode 100644
index 0000000000..6d68b49b4d
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-7.component.html
@@ -0,0 +1,46 @@
+
+Hero Detail
+A FormGroup with multiple FormControls
+
+
+
+Form value: {{ heroForm.value | json }}
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-7.component.ts b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-7.component.ts
new file mode 100644
index 0000000000..497c7f6a56
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-7.component.ts
@@ -0,0 +1,69 @@
+/* tslint:disable:component-class-suffix */
+// #docplaster
+// #docregion imports
+import { Component, Input, OnChanges } from '@angular/core';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+
+// #docregion import-address
+import { Address, Hero, states } from './data-model';
+// #enddocregion import-address
+
+// #enddocregion imports
+
+@Component({
+ selector: 'hero-detail-7',
+ templateUrl: './hero-detail-5.component.html'
+})
+// #docregion v7
+export class HeroDetailComponent7 implements OnChanges {
+ @Input() hero: Hero;
+
+ heroForm: FormGroup;
+ states = states;
+
+ constructor(private fb: FormBuilder) {
+ this.createForm();
+ }
+
+ createForm() {
+ // #docregion address-form-group
+ this.heroForm = this.fb.group({
+ name: ['', Validators.required ],
+ address: this.fb.group(new Address()), // <-- a FormGroup with a new address
+ power: '',
+ sidekick: ''
+ });
+ // #enddocregion address-form-group
+ }
+
+ // #docregion ngOnChanges
+ ngOnChanges() {
+ this.heroForm.reset({
+ name: this.hero.name,
+ address: this.hero.addresses[0] || new Address()
+ });
+ }
+ // #enddocregion ngOnChanges
+
+ /* First version of ngOnChanges
+ // #docregion ngOnChanges-1
+ ngOnChanges()
+ // #enddocregion ngOnChanges-1
+ */
+ ngOnChanges1() {
+ // #docregion reset
+ this.heroForm.reset();
+ // #enddocregion reset
+ // #docregion ngOnChanges-1
+ // #docregion set-value
+ this.heroForm.setValue({
+ name: this.hero.name,
+ // #docregion set-value-address
+ address: this.hero.addresses[0] || new Address()
+ // #enddocregion set-value-address
+ });
+ // #enddocregion set-value
+ }
+ // #enddocregion ngOnChanges-1
+}
+
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-8.component.html b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-8.component.html
new file mode 100644
index 0000000000..d8e47ae798
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-8.component.html
@@ -0,0 +1,70 @@
+
+Using FormArray to add groups
+
+
+
+heroForm value: {{ heroForm.value | json}}
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-8.component.ts b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-8.component.ts
new file mode 100644
index 0000000000..1141c836a7
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail-8.component.ts
@@ -0,0 +1,68 @@
+/* tslint:disable:component-class-suffix */
+// #docregion imports
+import { Component, Input, OnChanges } from '@angular/core';
+import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';
+
+import { Address, Hero, states } from './data-model';
+// #enddocregion imports
+
+@Component({
+ selector: 'hero-detail-8',
+ templateUrl: './hero-detail-8.component.html'
+})
+// #docregion v8
+export class HeroDetailComponent8 implements OnChanges {
+ @Input() hero: Hero;
+
+ heroForm: FormGroup;
+ states = states;
+
+ // #docregion ctor
+ constructor(private fb: FormBuilder) {
+ this.createForm();
+ this.logNameChange();
+ }
+ // #enddocregion ctor
+
+ createForm() {
+ // #docregion secretLairs-form-array
+ this.heroForm = this.fb.group({
+ name: ['', Validators.required ],
+ secretLairs: this.fb.array([]), // <-- secretLairs as an empty FormArray
+ power: '',
+ sidekick: ''
+ });
+ // #enddocregion secretLairs-form-array
+ }
+
+ logNameChange() {/* Coming soon */}
+
+ // #docregion onchanges
+ ngOnChanges() {
+ this.heroForm.reset({
+ name: this.hero.name
+ });
+ this.setAddresses(this.hero.addresses);
+ }
+ // #enddocregion onchanges
+
+ // #docregion get-secret-lairs
+ get secretLairs(): FormArray {
+ return this.heroForm.get('secretLairs') as FormArray;
+ };
+ // #enddocregion get-secret-lairs
+
+ // #docregion set-addresses
+ setAddresses(addresses: Address[]) {
+ const addressFGs = addresses.map(address => this.fb.group(address));
+ const addressFormArray = this.fb.array(addressFGs);
+ this.heroForm.setControl('secretLairs', addressFormArray);
+ }
+ // #enddocregion set-addresses
+
+ // #docregion add-lair
+ addLair() {
+ this.secretLairs.push(this.fb.group(new Address()));
+ }
+ // #enddocregion add-lair
+}
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/hero-detail.component.html b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail.component.html
new file mode 100644
index 0000000000..8f5b8bf2c8
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail.component.html
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+heroForm value: {{ heroForm.value | json}}
+
+
+Name change log
+{{name}}
+
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/hero-detail.component.ts b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail.component.ts
new file mode 100644
index 0000000000..4cb69aaedf
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/hero-detail.component.ts
@@ -0,0 +1,107 @@
+// #docplaster
+// #docregion
+import { Component, Input, OnChanges } from '@angular/core';
+import { FormArray, FormBuilder, FormGroup } from '@angular/forms';
+
+import { Address, Hero, states } from './data-model';
+// #docregion import-service
+import { HeroService } from './hero.service';
+// #enddocregion import-service
+
+// #docregion metadata
+@Component({
+ selector: 'hero-detail',
+ templateUrl: './hero-detail.component.html'
+})
+// #enddocregion metadata
+export class HeroDetailComponent implements OnChanges {
+ @Input() hero: Hero;
+
+ heroForm: FormGroup;
+ // #docregion log-name-change
+ nameChangeLog: string[] = [];
+ // #enddocregion log-name-change
+ states = states;
+
+ // #docregion ctor
+ constructor(
+ private fb: FormBuilder,
+ private heroService: HeroService) {
+
+ this.createForm();
+ this.logNameChange();
+ }
+ // #enddocregion ctor
+
+ createForm() {
+ this.heroForm = this.fb.group({
+ name: '',
+ secretLairs: this.fb.array([]),
+ power: '',
+ sidekick: ''
+ });
+ }
+
+ ngOnChanges() {
+ this.heroForm.reset({
+ name: this.hero.name
+ });
+ this.setAddresses(this.hero.addresses);
+ }
+
+ get secretLairs(): FormArray {
+ return this.heroForm.get('secretLairs') as FormArray;
+ };
+
+ setAddresses(addresses: Address[]) {
+ const addressFGs = addresses.map(address => this.fb.group(address));
+ const addressFormArray = this.fb.array(addressFGs);
+ this.heroForm.setControl('secretLairs', addressFormArray);
+ }
+
+ addLair() {
+ this.secretLairs.push(this.fb.group(new Address()));
+ }
+
+ // #docregion on-submit
+ onSubmit() {
+ this.hero = this.prepareSaveHero();
+ this.heroService.updateHero(this.hero).subscribe(/* error handling */);
+ this.ngOnChanges();
+ }
+ // #enddocregion on-submit
+
+ // #docregion prepare-save-hero
+ prepareSaveHero(): Hero {
+ const formModel = this.heroForm.value;
+
+ // deep copy of form model lairs
+ const secretLairsDeepCopy: Address[] = formModel.secretLairs.map(
+ (address: Address) => Object.assign({}, address)
+ );
+
+ // return new `Hero` object containing a combination of original hero value(s)
+ // and deep copies of changed form model values
+ const saveHero: Hero = {
+ id: this.hero.id,
+ name: formModel.name as string,
+ // addresses: formModel.secretLairs // <-- bad!
+ addresses: secretLairsDeepCopy
+ };
+ return saveHero;
+ }
+ // #enddocregion prepare-save-hero
+
+ // #docregion revert
+ revert() { this.ngOnChanges(); }
+ // #enddocregion revert
+
+ // #docregion log-name-change
+ logNameChange() {
+ const nameControl = this.heroForm.get('name');
+ nameControl.valueChanges.forEach(
+ (value: string) => this.nameChangeLog.push(value)
+ );
+ }
+ // #enddocregion log-name-change
+}
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/hero-list.component.1.html b/public/docs/_examples/reactive-forms/ts/src/app/hero-list.component.1.html
new file mode 100644
index 0000000000..fa76c84f54
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/hero-list.component.1.html
@@ -0,0 +1,8 @@
+
+
+ {{hero.name}}
+
+
+
+
+
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/hero-list.component.html b/public/docs/_examples/reactive-forms/ts/src/app/hero-list.component.html
new file mode 100644
index 0000000000..d0fb2ee920
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/hero-list.component.html
@@ -0,0 +1,17 @@
+
+Loading heroes ...
+Select a hero:
+
+
+ Refresh
+ {{hero.name}}
+
+
+
+
+ Hero Detail
+ Editing: {{selectedHero.name}}
+
+
+
+
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/hero-list.component.ts b/public/docs/_examples/reactive-forms/ts/src/app/hero-list.component.ts
new file mode 100644
index 0000000000..98092adcdb
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/hero-list.component.ts
@@ -0,0 +1,31 @@
+// #docregion
+import { Component, OnInit } from '@angular/core';
+import { Observable } from 'rxjs/Observable';
+import 'rxjs/add/operator/finally';
+
+import { Hero } from './data-model';
+import { HeroService } from './hero.service';
+
+@Component({
+ selector: 'hero-list',
+ templateUrl: './hero-list.component.html'
+})
+export class HeroListComponent implements OnInit {
+ heroes: Observable;
+ isLoading = false;
+ selectedHero: Hero;
+
+ constructor(private heroService: HeroService) { }
+
+ ngOnInit() { this.getHeroes(); }
+
+ getHeroes() {
+ this.isLoading = true;
+ this.heroes = this.heroService.getHeroes()
+ // Todo: error handling
+ .finally(() => this.isLoading = false);
+ this.selectedHero = undefined;
+ }
+
+ select(hero: Hero) { this.selectedHero = hero; }
+}
diff --git a/public/docs/_examples/reactive-forms/ts/src/app/hero.service.ts b/public/docs/_examples/reactive-forms/ts/src/app/hero.service.ts
new file mode 100644
index 0000000000..6600586de7
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/app/hero.service.ts
@@ -0,0 +1,26 @@
+// #docregion
+import { Injectable } from '@angular/core';
+
+import { Observable } from 'rxjs/Observable';
+import { of } from 'rxjs/observable/of';
+import 'rxjs/add/operator/delay';
+
+import { Hero, heroes } from './data-model';
+
+@Injectable()
+export class HeroService {
+
+ delayMs = 500;
+
+ // Fake server get; assume nothing can go wrong
+ getHeroes(): Observable {
+ return of(heroes).delay(this.delayMs); // simulate latency with delay
+ }
+
+ // Fake server update; assume nothing can go wrong
+ updateHero(hero: Hero): Observable {
+ const oldHero = heroes.find(h => h.id === hero.id);
+ const newHero = Object.assign(oldHero, hero); // Demo: mutate cached hero
+ return of(newHero).delay(this.delayMs); // simulate latency with delay
+ }
+}
diff --git a/public/docs/_examples/reactive-forms/ts/src/index-final.html b/public/docs/_examples/reactive-forms/ts/src/index-final.html
new file mode 100644
index 0000000000..9ef0a379e0
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/index-final.html
@@ -0,0 +1,31 @@
+
+
+
+
+ Hero Form
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
diff --git a/public/docs/_examples/reactive-forms/ts/src/index.html b/public/docs/_examples/reactive-forms/ts/src/index.html
new file mode 100644
index 0000000000..802d12f211
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/index.html
@@ -0,0 +1,31 @@
+
+
+
+
+ Hero Form
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
diff --git a/public/docs/_examples/reactive-forms/ts/src/main-final.ts b/public/docs/_examples/reactive-forms/ts/src/main-final.ts
new file mode 100644
index 0000000000..7572d1f1d3
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/main-final.ts
@@ -0,0 +1,5 @@
+// tslint:disable:no-unused-variable
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/reactive-forms/ts/src/main.ts b/public/docs/_examples/reactive-forms/ts/src/main.ts
new file mode 100644
index 0000000000..f415a71708
--- /dev/null
+++ b/public/docs/_examples/reactive-forms/ts/src/main.ts
@@ -0,0 +1,6 @@
+// tslint:disable:no-unused-variable
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module'; // just the final version
+import { DemoModule } from './app/demo.module'; // demo picker
+
+platformBrowserDynamic().bootstrapModule(DemoModule); // (AppModule);
diff --git a/public/docs/_examples/router/e2e-spec.js b/public/docs/_examples/router/e2e-spec.js
deleted file mode 100644
index 0cea6a73fb..0000000000
--- a/public/docs/_examples/router/e2e-spec.js
+++ /dev/null
@@ -1,128 +0,0 @@
-describe('Router', function () {
-
- beforeAll(function () {
- browser.get('');
- });
-
- function getPageStruct() {
- hrefEles = element.all(by.css('my-app a'));
-
- return {
- hrefs: hrefEles,
- routerParent: element(by.css('my-app > undefined')),
- routerTitle: element(by.css('my-app > undefined > h2')),
-
- crisisHref: hrefEles.get(0),
- crisisList: element.all(by.css('my-app > undefined > undefined li')),
- crisisDetail: element(by.css('my-app > undefined > undefined > div')),
- crisisDetailTitle: element(by.css('my-app > undefined > undefined > div > h3')),
-
- heroesHref: hrefEles.get(1),
- heroesList: element.all(by.css('my-app > undefined li')),
- heroDetail: element(by.css('my-app > undefined > div')),
- heroDetailTitle: element(by.css('my-app > undefined > div > h3')),
-
- }
- }
-
- it('should be able to see the start screen', function () {
- var page = getPageStruct();
- expect(page.hrefs.count()).toEqual(2, 'should be two dashboard choices');
- expect(page.crisisHref.getText()).toEqual("Crisis Center");
- expect(page.heroesHref.getText()).toEqual("Heroes");
- });
-
- // assumes that jasmine runs tests in order that they appear.
- // (don't move this test later in this file because it will fail first 'expect').
- it('should be able to see crises center items', function () {
- var page = getPageStruct();
- expect(page.crisisList.count()).toBe(0, "should be no crisis center entries on startup");
- page.crisisHref.click().then(function() {
- expect(page.routerTitle.getText()).toContain('CRISIS CENTER');
- expect(page.crisisList.count()).toBe(4, "should be 4 crisis center entries");
- });
- });
-
- it('should be able to see hero items', function () {
- var page = getPageStruct();
- page.heroesHref.click().then(function() {
- expect(page.routerTitle.getText()).toContain('HEROES');
- expect(page.heroesList.count()).toBe(6, "should be 6 heroes");
- });
- });
-
- it('should be able to toggle the views', function () {
- var page = getPageStruct();
- page.crisisHref.click().then(function() {
- expect(page.crisisList.count()).toBe(4, "should be 4 crisis center entries");
- return page.heroesHref.click();
- }).then(function() {
- expect(page.heroesList.count()).toBe(6, "should be 6 heroes");
- });
- });
-
- it('should be able to edit and save details from the crisis center view', function () {
- crisisCenterEdit(2, true);
- });
-
- it('should be able to edit and cancel details from the crisis center view', function () {
- crisisCenterEdit(3, false);
- });
-
- it('should be able to edit and save details from the heroes view', function () {
- var page = getPageStruct();
- var heroEle, heroText;
- page.heroesHref.click().then(function() {
- heroEle = page.heroesList.get(4);
- return heroEle.getText();
- }).then(function(text) {
- expect(text.length).toBeGreaterThan(0, 'should have some text');
- // remove leading id from text
- heroText = text.substr(text.indexOf(' ')).trim();
- return heroEle.click();
- }).then(function() {
- expect(page.heroesList.count()).toBe(0, "should no longer see crisis center entries");
- expect(page.heroDetail.isPresent()).toBe(true, 'should be able to see crisis detail');
- expect(page.heroDetailTitle.getText()).toContain(heroText);
- var inputEle = page.heroDetail.element(by.css('input'));
- return sendKeys(inputEle, '-foo');
- }).then(function() {
- expect(page.heroDetailTitle.getText()).toContain(heroText + '-foo');
- var buttonEle = page.heroDetail.element(by.css('button'));
- return buttonEle.click();
- }).then(function() {
- expect(heroEle.getText()).toContain(heroText + '-foo');
- })
- });
-
- function crisisCenterEdit(index, shouldSave) {
- var page = getPageStruct();
- var crisisEle, crisisText;
- page.crisisHref.click().then(function () {
- crisisEle = page.crisisList.get(index);
- return crisisEle.getText();
- }).then(function (text) {
- expect(text.length).toBeGreaterThan(0, 'should have some text');
- // remove leading id from text
- crisisText = text.substr(text.indexOf(' ')).trim();
- return crisisEle.click();
- }).then(function () {
- expect(page.crisisList.count()).toBe(0, "should no longer see crisis center entries");
- expect(page.crisisDetail.isPresent()).toBe(true, 'should be able to see crisis detail');
- expect(page.crisisDetailTitle.getText()).toContain(crisisText);
- var inputEle = page.crisisDetail.element(by.css('input'));
- return sendKeys(inputEle, '-foo');
- }).then(function () {
- expect(page.crisisDetailTitle.getText()).toContain(crisisText + '-foo');
- var buttonEle = page.crisisDetail.element(by.cssContainingText('button', shouldSave ? 'Save' : 'Cancel'));
- return buttonEle.click();
- }).then(function () {
- if (shouldSave) {
- expect(crisisEle.getText()).toContain(crisisText + '-foo');
- } else {
- expect(crisisEle.getText()).not.toContain(crisisText + '-foo');
- }
- });
- }
-
-});
diff --git a/public/docs/_examples/router/e2e-spec.ts b/public/docs/_examples/router/e2e-spec.ts
new file mode 100644
index 0000000000..2e9c6bafeb
--- /dev/null
+++ b/public/docs/_examples/router/e2e-spec.ts
@@ -0,0 +1,162 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by, ExpectedConditions } from 'protractor';
+
+const numDashboardTabs = 5;
+const numCrises = 4;
+const numHeroes = 6;
+const EC = ExpectedConditions;
+
+describe('Router', () => {
+
+ beforeAll(() => browser.get(''));
+
+ function getPageStruct() {
+ const hrefEles = element.all(by.css('my-app a'));
+ const crisisDetail = element.all(by.css('my-app > ng-component > ng-component > ng-component > div')).first();
+ const heroDetail = element(by.css('my-app > ng-component > div'));
+
+ return {
+ hrefs: hrefEles,
+ activeHref: element(by.css('my-app a.active')),
+
+ crisisHref: hrefEles.get(0),
+ crisisList: element.all(by.css('my-app > ng-component > ng-component li')),
+ crisisDetail: crisisDetail,
+ crisisDetailTitle: crisisDetail.element(by.xpath('*[1]')),
+
+ heroesHref: hrefEles.get(1),
+ heroesList: element.all(by.css('my-app > ng-component li')),
+ heroDetail: heroDetail,
+ heroDetailTitle: heroDetail.element(by.xpath('*[1]')),
+
+ adminHref: hrefEles.get(2),
+ adminPreloadList: element.all(by.css('my-app > ng-component > ng-component > ul > li')),
+
+ loginHref: hrefEles.get(3),
+ loginButton: element.all(by.css('my-app > ng-component > p > button')),
+
+ contactHref: hrefEles.get(4),
+ contactCancelButton: element.all(by.buttonText('Cancel')),
+
+ outletComponents: element.all(by.css('my-app > ng-component'))
+ };
+ }
+
+ it('has expected dashboard tabs', () => {
+ const page = getPageStruct();
+ expect(page.hrefs.count()).toEqual(numDashboardTabs, 'dashboard tab count');
+ expect(page.crisisHref.getText()).toEqual('Crisis Center');
+ expect(page.heroesHref.getText()).toEqual('Heroes');
+ expect(page.adminHref.getText()).toEqual('Admin');
+ expect(page.loginHref.getText()).toEqual('Login');
+ expect(page.contactHref.getText()).toEqual('Contact');
+ });
+
+ it('has heroes selected as opening tab', () => {
+ const page = getPageStruct();
+ expect(page.activeHref.getText()).toEqual('Heroes');
+ });
+
+ it('has crises center items', async () => {
+ const page = getPageStruct();
+ await page.crisisHref.click();
+ expect(page.activeHref.getText()).toEqual('Crisis Center');
+ expect(page.crisisList.count()).toBe(numCrises, 'crisis list count');
+ });
+
+ it('has hero items', async () => {
+ const page = getPageStruct();
+ await page.heroesHref.click();
+ expect(page.activeHref.getText()).toEqual('Heroes');
+ expect(page.heroesList.count()).toBe(numHeroes, 'hero list count');
+ });
+
+ it('toggles views', async () => {
+ const page = getPageStruct();
+ await page.crisisHref.click();
+ expect(page.activeHref.getText()).toEqual('Crisis Center');
+ expect(page.crisisList.count()).toBe(numCrises, 'crisis list count');
+ await page.heroesHref.click();
+ expect(page.activeHref.getText()).toEqual('Heroes');
+ expect(page.heroesList.count()).toBe(numHeroes, 'hero list count');
+ });
+
+ it('saves changed crisis details', async () => {
+ const page = getPageStruct();
+ await page.crisisHref.click();
+ await crisisCenterEdit(2, true);
+ });
+
+ it('can cancel changed crisis details', async () => {
+ const page = getPageStruct();
+ await page.crisisHref.click();
+ await crisisCenterEdit(3, false);
+ });
+
+ it('saves changed hero details', async () => {
+ const page = getPageStruct();
+ await page.heroesHref.click();
+ const heroEle = page.heroesList.get(4);
+ let text = await heroEle.getText();
+ expect(text.length).toBeGreaterThan(0, 'hero item text length');
+ // remove leading id from text
+ const heroText = text.substr(text.indexOf(' ')).trim();
+
+ await heroEle.click();
+ expect(page.heroesList.count()).toBe(0, 'hero list count');
+ expect(page.heroDetail.isPresent()).toBe(true, 'hero detail');
+ expect(page.heroDetailTitle.getText()).toContain(heroText);
+ let inputEle = page.heroDetail.element(by.css('input'));
+ await inputEle.sendKeys('-foo');
+ expect(page.heroDetailTitle.getText()).toContain(heroText + '-foo');
+
+ let buttonEle = page.heroDetail.element(by.css('button'));
+ await buttonEle.click();
+ expect(heroEle.getText()).toContain(heroText + '-foo');
+ });
+
+ it('sees preloaded modules', async () => {
+ const page = getPageStruct();
+ await page.loginHref.click();
+ await page.loginButton.click();
+ const list = page.adminPreloadList;
+ expect(list.count()).toBe(1, 'preloaded module');
+ expect(await list.first().getText()).toBe('crisis-center', 'first preloaded module');
+ });
+
+ it('sees the secondary route', async () => {
+ const page = getPageStruct();
+ await page.heroesHref.click();
+ await page.contactHref.click();
+ expect(page.outletComponents.count()).toBe(2, 'route count');
+ });
+
+ async function crisisCenterEdit(index: number, save: boolean) {
+ const page = getPageStruct();
+ await page.crisisHref.click();
+ let crisisEle = page.crisisList.get(index);
+ let text = await crisisEle.getText();
+ expect(text.length).toBeGreaterThan(0, 'crisis item text length');
+ // remove leading id from text
+ const crisisText = text.substr(text.indexOf(' ')).trim();
+
+ await crisisEle.click();
+ expect(page.crisisDetail.isPresent()).toBe(true, 'crisis detail present');
+ expect(page.crisisDetailTitle.getText()).toContain(crisisText);
+ let inputEle = page.crisisDetail.element(by.css('input'));
+ await inputEle.sendKeys('-foo');
+
+ let buttonEle = page.crisisDetail.element(by.buttonText(save ? 'Save' : 'Cancel'));
+ await buttonEle.click();
+ crisisEle = page.crisisList.get(index);
+ if (save) {
+ expect(crisisEle.getText()).toEqual(crisisText + '-foo');
+ } else {
+ await browser.wait(EC.alertIsPresent(), 4000);
+ await browser.switchTo().alert().accept();
+ expect(crisisEle.getText()).toEqual(crisisText);
+ }
+ }
+
+});
diff --git a/public/docs/_examples/router/ts/.gitignore b/public/docs/_examples/router/ts/.gitignore
deleted file mode 100644
index 2cb7d2a2e9..0000000000
--- a/public/docs/_examples/router/ts/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-**/*.js
diff --git a/public/docs/_examples/router/ts/app/app.component.1.ts b/public/docs/_examples/router/ts/app/app.component.1.ts
deleted file mode 100644
index 3caad41fe8..0000000000
--- a/public/docs/_examples/router/ts/app/app.component.1.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-/* First version */
-// #docplaster
-
-// #docregion
-import {Component} from 'angular2/core';
-import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';
-
-import {CrisisListComponent} from './crisis-list.component';
-import {HeroListComponent} from './hero-list.component';
-
-@Component({
- selector: 'my-app',
-// #docregion template
- template: `
- Component Router
-
- Crisis Center
- Heroes
-
-
- `,
-// #enddocregion template
- directives: [ROUTER_DIRECTIVES]
-})
-// #enddocregion
-/*
-// #docregion route-config
-@Component({ ... })
-// #enddocregion route-config
-*/
-// #docregion
-// #docregion route-config
-@RouteConfig([
-// #docregion route-defs
- {path:'/crisis-center', name: 'CrisisCenter', component: CrisisListComponent},
- {path:'/heroes', name: 'Heroes', component: HeroListComponent}
-// #enddocregion route-defs
-])
-export class AppComponent { }
-// #enddocregion route-config
-// #enddocregion
diff --git a/public/docs/_examples/router/ts/app/app.component.2.ts b/public/docs/_examples/router/ts/app/app.component.2.ts
deleted file mode 100644
index ce4f3c1c53..0000000000
--- a/public/docs/_examples/router/ts/app/app.component.2.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Second Heroes version */
-// #docplaster
-
-// #docregion
-import {Component} from 'angular2/core';
-import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';
-
-import {CrisisListComponent} from './crisis-list.component';
-// #enddocregion
-/*
-// Apparent Milestone 2 imports
-// #docregion
-// #docregion hero-import
-import {HeroListComponent} from './heroes/hero-list.component';
-import {HeroDetailComponent} from './heroes/hero-detail.component';
-import {HeroService} from './heroes/hero.service';
-// #enddocregion hero-import
-// #enddocregion
-*/
-// Actual Milestone 2 imports
-import {HeroListComponent} from './heroes/hero-list.component.1';
-import {HeroDetailComponent} from './heroes/hero-detail.component.1';
-import {HeroService} from './heroes/hero.service';
-// #docregion
-
-@Component({
- selector: 'my-app',
- template: `
- Component Router
-
- Crisis Center
- Heroes
-
-
- `,
- providers: [HeroService],
- directives: [ROUTER_DIRECTIVES]
-})
-// #enddocregion
-/*
-// #docregion route-config
-@Component({ ... })
-// #enddocregion route-config
-*/
-// #docregion
-// #docregion route-config
-@RouteConfig([
-// #docregion route-defs
- {path:'/crisis-center', name: 'CrisisCenter', component: CrisisListComponent},
- {path:'/heroes', name: 'Heroes', component: HeroListComponent},
- // #docregion hero-detail-route
- {path:'/hero/:id', name: 'HeroDetail', component: HeroDetailComponent}
- // #enddocregion hero-detail-route
-// #enddocregion route-defs
-])
-export class AppComponent { }
-// #enddocregion route-config
-// #enddocregion
diff --git a/public/docs/_examples/router/ts/app/app.component.3.ts b/public/docs/_examples/router/ts/app/app.component.3.ts
deleted file mode 100644
index a16defa8af..0000000000
--- a/public/docs/_examples/router/ts/app/app.component.3.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-// #docplaster
-import {Component} from 'angular2/core';
-import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';
-
-import {CrisisCenterComponent} from './crisis-center/crisis-center.component.1';
-import {HeroListComponent} from './heroes/hero-list.component.1';
-import {HeroDetailComponent} from './heroes/hero-detail.component.1';
-
-import {DialogService} from './dialog.service';
-import {HeroService} from './heroes/hero.service';
-
-@Component({
- selector: 'my-app',
-// #enddocregion
- /* Typical link
- // #docregion h-anchor
- Heroes
- // #enddocregion h-anchor
- */
- /* Incomplete Crisis Center link when CC lacks a default
- // #docregion cc-anchor-fail
- // The link now fails with a "non-terminal link" error
- // #docregion cc-anchor-w-default
- Crisis Center
- // #enddocregion cc-anchor-w-default
- // #enddocregion cc-anchor-fail
- */
- /* Crisis Center link when CC lacks a default
- // #docregion cc-anchor-no-default
- Crisis Center
- // #enddocregion cc-anchor-no-default
- */
- /* Crisis Center Detail link
- // #docregion Dragon-anchor
- Dragon Crisis
- // #enddocregion Dragon-anchor
- */
-// #docregion template
- template: `
- Component Router
-
- Crisis Center
- Dragon Crisis
- Shark Crisis
-
-
- `,
-// #enddocregion template
- providers: [DialogService, HeroService],
- directives: [ROUTER_DIRECTIVES]
-})
-@RouteConfig([
- {path: '/crisis-center/...', name: 'CrisisCenter', component: CrisisCenterComponent},
-])
-export class AppComponent { }
diff --git a/public/docs/_examples/router/ts/app/app.component.ts b/public/docs/_examples/router/ts/app/app.component.ts
deleted file mode 100644
index d2ca8c0c4c..0000000000
--- a/public/docs/_examples/router/ts/app/app.component.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-// #docplaster
-// #docregion
-import {Component} from 'angular2/core';
-import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';
-
-import {CrisisCenterComponent} from './crisis-center/crisis-center.component';
-import {HeroListComponent} from './heroes/hero-list.component';
-import {HeroDetailComponent} from './heroes/hero-detail.component';
-
-import {DialogService} from './dialog.service';
-import {HeroService} from './heroes/hero.service';
-
-@Component({
- selector: 'my-app',
-// #docregion template
- template: `
- Component Router
-
- Crisis Center
- Heroes
-
-
- `,
-// #enddocregion template
- providers: [DialogService, HeroService],
- directives: [ROUTER_DIRECTIVES]
-})
-// #docregion route-config
-@RouteConfig([
-
- // #docregion route-config-cc
- { // Crisis Center child route
- path: '/crisis-center/...',
- name: 'CrisisCenter',
- component: CrisisCenterComponent,
- useAsDefault: true
- },
- // #enddocregion route-config-cc
-
- {path: '/heroes', name: 'Heroes', component: HeroListComponent},
- {path: '/hero/:id', name: 'HeroDetail', component: HeroDetailComponent},
- // #enddocregion route-config
- // #docregion asteroid-route
- {path: '/disaster', name: 'Asteroid', redirectTo: ['CrisisCenter', 'CrisisDetail', {id:3}]}
- // #enddocregion asteroid-route
- // #docregion route-config
-])
-// #enddocregion route-config
-export class AppComponent { }
diff --git a/public/docs/_examples/router/ts/app/crisis-center/add-crisis.component.ts b/public/docs/_examples/router/ts/app/crisis-center/add-crisis.component.ts
deleted file mode 100644
index c9e2550eab..0000000000
--- a/public/docs/_examples/router/ts/app/crisis-center/add-crisis.component.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import {Component} from 'angular2/core';
-import {Crisis, CrisisService} from './crisis.service';
-import {DialogService} from '../dialog.service';
-import {CanDeactivate, ComponentInstruction, Router} from 'angular2/router';
-
-@Component({
- template: `
- "{{editName}}"
-
- Name:
-
-
- Save
- Cancel
- `,
- styles: ['input {width: 20em}']
-})
-export class AddCrisisComponent implements CanDeactivate {
- editName: string;
-
- constructor(
- private _service: CrisisService,
- private _router: Router,
- private _dialog: DialogService) { }
-
- routerCanDeactivate(next: ComponentInstruction, prev: ComponentInstruction) {
- return !!this.editName.trim() ||
- this._dialog.confirm('Discard changes?');
- }
-
- cancel() { this.gotoCrises(); }
-
- save() {
- this._service.addCrisis(this.editName);
- this.gotoCrises();
- }
-
- gotoCrises() {
- this._router.navigate(['CrisisCenter']);
- }
-}
\ No newline at end of file
diff --git a/public/docs/_examples/router/ts/app/crisis-center/crisis-center.component.1.ts b/public/docs/_examples/router/ts/app/crisis-center/crisis-center.component.1.ts
deleted file mode 100644
index 1cb8250f34..0000000000
--- a/public/docs/_examples/router/ts/app/crisis-center/crisis-center.component.1.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import {Component} from 'angular2/core';
-import {RouteConfig, RouterOutlet} from 'angular2/router';
-
-import {CrisisListComponent} from './crisis-list.component.1';
-import {CrisisDetailComponent} from './crisis-detail.component.1';
-import {CrisisService} from './crisis.service';
-
-// #docregion minus-imports
-@Component({
- template: `
- CRISIS CENTER
-
- `,
- directives: [RouterOutlet],
-// #docregion providers
- providers: [CrisisService]
-// #enddocregion providers
-})
-// #docregion route-config
-@RouteConfig([
- // #docregion default-route
- {path:'/', name: 'CrisisList', component: CrisisListComponent, useAsDefault: true},
- // #enddocregion default-route
- {path:'/:id', name: 'CrisisDetail', component: CrisisDetailComponent}
-])
-// #enddocregion route-config
-export class CrisisCenterComponent { }
-// #enddocregion minus-imports
diff --git a/public/docs/_examples/router/ts/app/crisis-center/crisis-center.component.ts b/public/docs/_examples/router/ts/app/crisis-center/crisis-center.component.ts
deleted file mode 100644
index 37fb4bf2dd..0000000000
--- a/public/docs/_examples/router/ts/app/crisis-center/crisis-center.component.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-// #docregion
-import {Component} from 'angular2/core';
-import {RouteConfig, RouterOutlet} from 'angular2/router';
-
-import {CrisisListComponent} from './crisis-list.component';
-import {CrisisDetailComponent} from './crisis-detail.component';
-import {CrisisService} from './crisis.service';
-
-@Component({
- template: `
- CRISIS CENTER
-
- `,
- directives: [RouterOutlet],
- providers: [CrisisService]
-})
-@RouteConfig([
- {path:'/', name: 'CrisisList', component: CrisisListComponent, useAsDefault: true},
- {path:'/:id', name: 'CrisisDetail', component: CrisisDetailComponent}
-])
-export class CrisisCenterComponent { }
-// #enddocregion
diff --git a/public/docs/_examples/router/ts/app/crisis-center/crisis-detail.component.1.ts b/public/docs/_examples/router/ts/app/crisis-center/crisis-detail.component.1.ts
deleted file mode 100644
index ed3994eaf8..0000000000
--- a/public/docs/_examples/router/ts/app/crisis-center/crisis-detail.component.1.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-// #docplaster
-
-// #docregion
-import {Component, OnInit} from 'angular2/core';
-import {Crisis, CrisisService} from './crisis.service';
-import {RouteParams, Router} from 'angular2/router';
-// #docregion routerCanDeactivate
-import {CanDeactivate, ComponentInstruction} from 'angular2/router';
-import {DialogService} from '../dialog.service';
-
-// #enddocregion routerCanDeactivate
-
-@Component({
- // #docregion template
- template: `
-
-
"{{editName}}"
-
- Id: {{crisis.id}}
-
- Name:
-
-
-
- Save
- Cancel
-
-
- `,
- // #enddocregion template
- styles: ['input {width: 20em}']
-})
-// #docregion routerCanDeactivate, cancel-save
-export class CrisisDetailComponent implements OnInit, CanDeactivate {
-
- crisis: Crisis;
- editName: string;
-
-// #enddocregion routerCanDeactivate, cancel-save
- constructor(
- private _service: CrisisService,
- private _router: Router,
- private _routeParams: RouteParams,
- private _dialog: DialogService
- ) { }
-
- // #docregion ngOnInit
- ngOnInit() {
- let id = +this._routeParams.get('id');
- this._service.getCrisis(id).then(crisis => {
- if (crisis) {
- this.editName = crisis.name;
- this.crisis = crisis;
- } else { // id not found
- this.gotoCrises();
- }
- });
- }
- // #enddocregion ngOnInit
-
- // #docregion routerCanDeactivate
- routerCanDeactivate(next: ComponentInstruction, prev: ComponentInstruction) : any {
- // Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged.
- if (!this.crisis || this.crisis.name === this.editName) {
- return true;
- }
- // Otherwise ask the user with the dialog service and return its
- // promise which resolves to true or false when the user decides
- return this._dialog.confirm('Discard changes?');
- }
- // #enddocregion routerCanDeactivate
-
- // #docregion cancel-save
- cancel() {
- this.editName = this.crisis.name;
- this.gotoCrises();
- }
-
- save() {
- this.crisis.name = this.editName;
- this.gotoCrises();
- }
- // #enddocregion cancel-save
-
- // #docregion gotoCrises
- gotoCrises() {
- // Like Crisis Center
- "{{editName}}"
-
- Id: {{crisis.id}}
-
- Name:
-
-
-
- Save
- Cancel
-
-
- `,
- styles: ['input {width: 20em}']
-})
-
-export class CrisisDetailComponent implements OnInit, CanDeactivate {
-
- crisis: Crisis;
- editName: string;
-
- constructor(
- private _service: CrisisService,
- private _router: Router,
- private _routeParams: RouteParams,
- private _dialog: DialogService
- ) { }
-
- ngOnInit() {
- let id = +this._routeParams.get('id');
- this._service.getCrisis(id).then(crisis => {
- if (crisis) {
- this.editName = crisis.name;
- this.crisis = crisis;
- } else { // id not found
- this.gotoCrises();
- }
- });
- }
-
- routerCanDeactivate(next: ComponentInstruction, prev: ComponentInstruction) : any {
- // Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged.
- if (!this.crisis || this.crisis.name === this.editName) {
- return true;
- }
- // Otherwise ask the user with the dialog service and return its
- // promise which resolves to true or false when the user decides
- return this._dialog.confirm('Discard changes?');
- }
-
- cancel() {
- this.editName = this.crisis.name;
- this.gotoCrises();
- }
-
- save() {
- this.crisis.name = this.editName;
- this.gotoCrises();
- }
-
- // #docregion gotoCrises
- gotoCrises() {
- let crisisId = this.crisis ? this.crisis.id : null;
- // Pass along the hero id if available
- // so that the CrisisListComponent can select that hero.
- // Add a totally useless `foo` parameter for kicks.
- // #docregion gotoCrises-navigate
- this._router.navigate(['CrisisList', {id: crisisId, foo: 'foo'} ]);
- // #enddocregion gotoCrises-navigate
- }
- // #enddocregion gotoCrises
-}
diff --git a/public/docs/_examples/router/ts/app/crisis-center/crisis-list.component.1.ts b/public/docs/_examples/router/ts/app/crisis-center/crisis-list.component.1.ts
deleted file mode 100644
index 96854b910c..0000000000
--- a/public/docs/_examples/router/ts/app/crisis-center/crisis-list.component.1.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-// #docplaster
-
-// #docregion
-import {Component, OnInit} from 'angular2/core';
-import {Crisis, CrisisService} from './crisis.service';
-import {Router} from 'angular2/router';
-
-@Component({
- // #docregion template
- template: `
-
-
- {{crisis.id}} {{crisis.name}}
-
-
- `,
- // #enddocregion template
-})
-export class CrisisListComponent implements OnInit {
- crises: Crisis[];
-
- constructor(
- private _service: CrisisService,
- private _router: Router) {}
-
- ngOnInit() {
- this._service.getCrises().then(crises => this.crises = crises);
- }
-
- // #docregion select
- onSelect(crisis: Crisis) {
- this._router.navigate(['CrisisDetail', { id: crisis.id }] );
- }
- // #enddocregion select
-}
diff --git a/public/docs/_examples/router/ts/app/crisis-center/crisis-list.component.ts b/public/docs/_examples/router/ts/app/crisis-center/crisis-list.component.ts
deleted file mode 100644
index 8d6dcfca16..0000000000
--- a/public/docs/_examples/router/ts/app/crisis-center/crisis-list.component.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-// #docplaster
-
-// #docregion
-import {Component, OnInit} from 'angular2/core';
-import {Crisis, CrisisService} from './crisis.service';
-import {Router, RouteParams} from 'angular2/router';
-
-@Component({
- template: `
-
-
- {{crisis.id}} {{crisis.name}}
-
-
- `,
-})
-export class CrisisListComponent implements OnInit {
- crises: Crisis[];
-
- private _selectedId: number;
-
- constructor(
- private _service: CrisisService,
- private _router: Router,
- routeParams: RouteParams) {
- this._selectedId = +routeParams.get('id');
- }
-
- isSelected(crisis: Crisis) { return crisis.id === this._selectedId; }
-
- ngOnInit() {
- this._service.getCrises().then(crises => this.crises = crises);
- }
-
- onSelect(crisis: Crisis) {
- this._router.navigate( ['CrisisDetail', { id: crisis.id }] );
- }
-}
diff --git a/public/docs/_examples/router/ts/app/crisis-center/crisis.service.ts b/public/docs/_examples/router/ts/app/crisis-center/crisis.service.ts
deleted file mode 100644
index 2f3fd761ec..0000000000
--- a/public/docs/_examples/router/ts/app/crisis-center/crisis.service.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-// #docplaster
-
-// #docregion
-import {Injectable} from 'angular2/core';
-
-export class Crisis {
- constructor(public id: number, public name: string) { }
-}
-
-@Injectable()
-export class CrisisService {
- getCrises() { return crisesPromise; }
-
- getCrisis(id: number | string) {
- return crisesPromise
- .then(crises => crises.filter(c => c.id === +id)[0]);
- }
-
-// #enddocregion
-
- static nextCrisisId = 100;
-
- addCrisis(name:string) {
- name = name.trim();
- if (name){
- let crisis = new Crisis(CrisisService.nextCrisisId++, name);
- crisesPromise.then(crises => crises.push(crisis));
- }
- }
-// #docregion
-}
-
-var crises = [
- new Crisis(1, 'Dragon Burning Cities'),
- new Crisis(2, 'Sky Rains Great White Sharks'),
- new Crisis(3, 'Giant Asteroid Heading For Earth'),
- new Crisis(4, 'Procrastinators Meeting Delayed Again'),
-];
-
-var crisesPromise = Promise.resolve(crises);
-// #enddocregion
diff --git a/public/docs/_examples/router/ts/app/crisis-list.component.ts b/public/docs/_examples/router/ts/app/crisis-list.component.ts
deleted file mode 100644
index b712137d05..0000000000
--- a/public/docs/_examples/router/ts/app/crisis-list.component.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-// Initial empty version
-// #docregion
-import {Component} from 'angular2/core';
-
-@Component({
- template: `
- CRISIS CENTER
- Get your crisis here
`
-})
-export class CrisisListComponent { }
diff --git a/public/docs/_examples/router/ts/app/dialog.service.ts b/public/docs/_examples/router/ts/app/dialog.service.ts
deleted file mode 100644
index a25f9c68d2..0000000000
--- a/public/docs/_examples/router/ts/app/dialog.service.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-// #docregion
-import {Injectable} from 'angular2/core';
-/**
- * Async modal dialog service
- * DialogService makes this app easier to test by faking this service.
- * TODO: better modal implemenation that doesn't use window.confirm
- */
-@Injectable()
-export class DialogService {
- /**
- * Ask user to confirm an action. `message` explains the action and choices.
- * Returns promise resolving to `true`=confirm or `false`=cancel
- */
- confirm(message?:string) {
- return new Promise((resolve, reject) =>
- resolve(window.confirm(message || 'Is it OK?')));
- };
-}
diff --git a/public/docs/_examples/router/ts/app/hero-list.component.ts b/public/docs/_examples/router/ts/app/hero-list.component.ts
deleted file mode 100644
index d1abf925de..0000000000
--- a/public/docs/_examples/router/ts/app/hero-list.component.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-/// Initial empty version
-// #docregion
-import {Component} from 'angular2/core';
-
-@Component({
- template: `
- HEROES
- Get your heroes here
`
-})
-export class HeroListComponent { }
diff --git a/public/docs/_examples/router/ts/app/heroes/hero-detail.component.1.ts b/public/docs/_examples/router/ts/app/heroes/hero-detail.component.1.ts
deleted file mode 100644
index bf189d7e1c..0000000000
--- a/public/docs/_examples/router/ts/app/heroes/hero-detail.component.1.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-// #docregion
-import {Component, OnInit} from 'angular2/core';
-import {Hero, HeroService} from './hero.service';
-import {RouteParams, Router} from 'angular2/router';
-
-@Component({
- template: `
- HEROES
-
-
"{{hero.name}}"
-
- Id: {{hero.id}}
-
- Name:
-
-
-
- Back
-
-
- `,
-})
-export class HeroDetailComponent implements OnInit {
- hero: Hero;
-
- // #docregion ctor
- constructor(
- private _router:Router,
- private _routeParams:RouteParams,
- private _service:HeroService){}
- // #enddocregion ctor
-
- // #docregion ngOnInit
- ngOnInit() {
- let id = this._routeParams.get('id');
- this._service.getHero(id).then(hero => this.hero = hero);
- }
- // #enddocregion ngOnInit
-
- // #docregion gotoHeroes
- gotoHeroes() {
- // Like Heroes
- this._router.navigate(['Heroes']);
- }
- // #enddocregion gotoHeroes
-}
diff --git a/public/docs/_examples/router/ts/app/heroes/hero-detail.component.ts b/public/docs/_examples/router/ts/app/heroes/hero-detail.component.ts
deleted file mode 100644
index b13c15c8d8..0000000000
--- a/public/docs/_examples/router/ts/app/heroes/hero-detail.component.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-// #docregion
-import {Component, OnInit} from 'angular2/core';
-import {Hero, HeroService} from './hero.service';
-import {RouteParams, Router} from 'angular2/router';
-
-@Component({
- template: `
- HEROES
-
-
"{{hero.name}}"
-
- Id: {{hero.id}}
-
- Name:
-
-
-
- Back
-
-
- `,
-})
-export class HeroDetailComponent implements OnInit {
- hero: Hero;
-
- // #docregion ctor
- constructor(
- private _router:Router,
- private _routeParams:RouteParams,
- private _service:HeroService){}
- // #enddocregion ctor
-
- // #docregion ngOnInit
- ngOnInit() {
- let id = this._routeParams.get('id');
- this._service.getHero(id).then(hero => this.hero = hero);
- }
- // #enddocregion ngOnInit
-
- // #docregion gotoHeroes
- gotoHeroes() {
- let heroId = this.hero ? this.hero.id : null;
- // Pass along the hero id if available
- // so that the HeroList component can select that hero.
- // Add a totally useless `foo` parameter for kicks.
- // #docregion gotoHeroes-navigate
- this._router.navigate(['Heroes', {id: heroId, foo: 'foo'} ]);
- // #enddocregion gotoHeroes-navigate
- }
- // #enddocregion gotoHeroes
-}
diff --git a/public/docs/_examples/router/ts/app/heroes/hero-list.component.1.ts b/public/docs/_examples/router/ts/app/heroes/hero-list.component.1.ts
deleted file mode 100644
index 05ca2ded3e..0000000000
--- a/public/docs/_examples/router/ts/app/heroes/hero-list.component.1.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-// #docplaster
-
-// #docregion
-// TODO SOMEDAY: Feature Componetized like HeroCenter
-import {Component, OnInit} from 'angular2/core';
-import {Hero, HeroService} from './hero.service';
-import {Router} from 'angular2/router';
-
-@Component({
- // #docregion template
- template: `
- HEROES
-
-
- {{hero.id}} {{hero.name}}
-
-
- `
- // #enddocregion template
-})
-export class HeroListComponent implements OnInit {
- heroes: Hero[];
-
- // #docregion ctor
- constructor(
- private _router: Router,
- private _service: HeroService) { }
- // #enddocregion ctor
-
- ngOnInit() {
- this._service.getHeroes().then(heroes => this.heroes = heroes)
- }
-
- // #docregion select
- onSelect(hero: Hero) {
- // #docregion nav-to-detail
- this._router.navigate( ['HeroDetail', { id: hero.id }] );
- // #enddocregion nav-to-detail
- }
- // #enddocregion select
-}
-// #enddocregion
-
-/* A link parameters array
-// #docregion link-parameters-array
-['HeroDetail', { id: hero.id }] // {id: 15}
-// #enddocregion link-parameters-array
-*/
\ No newline at end of file
diff --git a/public/docs/_examples/router/ts/app/heroes/hero-list.component.ts b/public/docs/_examples/router/ts/app/heroes/hero-list.component.ts
deleted file mode 100644
index 83f628704c..0000000000
--- a/public/docs/_examples/router/ts/app/heroes/hero-list.component.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-// #docplaster
-
-// TODO SOMEDAY: Feature Componetized like CrisisCenter
-// #docregion
-import {Component, OnInit} from 'angular2/core';
-import {Hero, HeroService} from './hero.service';
-// #docregion import-route-params
-import {Router, RouteParams} from 'angular2/router';
-// #enddocregion import-route-params
-
-@Component({
- // #docregion template
- template: `
- HEROES
-
-
- {{hero.id}} {{hero.name}}
-
-
- `
- // #enddocregion template
-})
-export class HeroListComponent implements OnInit {
- heroes: Hero[];
-
- // #docregion ctor
- private _selectedId: number;
-
- constructor(
- private _service: HeroService,
- private _router: Router,
- routeParams: RouteParams) {
- this._selectedId = +routeParams.get('id');
- }
- // #enddocregion ctor
-
- // #docregion isSelected
- isSelected(hero: Hero) { return hero.id === this._selectedId; }
- // #enddocregion isSelected
-
- // #docregion select
- onSelect(hero: Hero) {
- this._router.navigate( ['HeroDetail', { id: hero.id }] );
- }
- // #enddocregion select
-
- ngOnInit() {
- this._service.getHeroes().then(heroes => this.heroes = heroes)
- }
-}
-// #enddocregion
diff --git a/public/docs/_examples/router/ts/app/heroes/hero.service.ts b/public/docs/_examples/router/ts/app/heroes/hero.service.ts
deleted file mode 100644
index f85d353d2d..0000000000
--- a/public/docs/_examples/router/ts/app/heroes/hero.service.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-// #docregion
-import {Injectable} from 'angular2/core';
-
-export class Hero {
- constructor(public id: number, public name: string) { }
-}
-
-@Injectable()
-export class HeroService {
- getHeroes() { return heroesPromise; }
-
- getHero(id: number | string) {
- return heroesPromise
- .then(heroes => heroes.filter(h => h.id === +id)[0]);
- }
-}
-
-var HEROES = [
- new Hero(11, 'Mr. Nice'),
- new Hero(12, 'Narco'),
- new Hero(13, 'Bombasto'),
- new Hero(14, 'Celeritas'),
- new Hero(15, 'Magneta'),
- new Hero(16, 'RubberMan')
-];
-
-var heroesPromise = Promise.resolve(HEROES);
diff --git a/public/docs/_examples/router/ts/app/main.1.ts b/public/docs/_examples/router/ts/app/main.1.ts
deleted file mode 100644
index 8dfbeb39eb..0000000000
--- a/public/docs/_examples/router/ts/app/main.1.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-/* First version */
-// #docplaster
-
-// #docregion all
-import {AppComponent} from './app.component';
-import {bootstrap} from 'angular2/platform/browser';
-import {ROUTER_PROVIDERS} from 'angular2/router';
-
-// #enddocregion all
-
-/* Can't use AppComponent ... but display as if we can
-// #docregion all
-bootstrap(AppComponent, [
-// #enddocregion all
-*/
-
-// Actually use the v.1 component
-import {AppComponent as ac} from './app.component.1';
-bootstrap(ac, [
-// #docregion all
- ROUTER_PROVIDERS
-]);
-// #enddocregion all
\ No newline at end of file
diff --git a/public/docs/_examples/router/ts/app/main.2.ts b/public/docs/_examples/router/ts/app/main.2.ts
deleted file mode 100644
index 244050a36a..0000000000
--- a/public/docs/_examples/router/ts/app/main.2.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Second version */
-// For Milestone #2
-// Also includes digression on HashPathStrategy (not used in the final app)
-// #docplaster
-
-// #docregion
-import {bootstrap} from 'angular2/platform/browser';
-import {ROUTER_PROVIDERS} from 'angular2/router';
-import {AppComponent} from './app.component';
-
-// Add these symbols to override the `LocationStrategy`
-import {provide} from 'angular2/core';
-import {LocationStrategy,
- HashLocationStrategy} from 'angular2/router';
-// #enddocregion
-/* Can't use AppComponent ... but display as if we can
-// #docregion
-
-bootstrap(AppComponent, [
-// #enddocregion
-*/
-
-// Actually use the v.2 component
-import {AppComponent as ac} from './app.component.2';
-
-bootstrap(ac, [
-// #docregion
- ROUTER_PROVIDERS,
- provide(LocationStrategy,
- {useClass: HashLocationStrategy}) // .../#/crisis-center/
-]);
-// #enddocregion
diff --git a/public/docs/_examples/router/ts/app/main.3.ts b/public/docs/_examples/router/ts/app/main.3.ts
deleted file mode 100644
index d895aff5e9..0000000000
--- a/public/docs/_examples/router/ts/app/main.3.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// #docregion
-import {bootstrap} from 'angular2/platform/browser';
-import {ROUTER_PROVIDERS} from 'angular2/router';
-
-import {AppComponent} from './app.component.3';
-
-bootstrap(AppComponent, [ROUTER_PROVIDERS]);
diff --git a/public/docs/_examples/router/ts/app/main.ts b/public/docs/_examples/router/ts/app/main.ts
deleted file mode 100644
index 6805a24f60..0000000000
--- a/public/docs/_examples/router/ts/app/main.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// #docregion
-import {bootstrap} from 'angular2/platform/browser';
-import {ROUTER_PROVIDERS} from 'angular2/router';
-
-import {AppComponent} from './app.component';
-
-bootstrap(AppComponent, [ROUTER_PROVIDERS]);
diff --git a/public/docs/_examples/router/ts/index.1.html b/public/docs/_examples/router/ts/index.1.html
deleted file mode 100644
index f6a027f1de..0000000000
--- a/public/docs/_examples/router/ts/index.1.html
+++ /dev/null
@@ -1,46 +0,0 @@
-
-
-
-
-
-
-
- Router Sample
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Milestone 1
- loading...
-
-
-
-
diff --git a/public/docs/_examples/router/ts/index.2.html b/public/docs/_examples/router/ts/index.2.html
deleted file mode 100644
index 9fa6328a22..0000000000
--- a/public/docs/_examples/router/ts/index.2.html
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
-
-
-
-
- Router Sample
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Milestone 2
- loading...
-
-
-
-
diff --git a/public/docs/_examples/router/ts/index.3.html b/public/docs/_examples/router/ts/index.3.html
deleted file mode 100644
index 8b66281cc9..0000000000
--- a/public/docs/_examples/router/ts/index.3.html
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
-
-
-
-
- Router Sample
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Milestone 3
- loading...
-
-
-
-
diff --git a/public/docs/_examples/router/ts/index.html b/public/docs/_examples/router/ts/index.html
deleted file mode 100644
index dae130f8aa..0000000000
--- a/public/docs/_examples/router/ts/index.html
+++ /dev/null
@@ -1,50 +0,0 @@
-
-
-
-
-
-
-
-
-
- Router Sample
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- loading...
-
-
-
-
diff --git a/public/docs/_examples/router/ts/plnkr.json b/public/docs/_examples/router/ts/plnkr.json
index 741f87caa6..23ed1a1606 100644
--- a/public/docs/_examples/router/ts/plnkr.json
+++ b/public/docs/_examples/router/ts/plnkr.json
@@ -1,12 +1,12 @@
{
"description": "Router",
+ "basePath": "src/",
"files":[
"!**/*.d.ts",
"!**/*.js",
- "!**/*.[1,2,3].*",
+ "!**/*.[0-9].*",
"!app/crisis-list.component.ts",
- "!app/hero-list.component.ts",
- "!app/crisis-center/add-crisis.component.ts"
+ "!app/hero-list.component.ts"
],
"tags": ["router"]
-}
\ No newline at end of file
+}
diff --git a/public/docs/_examples/router/ts/src/app/admin/admin-dashboard.component.1.ts b/public/docs/_examples/router/ts/src/app/admin/admin-dashboard.component.1.ts
new file mode 100644
index 0000000000..ffa3e3cb8f
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/admin/admin-dashboard.component.1.ts
@@ -0,0 +1,9 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ template: `
+ Dashboard
+ `
+})
+export class AdminDashboardComponent { }
diff --git a/public/docs/_examples/router/ts/src/app/admin/admin-dashboard.component.2.ts b/public/docs/_examples/router/ts/src/app/admin/admin-dashboard.component.2.ts
new file mode 100644
index 0000000000..8c8e481643
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/admin/admin-dashboard.component.2.ts
@@ -0,0 +1,33 @@
+// #docregion
+import { Component, OnInit } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+import { Observable } from 'rxjs/Observable';
+import 'rxjs/add/operator/map';
+
+@Component({
+ template: `
+ Dashboard
+
+ Session ID: {{ sessionId | async }}
+
+ Token: {{ token | async }}
+ `
+})
+export class AdminDashboardComponent implements OnInit {
+ sessionId: Observable;
+ token: Observable;
+
+ constructor(private route: ActivatedRoute) {}
+
+ ngOnInit() {
+ // Capture the session ID if available
+ this.sessionId = this.route
+ .queryParams
+ .map(params => params['session_id'] || 'None');
+
+ // Capture the fragment if available
+ this.token = this.route
+ .fragment
+ .map(fragment => fragment || 'None');
+ }
+}
diff --git a/public/docs/_examples/router/ts/src/app/admin/admin-dashboard.component.ts b/public/docs/_examples/router/ts/src/app/admin/admin-dashboard.component.ts
new file mode 100644
index 0000000000..b3fc839616
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/admin/admin-dashboard.component.ts
@@ -0,0 +1,47 @@
+// #docregion
+import { Component, OnInit } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+import { Observable } from 'rxjs/Observable';
+
+import { SelectivePreloadingStrategy } from '../selective-preloading-strategy';
+
+import 'rxjs/add/operator/map';
+
+@Component({
+ template: `
+ Dashboard
+
+ Session ID: {{ sessionId | async }}
+
+ Token: {{ token | async }}
+
+ Preloaded Modules
+
+ `
+})
+export class AdminDashboardComponent implements OnInit {
+ sessionId: Observable;
+ token: Observable;
+ modules: string[];
+
+ constructor(
+ private route: ActivatedRoute,
+ private preloadStrategy: SelectivePreloadingStrategy
+ ) {
+ this.modules = preloadStrategy.preloadedModules;
+ }
+
+ ngOnInit() {
+ // Capture the session ID if available
+ this.sessionId = this.route
+ .queryParams
+ .map(params => params['session_id'] || 'None');
+
+ // Capture the fragment if available
+ this.token = this.route
+ .fragment
+ .map(fragment => fragment || 'None');
+ }
+}
diff --git a/public/docs/_examples/router/ts/src/app/admin/admin-routing.module.1.ts b/public/docs/_examples/router/ts/src/app/admin/admin-routing.module.1.ts
new file mode 100644
index 0000000000..e7d83f113f
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/admin/admin-routing.module.1.ts
@@ -0,0 +1,39 @@
+// #docplaster
+// #docregion
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+import { AdminComponent } from './admin.component';
+import { AdminDashboardComponent } from './admin-dashboard.component';
+import { ManageCrisesComponent } from './manage-crises.component';
+import { ManageHeroesComponent } from './manage-heroes.component';
+
+// #docregion admin-routes
+const adminRoutes: Routes = [
+ {
+ path: 'admin',
+ component: AdminComponent,
+ children: [
+ {
+ path: '',
+ children: [
+ { path: 'crises', component: ManageCrisesComponent },
+ { path: 'heroes', component: ManageHeroesComponent },
+ { path: '', component: AdminDashboardComponent }
+ ]
+ }
+ ]
+ }
+];
+
+@NgModule({
+ imports: [
+ RouterModule.forChild(adminRoutes)
+ ],
+ exports: [
+ RouterModule
+ ]
+})
+export class AdminRoutingModule {}
+// #enddocregion admin-routes
+// #enddocregion
diff --git a/public/docs/_examples/router/ts/src/app/admin/admin-routing.module.2.ts b/public/docs/_examples/router/ts/src/app/admin/admin-routing.module.2.ts
new file mode 100644
index 0000000000..d945201afe
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/admin/admin-routing.module.2.ts
@@ -0,0 +1,44 @@
+// #docplaster
+// #docregion
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+import { AdminComponent } from './admin.component';
+import { AdminDashboardComponent } from './admin-dashboard.component';
+import { ManageCrisesComponent } from './manage-crises.component';
+import { ManageHeroesComponent } from './manage-heroes.component';
+
+// #docregion admin-route
+import { AuthGuard } from '../auth-guard.service';
+
+const adminRoutes: Routes = [
+ {
+ path: 'admin',
+ component: AdminComponent,
+ canActivate: [AuthGuard],
+ children: [
+ {
+ path: '',
+ children: [
+ { path: 'crises', component: ManageCrisesComponent },
+ { path: 'heroes', component: ManageHeroesComponent },
+ { path: '', component: AdminDashboardComponent }
+ ],
+ // #enddocregion admin-route
+ canActivateChild: [AuthGuard]
+ // #docregion admin-route
+ }
+ ]
+ }
+];
+
+@NgModule({
+ imports: [
+ RouterModule.forChild(adminRoutes)
+ ],
+ exports: [
+ RouterModule
+ ]
+})
+export class AdminRoutingModule {}
+// #enddocregion
diff --git a/public/docs/_examples/router/ts/src/app/admin/admin-routing.module.3.ts b/public/docs/_examples/router/ts/src/app/admin/admin-routing.module.3.ts
new file mode 100644
index 0000000000..63f1c9aaf4
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/admin/admin-routing.module.3.ts
@@ -0,0 +1,43 @@
+// #docplaster
+// #docregion
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+import { AdminComponent } from './admin.component';
+import { AdminDashboardComponent } from './admin-dashboard.component';
+import { ManageCrisesComponent } from './manage-crises.component';
+import { ManageHeroesComponent } from './manage-heroes.component';
+
+// #docregion admin-route
+import { AuthGuard } from '../auth-guard.service';
+
+// #docregion can-activate-child
+const adminRoutes: Routes = [
+ {
+ path: 'admin',
+ component: AdminComponent,
+ canActivate: [AuthGuard],
+ children: [
+ {
+ path: '',
+ canActivateChild: [AuthGuard],
+ children: [
+ { path: 'crises', component: ManageCrisesComponent },
+ { path: 'heroes', component: ManageHeroesComponent },
+ { path: '', component: AdminDashboardComponent }
+ ]
+ }
+ ]
+ }
+];
+
+@NgModule({
+ imports: [
+ RouterModule.forChild(adminRoutes)
+ ],
+ exports: [
+ RouterModule
+ ]
+})
+export class AdminRoutingModule {}
+// #enddocregion
diff --git a/public/docs/_examples/router/ts/src/app/admin/admin-routing.module.ts b/public/docs/_examples/router/ts/src/app/admin/admin-routing.module.ts
new file mode 100644
index 0000000000..2b1048d110
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/admin/admin-routing.module.ts
@@ -0,0 +1,41 @@
+// #docplaster
+// #docregion
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+import { AdminComponent } from './admin.component';
+import { AdminDashboardComponent } from './admin-dashboard.component';
+import { ManageCrisesComponent } from './manage-crises.component';
+import { ManageHeroesComponent } from './manage-heroes.component';
+
+import { AuthGuard } from '../auth-guard.service';
+
+const adminRoutes: Routes = [
+ {
+ path: '',
+ component: AdminComponent,
+ canActivate: [AuthGuard],
+ children: [
+ {
+ path: '',
+ canActivateChild: [AuthGuard],
+ children: [
+ { path: 'crises', component: ManageCrisesComponent },
+ { path: 'heroes', component: ManageHeroesComponent },
+ { path: '', component: AdminDashboardComponent }
+ ]
+ }
+ ]
+ }
+];
+
+@NgModule({
+ imports: [
+ RouterModule.forChild(adminRoutes)
+ ],
+ exports: [
+ RouterModule
+ ]
+})
+export class AdminRoutingModule {}
+// #enddocregion
diff --git a/public/docs/_examples/router/ts/src/app/admin/admin.component.ts b/public/docs/_examples/router/ts/src/app/admin/admin.component.ts
new file mode 100644
index 0000000000..30abfa4524
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/admin/admin.component.ts
@@ -0,0 +1,17 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ template: `
+ ADMIN
+
+ Dashboard
+ Manage Crises
+ Manage Heroes
+
+
+ `
+})
+export class AdminComponent {
+}
diff --git a/public/docs/_examples/router/ts/src/app/admin/admin.module.ts b/public/docs/_examples/router/ts/src/app/admin/admin.module.ts
new file mode 100644
index 0000000000..2736f00e1d
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/admin/admin.module.ts
@@ -0,0 +1,24 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { AdminComponent } from './admin.component';
+import { AdminDashboardComponent } from './admin-dashboard.component';
+import { ManageCrisesComponent } from './manage-crises.component';
+import { ManageHeroesComponent } from './manage-heroes.component';
+
+import { AdminRoutingModule } from './admin-routing.module';
+
+@NgModule({
+ imports: [
+ CommonModule,
+ AdminRoutingModule
+ ],
+ declarations: [
+ AdminComponent,
+ AdminDashboardComponent,
+ ManageCrisesComponent,
+ ManageHeroesComponent
+ ]
+})
+export class AdminModule {}
diff --git a/public/docs/_examples/router/ts/src/app/admin/manage-crises.component.ts b/public/docs/_examples/router/ts/src/app/admin/manage-crises.component.ts
new file mode 100644
index 0000000000..d3176563eb
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/admin/manage-crises.component.ts
@@ -0,0 +1,9 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ template: `
+ Manage your crises here
+ `
+})
+export class ManageCrisesComponent { }
diff --git a/public/docs/_examples/router/ts/src/app/admin/manage-heroes.component.ts b/public/docs/_examples/router/ts/src/app/admin/manage-heroes.component.ts
new file mode 100644
index 0000000000..7f3a39893d
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/admin/manage-heroes.component.ts
@@ -0,0 +1,9 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ template: `
+ Manage your heroes here
+ `
+})
+export class ManageHeroesComponent { }
diff --git a/public/docs/_examples/router/ts/src/app/animations.ts b/public/docs/_examples/router/ts/src/app/animations.ts
new file mode 100644
index 0000000000..d7a55d721f
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/animations.ts
@@ -0,0 +1,26 @@
+// #docregion
+import { animate, AnimationEntryMetadata, state, style, transition, trigger } from '@angular/core';
+
+// Component transition animations
+export const slideInDownAnimation: AnimationEntryMetadata =
+ trigger('routeAnimation', [
+ state('*',
+ style({
+ opacity: 1,
+ transform: 'translateX(0)'
+ })
+ ),
+ transition(':enter', [
+ style({
+ opacity: 0,
+ transform: 'translateX(-100%)'
+ }),
+ animate('0.2s ease-in')
+ ]),
+ transition(':leave', [
+ animate('0.5s ease-out', style({
+ opacity: 0,
+ transform: 'translateY(100%)'
+ }))
+ ])
+ ]);
diff --git a/public/docs/_examples/router/ts/src/app/app-routing.module.1.ts b/public/docs/_examples/router/ts/src/app/app-routing.module.1.ts
new file mode 100644
index 0000000000..8146e54671
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/app-routing.module.1.ts
@@ -0,0 +1,26 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+import { CrisisListComponent } from './crisis-list.component';
+import { HeroListComponent } from './hero-list.component';
+import { PageNotFoundComponent } from './not-found.component';
+
+// #docregion appRoutes
+const appRoutes: Routes = [
+ { path: 'crisis-center', component: CrisisListComponent },
+ { path: 'heroes', component: HeroListComponent },
+ { path: '', redirectTo: '/heroes', pathMatch: 'full' },
+ { path: '**', component: PageNotFoundComponent }
+];
+// #enddocregion appRoutes
+
+@NgModule({
+ imports: [
+ RouterModule.forRoot(appRoutes)
+ ],
+ exports: [
+ RouterModule
+ ]
+})
+export class AppRoutingModule {}
diff --git a/public/docs/_examples/router/ts/src/app/app-routing.module.2.ts b/public/docs/_examples/router/ts/src/app/app-routing.module.2.ts
new file mode 100644
index 0000000000..42ac84a481
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/app-routing.module.2.ts
@@ -0,0 +1,24 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+import { CrisisListComponent } from './crisis-list.component';
+// import { HeroListComponent } from './hero-list.component'; // <-- delete this line
+import { PageNotFoundComponent } from './not-found.component';
+
+const appRoutes: Routes = [
+ { path: 'crisis-center', component: CrisisListComponent },
+ // { path: 'heroes', component: HeroListComponent }, // <-- delete this line
+ { path: '', redirectTo: '/heroes', pathMatch: 'full' },
+ { path: '**', component: PageNotFoundComponent }
+];
+
+@NgModule({
+ imports: [
+ RouterModule.forRoot(appRoutes)
+ ],
+ exports: [
+ RouterModule
+ ]
+})
+export class AppRoutingModule {}
diff --git a/public/docs/_examples/router/ts/src/app/app-routing.module.3.ts b/public/docs/_examples/router/ts/src/app/app-routing.module.3.ts
new file mode 100644
index 0000000000..538ff9aafc
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/app-routing.module.3.ts
@@ -0,0 +1,31 @@
+// #docplaster
+// #docregion , v3
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+import { ComposeMessageComponent } from './compose-message.component';
+import { PageNotFoundComponent } from './not-found.component';
+
+const appRoutes: Routes = [
+// #enddocregion v3
+// #docregion compose
+ {
+ path: 'compose',
+ component: ComposeMessageComponent,
+ outlet: 'popup'
+ },
+// #enddocregion compose
+// #docregion v3
+ { path: '', redirectTo: '/heroes', pathMatch: 'full' },
+ { path: '**', component: PageNotFoundComponent }
+];
+
+@NgModule({
+ imports: [
+ RouterModule.forRoot(appRoutes)
+ ],
+ exports: [
+ RouterModule
+ ]
+})
+export class AppRoutingModule {}
diff --git a/public/docs/_examples/router/ts/src/app/app-routing.module.4.ts b/public/docs/_examples/router/ts/src/app/app-routing.module.4.ts
new file mode 100644
index 0000000000..6835d24a85
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/app-routing.module.4.ts
@@ -0,0 +1,30 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+import { ComposeMessageComponent } from './compose-message.component';
+import { CanDeactivateGuard } from './can-deactivate-guard.service';
+import { PageNotFoundComponent } from './not-found.component';
+
+const appRoutes: Routes = [
+ {
+ path: 'compose',
+ component: ComposeMessageComponent,
+ outlet: 'popup'
+ },
+ { path: '', redirectTo: '/heroes', pathMatch: 'full' },
+ { path: '**', component: PageNotFoundComponent }
+];
+
+@NgModule({
+ imports: [
+ RouterModule.forRoot(appRoutes)
+ ],
+ exports: [
+ RouterModule
+ ],
+ providers: [
+ CanDeactivateGuard
+ ]
+})
+export class AppRoutingModule {}
diff --git a/public/docs/_examples/router/ts/src/app/app-routing.module.5.ts b/public/docs/_examples/router/ts/src/app/app-routing.module.5.ts
new file mode 100644
index 0000000000..2badf7f593
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/app-routing.module.5.ts
@@ -0,0 +1,45 @@
+// #docplaster
+// #docregion
+import { NgModule } from '@angular/core';
+// #docregion import-router
+import { RouterModule, Routes } from '@angular/router';
+// #enddocregion import-router
+
+import { ComposeMessageComponent } from './compose-message.component';
+import { PageNotFoundComponent } from './not-found.component';
+
+import { CanDeactivateGuard } from './can-deactivate-guard.service';
+import { AuthGuard } from './auth-guard.service';
+
+
+const appRoutes: Routes = [
+ {
+ path: 'compose',
+ component: ComposeMessageComponent,
+ outlet: 'popup'
+ },
+// #docregion admin, admin-1
+ {
+ path: 'admin',
+ loadChildren: 'app/admin/admin.module#AdminModule',
+// #enddocregion admin-1
+ canLoad: [AuthGuard]
+// #docregion admin-1
+ },
+// #enddocregion admin, admin-1
+ { path: '', redirectTo: '/heroes', pathMatch: 'full' },
+ { path: '**', component: PageNotFoundComponent }
+];
+
+@NgModule({
+ imports: [
+ RouterModule.forRoot(appRoutes)
+ ],
+ exports: [
+ RouterModule
+ ],
+ providers: [
+ CanDeactivateGuard
+ ]
+})
+export class AppRoutingModule {}
diff --git a/public/docs/_examples/router/ts/src/app/app-routing.module.6.ts b/public/docs/_examples/router/ts/src/app/app-routing.module.6.ts
new file mode 100644
index 0000000000..df2c8c097d
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/app-routing.module.6.ts
@@ -0,0 +1,54 @@
+// #docplaster
+// #docregion, preload-v1
+import { NgModule } from '@angular/core';
+import {
+ RouterModule, Routes,
+// #enddocregion preload-v1
+ PreloadAllModules
+// #docregion preload-v1
+} from '@angular/router';
+
+import { ComposeMessageComponent } from './compose-message.component';
+import { PageNotFoundComponent } from './not-found.component';
+
+import { CanDeactivateGuard } from './can-deactivate-guard.service';
+import { AuthGuard } from './auth-guard.service';
+
+const appRoutes: Routes = [
+ {
+ path: 'compose',
+ component: ComposeMessageComponent,
+ outlet: 'popup'
+ },
+ {
+ path: 'admin',
+ loadChildren: 'app/admin/admin.module#AdminModule',
+ canLoad: [AuthGuard]
+ },
+ {
+ path: 'crisis-center',
+ loadChildren: 'app/crisis-center/crisis-center.module#CrisisCenterModule'
+ },
+ { path: '', redirectTo: '/heroes', pathMatch: 'full' },
+ { path: '**', component: PageNotFoundComponent }
+];
+
+@NgModule({
+ imports: [
+ // #docregion forRoot
+ RouterModule.forRoot(
+ appRoutes
+ // #enddocregion preload-v1
+ , { preloadingStrategy: PreloadAllModules }
+ // #docregion preload-v1
+ )
+ // #enddocregion forRoot
+ ],
+ exports: [
+ RouterModule
+ ],
+ providers: [
+ CanDeactivateGuard
+ ]
+})
+export class AppRoutingModule {}
diff --git a/public/docs/_examples/router/ts/src/app/app-routing.module.ts b/public/docs/_examples/router/ts/src/app/app-routing.module.ts
new file mode 100644
index 0000000000..cc01ced890
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/app-routing.module.ts
@@ -0,0 +1,50 @@
+// #docplaster
+// #docregion, preload-v1
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+import { ComposeMessageComponent } from './compose-message.component';
+import { PageNotFoundComponent } from './not-found.component';
+
+import { CanDeactivateGuard } from './can-deactivate-guard.service';
+import { AuthGuard } from './auth-guard.service';
+import { SelectivePreloadingStrategy } from './selective-preloading-strategy';
+
+const appRoutes: Routes = [
+ {
+ path: 'compose',
+ component: ComposeMessageComponent,
+ outlet: 'popup'
+ },
+ {
+ path: 'admin',
+ loadChildren: 'app/admin/admin.module#AdminModule',
+ canLoad: [AuthGuard]
+ },
+ // #docregion preload-v2
+ {
+ path: 'crisis-center',
+ loadChildren: 'app/crisis-center/crisis-center.module#CrisisCenterModule',
+ data: { preload: true }
+ },
+ // #enddocregion preload-v2
+ { path: '', redirectTo: '/heroes', pathMatch: 'full' },
+ { path: '**', component: PageNotFoundComponent }
+];
+
+@NgModule({
+ imports: [
+ RouterModule.forRoot(
+ appRoutes,
+ { preloadingStrategy: SelectivePreloadingStrategy }
+ )
+ ],
+ exports: [
+ RouterModule
+ ],
+ providers: [
+ CanDeactivateGuard,
+ SelectivePreloadingStrategy
+ ]
+})
+export class AppRoutingModule { }
diff --git a/public/docs/_examples/router/ts/src/app/app.component.1.ts b/public/docs/_examples/router/ts/src/app/app.component.1.ts
new file mode 100644
index 0000000000..21e9aa417d
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/app.component.1.ts
@@ -0,0 +1,18 @@
+/* First version */
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ // #docregion template
+ template: `
+ Angular Router
+
+ Crisis Center
+ Heroes
+
+
+ `
+ // #enddocregion template
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/router/ts/src/app/app.component.2.ts b/public/docs/_examples/router/ts/src/app/app.component.2.ts
new file mode 100644
index 0000000000..ffd4d8dfae
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/app.component.2.ts
@@ -0,0 +1,16 @@
+/* Second Heroes version */
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ template: `
+ Angular Router
+
+ Crisis Center
+ Heroes
+
+
+ `
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/router/ts/src/app/app.component.3.ts b/public/docs/_examples/router/ts/src/app/app.component.3.ts
new file mode 100644
index 0000000000..6013df6321
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/app.component.3.ts
@@ -0,0 +1,48 @@
+/* tslint:disable:no-unused-variable */
+// #docplaster
+import { Component } from '@angular/core';
+import { Router } from '@angular/router';
+
+@Component({
+ selector: 'my-app',
+ /* Typical link
+ // #docregion h-anchor
+ Heroes
+ // #enddocregion h-anchor
+ */
+ /* Incomplete Crisis Center link when CC lacks a default
+ // #docregion cc-anchor-fail
+ // The link now fails with a "non-terminal link" error
+ // #docregion cc-anchor-w-default
+ Crisis Center
+ // #enddocregion cc-anchor-w-default
+ // #enddocregion cc-anchor-fail
+ */
+ /* Crisis Center link when CC lacks a default
+ // #docregion cc-anchor-no-default
+ Crisis Center
+ // #enddocregion cc-anchor-no-default
+ */
+ /* Crisis Center Detail link
+ // #docregion Dragon-anchor
+ Dragon Crisis
+ // #enddocregion Dragon-anchor
+ */
+ /* Crisis Center link with optional query params
+ // #docregion cc-query-params
+ Crisis Center
+ // #enddocregion cc-query-params
+ */
+// #docregion template
+ template: `
+ Angular Router
+
+ Crisis Center
+ Dragon Crisis
+ Shark Crisis
+
+
+ `
+// #enddocregion template
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/router/ts/src/app/app.component.4.ts b/public/docs/_examples/router/ts/src/app/app.component.4.ts
new file mode 100644
index 0000000000..a630703c28
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/app.component.4.ts
@@ -0,0 +1,23 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ // #docregion template
+ template: `
+ Angular Router
+
+ Crisis Center
+ Heroes
+ // #docregion contact-link
+ Contact
+ // #enddocregion contact-link
+
+ // #docregion outlets
+
+
+ // #enddocregion outlets
+ `
+ // #enddocregion template
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/router/ts/src/app/app.component.5.ts b/public/docs/_examples/router/ts/src/app/app.component.5.ts
new file mode 100644
index 0000000000..24162c6136
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/app.component.5.ts
@@ -0,0 +1,20 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ // #docregion template
+ template: `
+ Angular Router
+
+ Crisis Center
+ Heroes
+ Admin
+ Contact
+
+
+
+ `
+ // #enddocregion template
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/router/ts/src/app/app.component.ts b/public/docs/_examples/router/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..a479680cbe
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/app.component.ts
@@ -0,0 +1,23 @@
+// #docplaster
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ // #docregion template
+ template: `
+ Angular Router
+
+ Crisis Center
+ Heroes
+ Admin
+ Login
+ Contact
+
+
+
+ `
+ // #enddocregion template
+})
+export class AppComponent {
+}
diff --git a/public/docs/_examples/router/ts/src/app/app.module.0.ts b/public/docs/_examples/router/ts/src/app/app.module.0.ts
new file mode 100644
index 0000000000..a195dbdd7a
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/app.module.0.ts
@@ -0,0 +1,41 @@
+// NEVER USED. For docs only. Should compile though
+// #docplaster
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+import { HeroListComponent } from './hero-list.component';
+import { CrisisListComponent } from './crisis-list.component';
+import { PageNotFoundComponent } from './not-found.component';
+import { PageNotFoundComponent as HeroDetailComponent } from './not-found.component';
+
+// #docregion
+const appRoutes: Routes = [
+ { path: 'crisis-center', component: CrisisListComponent },
+ { path: 'hero/:id', component: HeroDetailComponent },
+ {
+ path: 'heroes',
+ component: HeroListComponent,
+ data: { title: 'Heroes List' }
+ },
+ { path: '',
+ redirectTo: '/heroes',
+ pathMatch: 'full'
+ },
+ { path: '**', component: PageNotFoundComponent }
+];
+
+@NgModule({
+ imports: [
+ RouterModule.forRoot(appRoutes)
+ // other imports here
+ ],
+// #enddocregion
+/*
+// #docregion
+ ...
+})
+export class AppModule { }
+// #enddocregion
+*/
+})
+export class AppModule0 { }
diff --git a/public/docs/_examples/router/ts/src/app/app.module.1.ts b/public/docs/_examples/router/ts/src/app/app.module.1.ts
new file mode 100644
index 0000000000..32f93b8f79
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/app.module.1.ts
@@ -0,0 +1,49 @@
+// #docplaster
+// #docregion
+// #docregion first-config
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { FormsModule } from '@angular/forms';
+// #docregion import-router
+import { RouterModule, Routes } from '@angular/router';
+// #enddocregion import-router
+
+import { AppComponent } from './app.component';
+import { CrisisListComponent } from './crisis-list.component';
+import { HeroListComponent } from './hero-list.component';
+// #enddocregion first-config
+import { PageNotFoundComponent } from './not-found.component';
+// #docregion first-config
+
+// #docregion appRoutes
+const appRoutes: Routes = [
+ { path: 'crisis-center', component: CrisisListComponent },
+ { path: 'heroes', component: HeroListComponent },
+// #enddocregion first-config
+
+ { path: '', redirectTo: '/heroes', pathMatch: 'full' },
+// #docregion wildcard
+ { path: '**', component: PageNotFoundComponent }
+// #enddocregion wildcard
+// #docregion first-config
+];
+// #enddocregion appRoutes
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ FormsModule,
+ RouterModule.forRoot(appRoutes)
+ ],
+ declarations: [
+ AppComponent,
+ HeroListComponent,
+ CrisisListComponent,
+// #enddocregion first-config
+ PageNotFoundComponent
+// #docregion first-config
+ ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
+// #enddocregion
diff --git a/public/docs/_examples/router/ts/src/app/app.module.2.ts b/public/docs/_examples/router/ts/src/app/app.module.2.ts
new file mode 100644
index 0000000000..2ba739168c
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/app.module.2.ts
@@ -0,0 +1,31 @@
+// #docplaster
+// #docregion
+// #docregion hero-import
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { FormsModule } from '@angular/forms';
+
+import { AppComponent } from './app.component';
+import { AppRoutingModule } from './app-routing.module';
+
+import { CrisisListComponent } from './crisis-list.component';
+import { HeroListComponent } from './hero-list.component';
+import { PageNotFoundComponent } from './not-found.component';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ FormsModule,
+ AppRoutingModule
+ ],
+ declarations: [
+ AppComponent,
+ HeroListComponent,
+ CrisisListComponent,
+ PageNotFoundComponent
+ ],
+ bootstrap: [ AppComponent ]
+})
+// #enddocregion hero-import
+export class AppModule { }
+// #enddocregion
diff --git a/public/docs/_examples/router/ts/src/app/app.module.3.ts b/public/docs/_examples/router/ts/src/app/app.module.3.ts
new file mode 100644
index 0000000000..862faf1c51
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/app.module.3.ts
@@ -0,0 +1,29 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { FormsModule } from '@angular/forms';
+
+import { AppComponent } from './app.component';
+import { AppRoutingModule } from './app-routing.module';
+import { HeroesModule } from './heroes/heroes.module';
+
+import { CrisisListComponent } from './crisis-list.component';
+import { PageNotFoundComponent } from './not-found.component';
+
+@NgModule({
+// #docregion module-imports
+ imports: [
+ BrowserModule,
+ FormsModule,
+ HeroesModule,
+ AppRoutingModule
+ ],
+// #enddocregion module-imports
+ declarations: [
+ AppComponent,
+ CrisisListComponent,
+ PageNotFoundComponent
+ ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/router/ts/src/app/app.module.4.ts b/public/docs/_examples/router/ts/src/app/app.module.4.ts
new file mode 100644
index 0000000000..4825572361
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/app.module.4.ts
@@ -0,0 +1,46 @@
+// #docplaster
+// #docregion
+// #docregion crisis-center-module, admin-module
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+
+import { AppComponent } from './app.component';
+import { PageNotFoundComponent } from './not-found.component';
+
+import { AppRoutingModule } from './app-routing.module';
+import { HeroesModule } from './heroes/heroes.module';
+import { CrisisCenterModule } from './crisis-center/crisis-center.module';
+// #enddocregion crisis-center-module, admin-module
+import { ComposeMessageComponent } from './compose-message.component';
+// #docregion admin-module
+import { AdminModule } from './admin/admin.module';
+// #docregion crisis-center-module
+
+import { DialogService } from './dialog.service';
+
+@NgModule({
+ imports: [
+ CommonModule,
+ FormsModule,
+ HeroesModule,
+ CrisisCenterModule,
+// #enddocregion crisis-center-module
+ AdminModule,
+// #docregion crisis-center-module
+ AppRoutingModule
+ ],
+ declarations: [
+ AppComponent,
+// #enddocregion admin-module, crisis-center-module
+ ComposeMessageComponent,
+// #docregion admin-module, crisis-center-module
+ PageNotFoundComponent
+ ],
+ providers: [
+ DialogService
+ ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
+// #enddocregion
diff --git a/public/docs/_examples/router/ts/src/app/app.module.5.ts b/public/docs/_examples/router/ts/src/app/app.module.5.ts
new file mode 100644
index 0000000000..ad34668cea
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/app.module.5.ts
@@ -0,0 +1,38 @@
+// #docplaster
+// #docregion
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+
+import { AppComponent } from './app.component';
+import { AppRoutingModule } from './app-routing.module';
+
+import { HeroesModule } from './heroes/heroes.module';
+import { CrisisCenterModule } from './crisis-center/crisis-center.module';
+
+import { ComposeMessageComponent } from './compose-message.component';
+import { PageNotFoundComponent } from './not-found.component';
+
+import { AdminModule } from './admin/admin.module';
+import { DialogService } from './dialog.service';
+
+@NgModule({
+ imports: [
+ CommonModule,
+ FormsModule,
+ HeroesModule,
+ CrisisCenterModule,
+ AdminModule,
+ AppRoutingModule
+ ],
+ declarations: [
+ AppComponent,
+ ComposeMessageComponent,
+ PageNotFoundComponent
+ ],
+ providers: [
+ DialogService
+ ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/router/ts/src/app/app.module.6.ts b/public/docs/_examples/router/ts/src/app/app.module.6.ts
new file mode 100644
index 0000000000..4cb0b1fdd5
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/app.module.6.ts
@@ -0,0 +1,29 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { FormsModule } from '@angular/forms';
+import { Routes, RouterModule } from '@angular/router';
+
+import { AppComponent } from './app.component';
+import { PageNotFoundComponent } from './not-found.component';
+
+const routes: Routes = [
+
+];
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ FormsModule,
+ RouterModule.forRoot(routes, { useHash: true }) // .../#/crisis-center/
+ ],
+ declarations: [
+ AppComponent,
+ PageNotFoundComponent
+ ],
+ providers: [
+
+ ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/router/ts/src/app/app.module.7.ts b/public/docs/_examples/router/ts/src/app/app.module.7.ts
new file mode 100644
index 0000000000..b6ca81ddea
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/app.module.7.ts
@@ -0,0 +1,38 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { FormsModule } from '@angular/forms';
+
+import { AppComponent } from './app.component';
+import { AppRoutingModule } from './app-routing.module';
+
+import { HeroesModule } from './heroes/heroes.module';
+import { CrisisCenterModule } from './crisis-center/crisis-center.module';
+import { ComposeMessageComponent } from './compose-message.component';
+import { LoginRoutingModule } from './login-routing.module';
+import { LoginComponent } from './login.component';
+import { PageNotFoundComponent } from './not-found.component';
+
+import { DialogService } from './dialog.service';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ FormsModule,
+ HeroesModule,
+ CrisisCenterModule,
+ LoginRoutingModule,
+ AppRoutingModule
+ ],
+ declarations: [
+ AppComponent,
+ ComposeMessageComponent,
+ LoginComponent,
+ PageNotFoundComponent
+ ],
+ providers: [
+ DialogService
+ ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/router/ts/src/app/app.module.ts b/public/docs/_examples/router/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..dcf3401ded
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/app.module.ts
@@ -0,0 +1,56 @@
+// #docplaster
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { FormsModule } from '@angular/forms';
+// #docregion animations-module
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+
+// #enddocregion animations-module
+// #docregion inspect-config
+import { Router } from '@angular/router';
+
+// #enddocregion inspect-config
+import { AppComponent } from './app.component';
+import { AppRoutingModule } from './app-routing.module';
+
+import { HeroesModule } from './heroes/heroes.module';
+import { ComposeMessageComponent } from './compose-message.component';
+import { LoginRoutingModule } from './login-routing.module';
+import { LoginComponent } from './login.component';
+import { PageNotFoundComponent } from './not-found.component';
+
+import { DialogService } from './dialog.service';
+
+// #docregion animations-module
+@NgModule({
+ imports: [
+ // #enddocregion animations-module
+ BrowserModule,
+ FormsModule,
+ HeroesModule,
+ LoginRoutingModule,
+ AppRoutingModule,
+ // #docregion animations-module
+ BrowserAnimationsModule
+ // #enddocregion animations-module
+ ],
+ declarations: [
+ AppComponent,
+ ComposeMessageComponent,
+ LoginComponent,
+ PageNotFoundComponent
+ ],
+ providers: [
+ DialogService
+ ],
+ bootstrap: [ AppComponent ]
+})
+// #docregion inspect-config
+export class AppModule {
+ // Diagnostic only: inspect router configuration
+ constructor(router: Router) {
+ console.log('Routes: ', JSON.stringify(router.config, undefined, 2));
+ }
+}
+// #enddocregion inspect-config
diff --git a/public/docs/_examples/router/ts/src/app/auth-guard.service.1.ts b/public/docs/_examples/router/ts/src/app/auth-guard.service.1.ts
new file mode 100644
index 0000000000..c824bcb208
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/auth-guard.service.1.ts
@@ -0,0 +1,11 @@
+// #docregion
+import { Injectable } from '@angular/core';
+import { CanActivate } from '@angular/router';
+
+@Injectable()
+export class AuthGuard implements CanActivate {
+ canActivate() {
+ console.log('AuthGuard#canActivate called');
+ return true;
+ }
+}
diff --git a/public/docs/_examples/router/ts/src/app/auth-guard.service.2.ts b/public/docs/_examples/router/ts/src/app/auth-guard.service.2.ts
new file mode 100644
index 0000000000..8fd00e151a
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/auth-guard.service.2.ts
@@ -0,0 +1,37 @@
+// #docregion
+import { Injectable } from '@angular/core';
+import {
+ CanActivate, Router,
+ ActivatedRouteSnapshot,
+ RouterStateSnapshot
+} from '@angular/router';
+import { AuthService } from './auth.service';
+
+@Injectable()
+export class AuthGuard implements CanActivate {
+ constructor(private authService: AuthService, private router: Router) {}
+
+ canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
+ let url: string = state.url;
+
+ return this.checkLogin(url);
+ }
+
+ checkLogin(url: string): boolean {
+ if (this.authService.isLoggedIn) { return true; }
+
+ // Store the attempted URL for redirecting
+ this.authService.redirectUrl = url;
+
+ // Navigate to the login page with extras
+ this.router.navigate(['/login']);
+ return false;
+ }
+}
+// #enddocregion
+
+/*
+// #docregion can-load-interface
+export class AuthGuard implements CanActivate, CanLoad {
+// #enddocregion can-load-interface
+*/
diff --git a/public/docs/_examples/router/ts/src/app/auth-guard.service.3.ts b/public/docs/_examples/router/ts/src/app/auth-guard.service.3.ts
new file mode 100644
index 0000000000..dd89006411
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/auth-guard.service.3.ts
@@ -0,0 +1,39 @@
+// #docregion
+// #docregion can-activate-child
+import { Injectable } from '@angular/core';
+import {
+ CanActivate, Router,
+ ActivatedRouteSnapshot,
+ RouterStateSnapshot,
+ CanActivateChild
+} from '@angular/router';
+import { AuthService } from './auth.service';
+
+@Injectable()
+export class AuthGuard implements CanActivate, CanActivateChild {
+ constructor(private authService: AuthService, private router: Router) {}
+
+ canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
+ let url: string = state.url;
+
+ return this.checkLogin(url);
+ }
+
+ canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
+ return this.canActivate(route, state);
+ }
+
+// #enddocregion can-activate-child
+ checkLogin(url: string): boolean {
+ if (this.authService.isLoggedIn) { return true; }
+
+ // Store the attempted URL for redirecting
+ this.authService.redirectUrl = url;
+
+ // Navigate to the login page
+ this.router.navigate(['/login']);
+ return false;
+ }
+// #docregion can-activate-child
+}
+// #enddocregion
diff --git a/public/docs/_examples/router/ts/src/app/auth-guard.service.4.ts b/public/docs/_examples/router/ts/src/app/auth-guard.service.4.ts
new file mode 100644
index 0000000000..5d239a8432
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/auth-guard.service.4.ts
@@ -0,0 +1,47 @@
+// #docplaster
+// #docregion
+import { Injectable } from '@angular/core';
+import {
+ CanActivate, Router,
+ ActivatedRouteSnapshot,
+ RouterStateSnapshot,
+ CanActivateChild,
+ NavigationExtras
+} from '@angular/router';
+import { AuthService } from './auth.service';
+
+@Injectable()
+export class AuthGuard implements CanActivate, CanActivateChild {
+ constructor(private authService: AuthService, private router: Router) {}
+
+ canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
+ let url: string = state.url;
+
+ return this.checkLogin(url);
+ }
+
+ canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
+ return this.canActivate(route, state);
+ }
+
+ checkLogin(url: string): boolean {
+ if (this.authService.isLoggedIn) { return true; }
+
+ // Store the attempted URL for redirecting
+ this.authService.redirectUrl = url;
+
+ // Create a dummy session id
+ let sessionId = 123456789;
+
+ // Set our navigation extras object
+ // that contains our global query params and fragment
+ let navigationExtras: NavigationExtras = {
+ queryParams: { 'session_id': sessionId },
+ fragment: 'anchor'
+ };
+
+ // Navigate to the login page with extras
+ this.router.navigate(['/login'], navigationExtras);
+ return false;
+ }
+}
diff --git a/public/docs/_examples/router/ts/src/app/auth-guard.service.ts b/public/docs/_examples/router/ts/src/app/auth-guard.service.ts
new file mode 100644
index 0000000000..a32b5cc2b8
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/auth-guard.service.ts
@@ -0,0 +1,56 @@
+// #docplaster
+import { Injectable } from '@angular/core';
+import {
+ CanActivate, Router,
+ ActivatedRouteSnapshot,
+ RouterStateSnapshot,
+ CanActivateChild,
+ NavigationExtras,
+ CanLoad, Route
+} from '@angular/router';
+import { AuthService } from './auth.service';
+
+@Injectable()
+export class AuthGuard implements CanActivate, CanActivateChild, CanLoad {
+ constructor(private authService: AuthService, private router: Router) {}
+
+ canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
+ let url: string = state.url;
+
+ return this.checkLogin(url);
+ }
+
+ canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
+ return this.canActivate(route, state);
+ }
+
+// #docregion, canLoad
+ canLoad(route: Route): boolean {
+ let url = `/${route.path}`;
+
+ return this.checkLogin(url);
+ }
+// #enddocregion canLoad
+
+ checkLogin(url: string): boolean {
+ if (this.authService.isLoggedIn) { return true; }
+
+ // Store the attempted URL for redirecting
+ this.authService.redirectUrl = url;
+
+ // Create a dummy session id
+ let sessionId = 123456789;
+
+ // Set our navigation extras object
+ // that contains our global query params and fragment
+ let navigationExtras: NavigationExtras = {
+ queryParams: { 'session_id': sessionId },
+ fragment: 'anchor'
+ };
+
+ // Navigate to the login page with extras
+ this.router.navigate(['/login'], navigationExtras);
+ return false;
+ }
+// #docregion admin-can-load
+}
diff --git a/public/docs/_examples/router/ts/src/app/auth.service.ts b/public/docs/_examples/router/ts/src/app/auth.service.ts
new file mode 100644
index 0000000000..f86a80ebfe
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/auth.service.ts
@@ -0,0 +1,23 @@
+// #docregion
+import { Injectable } from '@angular/core';
+
+import { Observable } from 'rxjs/Observable';
+import 'rxjs/add/observable/of';
+import 'rxjs/add/operator/do';
+import 'rxjs/add/operator/delay';
+
+@Injectable()
+export class AuthService {
+ isLoggedIn: boolean = false;
+
+ // store the URL so we can redirect after logging in
+ redirectUrl: string;
+
+ login(): Observable {
+ return Observable.of(true).delay(1000).do(val => this.isLoggedIn = true);
+ }
+
+ logout(): void {
+ this.isLoggedIn = false;
+ }
+}
diff --git a/public/docs/_examples/router/ts/src/app/can-deactivate-guard.service.1.ts b/public/docs/_examples/router/ts/src/app/can-deactivate-guard.service.1.ts
new file mode 100644
index 0000000000..0b7c8247cf
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/can-deactivate-guard.service.1.ts
@@ -0,0 +1,31 @@
+// #docregion
+import { Injectable } from '@angular/core';
+import { CanDeactivate,
+ ActivatedRouteSnapshot,
+ RouterStateSnapshot } from '@angular/router';
+
+import { CrisisDetailComponent } from './crisis-center/crisis-detail.component';
+
+@Injectable()
+export class CanDeactivateGuard implements CanDeactivate {
+
+ canDeactivate(
+ component: CrisisDetailComponent,
+ route: ActivatedRouteSnapshot,
+ state: RouterStateSnapshot
+ ): Promise | boolean {
+ // Get the Crisis Center ID
+ console.log(route.params['id']);
+
+ // Get the current URL
+ console.log(state.url);
+
+ // Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged
+ if (!component.crisis || component.crisis.name === component.editName) {
+ return true;
+ }
+ // Otherwise ask the user with the dialog service and return its
+ // promise which resolves to true or false when the user decides
+ return component.dialogService.confirm('Discard changes?');
+ }
+}
diff --git a/public/docs/_examples/router/ts/src/app/can-deactivate-guard.service.ts b/public/docs/_examples/router/ts/src/app/can-deactivate-guard.service.ts
new file mode 100644
index 0000000000..44da69f9c7
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/can-deactivate-guard.service.ts
@@ -0,0 +1,15 @@
+// #docregion
+import { Injectable } from '@angular/core';
+import { CanDeactivate } from '@angular/router';
+import { Observable } from 'rxjs/Observable';
+
+export interface CanComponentDeactivate {
+ canDeactivate: () => Observable | Promise | boolean;
+}
+
+@Injectable()
+export class CanDeactivateGuard implements CanDeactivate {
+ canDeactivate(component: CanComponentDeactivate) {
+ return component.canDeactivate ? component.canDeactivate() : true;
+ }
+}
diff --git a/public/docs/_examples/router/ts/src/app/compose-message.component.html b/public/docs/_examples/router/ts/src/app/compose-message.component.html
new file mode 100644
index 0000000000..f0b964e6ac
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/compose-message.component.html
@@ -0,0 +1,17 @@
+
+Contact Crisis Center
+
+ {{ details }}
+
+
+
+ Send
+ Cancel
+
diff --git a/public/docs/_examples/router/ts/src/app/compose-message.component.ts b/public/docs/_examples/router/ts/src/app/compose-message.component.ts
new file mode 100644
index 0000000000..17a0953378
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/compose-message.component.ts
@@ -0,0 +1,43 @@
+// #docregion
+import { Component, HostBinding } from '@angular/core';
+import { Router } from '@angular/router';
+
+import { slideInDownAnimation } from './animations';
+
+@Component({
+ templateUrl: './compose-message.component.html',
+ styles: [ ':host { position: relative; bottom: 10%; }' ],
+ animations: [ slideInDownAnimation ]
+})
+export class ComposeMessageComponent {
+ @HostBinding('@routeAnimation') routeAnimation = true;
+ @HostBinding('style.display') display = 'block';
+ @HostBinding('style.position') position = 'absolute';
+
+ details: string;
+ sending: boolean = false;
+
+ constructor(private router: Router) {}
+
+ send() {
+ this.sending = true;
+ this.details = 'Sending Message...';
+
+ setTimeout(() => {
+ this.sending = false;
+ this.closePopup();
+ }, 1000);
+ }
+
+ cancel() {
+ this.closePopup();
+ }
+
+ // #docregion closePopup
+ closePopup() {
+ // Providing a `null` value to the named outlet
+ // clears the contents of the named outlet
+ this.router.navigate([{ outlets: { popup: null }}]);
+ }
+ // #enddocregion closePopup
+}
diff --git a/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center-home.component.ts b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center-home.component.ts
new file mode 100644
index 0000000000..a71d485c02
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center-home.component.ts
@@ -0,0 +1,13 @@
+// #docregion
+// #docplaster
+import { Component } from '@angular/core';
+
+// #docregion minus-imports
+@Component({
+ template: `
+ Welcome to the Crisis Center
+ `
+})
+export class CrisisCenterHomeComponent { }
+// #enddocregion minus-imports
+// #enddocregion
diff --git a/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center-routing.module.1.ts b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center-routing.module.1.ts
new file mode 100644
index 0000000000..e646f467d1
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center-routing.module.1.ts
@@ -0,0 +1,44 @@
+// #docplaster
+// #docregion
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+import { CrisisCenterHomeComponent } from './crisis-center-home.component';
+import { CrisisListComponent } from './crisis-list.component';
+import { CrisisCenterComponent } from './crisis-center.component';
+import { CrisisDetailComponent } from './crisis-detail.component';
+
+// #docregion routes
+const crisisCenterRoutes: Routes = [
+ {
+ path: 'crisis-center',
+ component: CrisisCenterComponent,
+ children: [
+ {
+ path: '',
+ component: CrisisListComponent,
+ children: [
+ {
+ path: ':id',
+ component: CrisisDetailComponent
+ },
+ {
+ path: '',
+ component: CrisisCenterHomeComponent
+ }
+ ]
+ }
+ ]
+ }
+];
+
+@NgModule({
+ imports: [
+ RouterModule.forChild(crisisCenterRoutes)
+ ],
+ exports: [
+ RouterModule
+ ]
+})
+export class CrisisCenterRoutingModule { }
+// #enddocregion
diff --git a/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center-routing.module.2.ts b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center-routing.module.2.ts
new file mode 100644
index 0000000000..9e9b514968
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center-routing.module.2.ts
@@ -0,0 +1,72 @@
+// #docplaster
+// #docregion routes
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+import { CrisisCenterHomeComponent } from './crisis-center-home.component';
+import { CrisisListComponent } from './crisis-list.component';
+import { CrisisCenterComponent } from './crisis-center.component';
+import { CrisisDetailComponent } from './crisis-detail.component';
+// #enddocregion routes
+
+// #docregion can-deactivate-guard
+import { CanDeactivateGuard } from '../can-deactivate-guard.service';
+// #enddocregion can-deactivate-guard
+// #docregion crisis-detail-resolver
+import { CrisisDetailResolver } from './crisis-detail-resolver.service';
+
+// #enddocregion crisis-detail-resolver
+// #docregion routes
+
+const crisisCenterRoutes: Routes = [
+// #enddocregion routes
+ // #docregion redirect, routes
+ {
+ path: '',
+ redirectTo: '/crisis-center',
+ pathMatch: 'full'
+ },
+ // #enddocregion redirect, routes
+ // #docregion routes
+ {
+ path: 'crisis-center',
+ component: CrisisCenterComponent,
+ children: [
+ {
+ path: '',
+ component: CrisisListComponent,
+ children: [
+ {
+ path: ':id',
+ component: CrisisDetailComponent,
+ // #enddocregion routes
+ // #docregion can-deactivate-guard
+ canDeactivate: [CanDeactivateGuard],
+ // #enddocregion can-deactivate-guard
+ // #docregion crisis-detail-resolver
+ resolve: {
+ crisis: CrisisDetailResolver
+ }
+ // #enddocregion crisis-detail-resolver
+ // #docregion routes
+ },
+ {
+ path: '',
+ component: CrisisCenterHomeComponent
+ }
+ ]
+ }
+ ]
+ }
+ // #enddocregion routes
+];
+
+@NgModule({
+ imports: [
+ RouterModule.forChild(crisisCenterRoutes)
+ ],
+ exports: [
+ RouterModule
+ ]
+})
+export class CrisisCenterRoutingModule { }
diff --git a/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center-routing.module.3.ts b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center-routing.module.3.ts
new file mode 100644
index 0000000000..6d605dbe84
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center-routing.module.3.ts
@@ -0,0 +1,52 @@
+// #docplaster
+// #docregion
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+import { CrisisCenterHomeComponent } from './crisis-center-home.component';
+import { CrisisListComponent } from './crisis-list.component';
+import { CrisisCenterComponent } from './crisis-center.component';
+import { CrisisDetailComponent } from './crisis-detail.component';
+
+// #docregion can-deactivate-guard
+import { CanDeactivateGuard } from '../can-deactivate-guard.service';
+
+const crisisCenterRoutes: Routes = [
+ {
+ path: '',
+ redirectTo: '/crisis-center',
+ pathMatch: 'full'
+ },
+ {
+ path: 'crisis-center',
+ component: CrisisCenterComponent,
+ children: [
+ {
+ path: '',
+ component: CrisisListComponent,
+ children: [
+ {
+ path: ':id',
+ component: CrisisDetailComponent,
+ canDeactivate: [CanDeactivateGuard]
+ },
+ {
+ path: '',
+ component: CrisisCenterHomeComponent
+ }
+ ]
+ }
+ ]
+ }
+];
+
+@NgModule({
+ imports: [
+ RouterModule.forChild(crisisCenterRoutes)
+ ],
+ exports: [
+ RouterModule
+ ]
+})
+export class CrisisCenterRoutingModule { }
+// #enddocregion
diff --git a/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center-routing.module.4.ts b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center-routing.module.4.ts
new file mode 100644
index 0000000000..b7ac88e852
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center-routing.module.4.ts
@@ -0,0 +1,65 @@
+// #docplaster
+// #docregion
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+import { CrisisCenterHomeComponent } from './crisis-center-home.component';
+import { CrisisListComponent } from './crisis-list.component';
+import { CrisisCenterComponent } from './crisis-center.component';
+import { CrisisDetailComponent } from './crisis-detail.component';
+
+import { CanDeactivateGuard } from '../can-deactivate-guard.service';
+
+// #docregion crisis-detail-resolver
+import { CrisisDetailResolver } from './crisis-detail-resolver.service';
+
+// #enddocregion crisis-detail-resolver
+const crisisCenterRoutes: Routes = [
+ // #docregion redirect
+ {
+ path: '',
+ redirectTo: '/crisis-center',
+ pathMatch: 'full'
+ },
+ // #enddocregion redirect
+ {
+ path: 'crisis-center',
+ component: CrisisCenterComponent,
+ children: [
+ {
+ path: '',
+ component: CrisisListComponent,
+ children: [
+ {
+ path: ':id',
+ component: CrisisDetailComponent,
+ canDeactivate: [CanDeactivateGuard],
+ resolve: {
+ crisis: CrisisDetailResolver
+ }
+ },
+ {
+ path: '',
+ component: CrisisCenterHomeComponent
+ }
+ ]
+ }
+ ]
+ }
+];
+
+// #docregion crisis-detail-resolver
+@NgModule({
+ imports: [
+ RouterModule.forChild(crisisCenterRoutes)
+ ],
+ exports: [
+ RouterModule
+ ],
+ providers: [
+ CrisisDetailResolver
+ ]
+})
+export class CrisisCenterRoutingModule { }
+// #enddocregion crisis-detail-resolver
+// #enddocregion
diff --git a/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center-routing.module.ts b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center-routing.module.ts
new file mode 100644
index 0000000000..c01d592455
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center-routing.module.ts
@@ -0,0 +1,53 @@
+// #docplaster
+// #docregion
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+import { CrisisCenterHomeComponent } from './crisis-center-home.component';
+import { CrisisListComponent } from './crisis-list.component';
+import { CrisisCenterComponent } from './crisis-center.component';
+import { CrisisDetailComponent } from './crisis-detail.component';
+
+import { CanDeactivateGuard } from '../can-deactivate-guard.service';
+import { CrisisDetailResolver } from './crisis-detail-resolver.service';
+
+const crisisCenterRoutes: Routes = [
+ {
+ path: '',
+ component: CrisisCenterComponent,
+ children: [
+ {
+ path: '',
+ component: CrisisListComponent,
+ children: [
+ {
+ path: ':id',
+ component: CrisisDetailComponent,
+ canDeactivate: [CanDeactivateGuard],
+ resolve: {
+ crisis: CrisisDetailResolver
+ }
+ },
+ {
+ path: '',
+ component: CrisisCenterHomeComponent
+ }
+ ]
+ }
+ ]
+ }
+];
+
+@NgModule({
+ imports: [
+ RouterModule.forChild(crisisCenterRoutes)
+ ],
+ exports: [
+ RouterModule
+ ],
+ providers: [
+ CrisisDetailResolver
+ ]
+})
+export class CrisisCenterRoutingModule { }
+// #enddocregion
diff --git a/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center.component.ts b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center.component.ts
new file mode 100644
index 0000000000..31d1790f45
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center.component.ts
@@ -0,0 +1,14 @@
+// #docregion
+// #docplaster
+import { Component } from '@angular/core';
+
+// #docregion minus-imports
+@Component({
+ template: `
+ CRISIS CENTER
+
+ `
+})
+export class CrisisCenterComponent { }
+// #enddocregion minus-imports
+// #enddocregion
diff --git a/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center.module.1.ts b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center.module.1.ts
new file mode 100644
index 0000000000..5a3e45f58f
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center.module.1.ts
@@ -0,0 +1,36 @@
+// #docplaster
+// #docregion
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+import { CommonModule } from '@angular/common';
+
+import { CrisisService } from './crisis.service';
+
+import { CrisisCenterComponent } from './crisis-center.component';
+import { CrisisListComponent } from './crisis-list.component';
+import { CrisisCenterHomeComponent } from './crisis-center-home.component';
+import { CrisisDetailComponent } from './crisis-detail.component';
+
+import { CrisisCenterRoutingModule } from './crisis-center-routing.module';
+
+@NgModule({
+ imports: [
+ CommonModule,
+ FormsModule,
+ CrisisCenterRoutingModule
+ ],
+ declarations: [
+ CrisisCenterComponent,
+ CrisisListComponent,
+ CrisisCenterHomeComponent,
+ CrisisDetailComponent
+ ],
+
+ // #docregion providers
+ providers: [
+ CrisisService
+ ]
+ // #enddocregion providers
+})
+export class CrisisCenterModule {}
+// #enddocregion
diff --git a/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center.module.ts b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center.module.ts
new file mode 100644
index 0000000000..4061ceac60
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-center.module.ts
@@ -0,0 +1,35 @@
+// #docplaster
+// #docregion
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+import { CommonModule } from '@angular/common';
+
+import { CrisisService } from './crisis.service';
+
+import { CrisisCenterComponent } from './crisis-center.component';
+import { CrisisListComponent } from './crisis-list.component';
+import { CrisisCenterHomeComponent } from './crisis-center-home.component';
+import { CrisisDetailComponent } from './crisis-detail.component';
+
+import { CrisisCenterRoutingModule } from './crisis-center-routing.module';
+
+@NgModule({
+ imports: [
+ CommonModule,
+ FormsModule,
+ CrisisCenterRoutingModule
+ ],
+ declarations: [
+ CrisisCenterComponent,
+ CrisisListComponent,
+ CrisisCenterHomeComponent,
+ CrisisDetailComponent
+ ],
+ providers: [
+ CrisisService
+ ]
+})
+// #docregion crisis-center-module-export
+export class CrisisCenterModule {}
+// #enddocregion crisis-center-module-export
+// #enddocregion
diff --git a/public/docs/_examples/router/ts/src/app/crisis-center/crisis-detail-resolver.service.ts b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-detail-resolver.service.ts
new file mode 100644
index 0000000000..94b4cd33e7
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-detail-resolver.service.ts
@@ -0,0 +1,24 @@
+// #docregion
+import { Injectable } from '@angular/core';
+import { Router, Resolve, RouterStateSnapshot,
+ ActivatedRouteSnapshot } from '@angular/router';
+
+import { Crisis, CrisisService } from './crisis.service';
+
+@Injectable()
+export class CrisisDetailResolver implements Resolve {
+ constructor(private cs: CrisisService, private router: Router) {}
+
+ resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise {
+ let id = route.params['id'];
+
+ return this.cs.getCrisis(id).then(crisis => {
+ if (crisis) {
+ return crisis;
+ } else { // id not found
+ this.router.navigate(['/crisis-center']);
+ return null;
+ }
+ });
+ }
+}
diff --git a/public/docs/_examples/router/ts/src/app/crisis-center/crisis-detail.component.1.ts b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-detail.component.1.ts
new file mode 100644
index 0000000000..d6fa27f629
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-detail.component.1.ts
@@ -0,0 +1,87 @@
+// #docplaster
+// #docregion
+import 'rxjs/add/operator/switchMap';
+import { Component, OnInit, HostBinding } from '@angular/core';
+import { ActivatedRoute, Router, Params } from '@angular/router';
+
+import { slideInDownAnimation } from '../animations';
+import { Crisis, CrisisService } from './crisis.service';
+import { DialogService } from '../dialog.service';
+
+@Component({
+ template: `
+
+
"{{ editName }}"
+
+ Id: {{ crisis.id }}
+
+ Name:
+
+
+
+ Save
+ Cancel
+
+
+ `,
+ styles: ['input {width: 20em}'],
+ animations: [ slideInDownAnimation ]
+})
+export class CrisisDetailComponent implements OnInit {
+ @HostBinding('@routeAnimation') routeAnimation = true;
+ @HostBinding('style.display') display = 'block';
+ @HostBinding('style.position') position = 'absolute';
+
+ crisis: Crisis;
+ editName: string;
+
+ constructor(
+ private service: CrisisService,
+ private router: Router,
+ private route: ActivatedRoute,
+ public dialogService: DialogService
+ ) {}
+
+ // #docregion ngOnInit
+ ngOnInit() {
+ this.route.params
+ .switchMap((params: Params) => this.service.getCrisis(params['id']))
+ .subscribe((crisis: Crisis) => {
+ if (crisis) {
+ this.editName = crisis.name;
+ this.crisis = crisis;
+ } else { // id not found
+ this.gotoCrises();
+ }
+ });
+ }
+ // #enddocregion ngOnInit
+
+ cancel() {
+ this.gotoCrises();
+ }
+
+ save() {
+ this.crisis.name = this.editName;
+ this.gotoCrises();
+ }
+
+ canDeactivate(): Promise | boolean {
+ // Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged
+ if (!this.crisis || this.crisis.name === this.editName) {
+ return true;
+ }
+ // Otherwise ask the user with the dialog service and return its
+ // promise which resolves to true or false when the user decides
+ return this.dialogService.confirm('Discard changes?');
+ }
+
+ gotoCrises() {
+ let crisisId = this.crisis ? this.crisis.id : null;
+ // Pass along the crisis id if available
+ // so that the CrisisListComponent can select that crisis.
+ // Add a totally useless `foo` parameter for kicks.
+ // Relative navigation back to the crises
+ this.router.navigate(['../', { id: crisisId, foo: 'foo' }], { relativeTo: this.route });
+ }
+}
diff --git a/public/docs/_examples/router/ts/src/app/crisis-center/crisis-detail.component.ts b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-detail.component.ts
new file mode 100644
index 0000000000..f0939b47a8
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-detail.component.ts
@@ -0,0 +1,86 @@
+// #docplaster
+// #docregion
+import { Component, OnInit, HostBinding } from '@angular/core';
+import { ActivatedRoute, Router } from '@angular/router';
+
+import { slideInDownAnimation } from '../animations';
+import { Crisis } from './crisis.service';
+import { DialogService } from '../dialog.service';
+
+@Component({
+ template: `
+
+
"{{ editName }}"
+
+ Id: {{ crisis.id }}
+
+ Name:
+
+
+
+ Save
+ Cancel
+
+
+ `,
+ styles: ['input {width: 20em}'],
+ animations: [ slideInDownAnimation ]
+})
+export class CrisisDetailComponent implements OnInit {
+ @HostBinding('@routeAnimation') routeAnimation = true;
+ @HostBinding('style.display') display = 'block';
+ @HostBinding('style.position') position = 'absolute';
+
+ crisis: Crisis;
+ editName: string;
+
+ constructor(
+ private route: ActivatedRoute,
+ private router: Router,
+ public dialogService: DialogService
+ ) {}
+
+// #docregion ngOnInit
+ ngOnInit() {
+ this.route.data
+ .subscribe((data: { crisis: Crisis }) => {
+ this.editName = data.crisis.name;
+ this.crisis = data.crisis;
+ });
+ }
+// #enddocregion ngOnInit
+
+ // #docregion cancel-save
+ cancel() {
+ this.gotoCrises();
+ }
+
+ save() {
+ this.crisis.name = this.editName;
+ this.gotoCrises();
+ }
+ // #enddocregion cancel-save
+
+ // #docregion canDeactivate
+ canDeactivate(): Promise | boolean {
+ // Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged
+ if (!this.crisis || this.crisis.name === this.editName) {
+ return true;
+ }
+ // Otherwise ask the user with the dialog service and return its
+ // promise which resolves to true or false when the user decides
+ return this.dialogService.confirm('Discard changes?');
+ }
+ // #enddocregion canDeactivate
+
+ gotoCrises() {
+ let crisisId = this.crisis ? this.crisis.id : null;
+ // Pass along the crisis id if available
+ // so that the CrisisListComponent can select that crisis.
+ // Add a totally useless `foo` parameter for kicks.
+ // #docregion gotoCrises-navigate
+ // Relative navigation back to the crises
+ this.router.navigate(['../', { id: crisisId, foo: 'foo' }], { relativeTo: this.route });
+ // #enddocregion gotoCrises-navigate
+ }
+}
diff --git a/public/docs/_examples/router/ts/src/app/crisis-center/crisis-list.component.1.ts b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-list.component.1.ts
new file mode 100644
index 0000000000..0000dde082
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-list.component.1.ts
@@ -0,0 +1,44 @@
+import 'rxjs/add/operator/do';
+import 'rxjs/add/operator/switchMap';
+import { Component, OnInit } from '@angular/core';
+import { ActivatedRoute, Router, Params } from '@angular/router';
+
+import { Crisis, CrisisService } from './crisis.service';
+import { Observable } from 'rxjs/Observable';
+
+@Component({
+ // #docregion relative-navigation-router-link
+ template: `
+ `
+ // #enddocregion relative-navigation-router-link
+})
+export class CrisisListComponent implements OnInit {
+ crises: Observable;
+ selectedId: number;
+
+ constructor(
+ private service: CrisisService,
+ private route: ActivatedRoute,
+ private router: Router
+ ) {}
+
+ ngOnInit() {
+ this.crises = this.route.params
+ .switchMap((params: Params) => {
+ this.selectedId = +params['id'];
+ return this.service.getCrises();
+ });
+ }
+
+ isSelected(crisis: Crisis) {
+ return crisis.id === this.selectedId;
+ }
+}
diff --git a/public/docs/_examples/router/ts/src/app/crisis-center/crisis-list.component.ts b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-list.component.ts
new file mode 100644
index 0000000000..4498a55c0f
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/crisis-center/crisis-list.component.ts
@@ -0,0 +1,56 @@
+// #docregion
+import 'rxjs/add/operator/switchMap';
+import { Component, OnInit } from '@angular/core';
+import { ActivatedRoute, Router, Params } from '@angular/router';
+
+import { Observable } from 'rxjs/Observable';
+
+import { Crisis, CrisisService } from './crisis.service';
+
+@Component({
+ template: `
+
+
+ {{ crisis.id }}
+ {{ crisis.name }}
+
+
+
+
+ `
+})
+export class CrisisListComponent implements OnInit {
+ crises: Observable;
+ selectedId: number;
+
+ // #docregion ctor
+ constructor(
+ private service: CrisisService,
+ private route: ActivatedRoute,
+ private router: Router
+ ) {}
+ // #enddocregion ctor
+
+ isSelected(crisis: Crisis) {
+ return crisis.id === this.selectedId;
+ }
+
+ ngOnInit() {
+ this.crises = this.route.params
+ .switchMap((params: Params) => {
+ this.selectedId = +params['id'];
+ return this.service.getCrises();
+ });
+ }
+
+ // #docregion onSelect
+ onSelect(crisis: Crisis) {
+ this.selectedId = crisis.id;
+
+ // Navigate with relative link
+ this.router.navigate([crisis.id], { relativeTo: this.route });
+ }
+ // #enddocregion onSelect
+}
diff --git a/public/docs/_examples/router/ts/src/app/crisis-center/crisis.service.ts b/public/docs/_examples/router/ts/src/app/crisis-center/crisis.service.ts
new file mode 100644
index 0000000000..e7fd34d387
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/crisis-center/crisis.service.ts
@@ -0,0 +1,40 @@
+// #docplaster
+// #docregion , mock-crises
+export class Crisis {
+ constructor(public id: number, public name: string) { }
+}
+
+const CRISES = [
+ new Crisis(1, 'Dragon Burning Cities'),
+ new Crisis(2, 'Sky Rains Great White Sharks'),
+ new Crisis(3, 'Giant Asteroid Heading For Earth'),
+ new Crisis(4, 'Procrastinators Meeting Delayed Again'),
+];
+// #enddocregion mock-crises
+
+let crisesPromise = Promise.resolve(CRISES);
+
+import { Injectable } from '@angular/core';
+
+@Injectable()
+export class CrisisService {
+
+ static nextCrisisId = 100;
+
+ getCrises() { return crisesPromise; }
+
+ getCrisis(id: number | string) {
+ return crisesPromise
+ .then(crises => crises.find(crisis => crisis.id === +id));
+ }
+
+ // #enddocregion
+ addCrisis(name: string) {
+ name = name.trim();
+ if (name) {
+ let crisis = new Crisis(CrisisService.nextCrisisId++, name);
+ crisesPromise.then(crises => crises.push(crisis));
+ }
+ }
+ // #docregion
+}
diff --git a/public/docs/_examples/router/ts/src/app/crisis-list.component.ts b/public/docs/_examples/router/ts/src/app/crisis-list.component.ts
new file mode 100644
index 0000000000..6caa3653b5
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/crisis-list.component.ts
@@ -0,0 +1,10 @@
+// Initial empty version
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ template: `
+ CRISIS CENTER
+ Get your crisis here
`
+})
+export class CrisisListComponent { }
diff --git a/public/docs/_examples/router/ts/src/app/dialog.service.ts b/public/docs/_examples/router/ts/src/app/dialog.service.ts
new file mode 100644
index 0000000000..0f09e4936d
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/dialog.service.ts
@@ -0,0 +1,19 @@
+// #docregion
+import { Injectable } from '@angular/core';
+/**
+ * Async modal dialog service
+ * DialogService makes this app easier to test by faking this service.
+ * TODO: better modal implementation that doesn't use window.confirm
+ */
+@Injectable()
+export class DialogService {
+ /**
+ * Ask user to confirm an action. `message` explains the action and choices.
+ * Returns promise resolving to `true`=confirm or `false`=cancel
+ */
+ confirm(message?: string) {
+ return new Promise(resolve => {
+ return resolve(window.confirm(message || 'Is it OK?'));
+ });
+ };
+}
diff --git a/public/docs/_examples/router/ts/src/app/hero-list.component.ts b/public/docs/_examples/router/ts/src/app/hero-list.component.ts
new file mode 100644
index 0000000000..7a8f97ca1e
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/hero-list.component.ts
@@ -0,0 +1,13 @@
+/// Initial empty version
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ template: `
+ HEROES
+ Get your heroes here
+
+ Go to sidekicks
+ `
+})
+export class HeroListComponent { }
diff --git a/public/docs/_examples/router/ts/src/app/heroes/hero-detail.component.1.ts b/public/docs/_examples/router/ts/src/app/heroes/hero-detail.component.1.ts
new file mode 100644
index 0000000000..93f0efaf0b
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/heroes/hero-detail.component.1.ts
@@ -0,0 +1,55 @@
+// #docplaster
+// #docregion
+// #docregion rxjs-operator-import
+import 'rxjs/add/operator/switchMap';
+// #enddocregion rxjs-operator-import
+import { Component, OnInit } from '@angular/core';
+// #docregion imports
+import { Router, ActivatedRoute, Params } from '@angular/router';
+// #enddocregion imports
+
+import { Hero, HeroService } from './hero.service';
+
+@Component({
+ template: `
+ HEROES
+
+
"{{ hero.name }}"
+
+ Id: {{ hero.id }}
+
+ Name:
+
+
+
+ Back
+
+
+ `
+})
+export class HeroDetailComponent implements OnInit {
+ hero: Hero;
+
+ // #docregion ctor
+ constructor(
+ private route: ActivatedRoute,
+ private router: Router,
+ private service: HeroService
+ ) {}
+ // #enddocregion ctor
+
+ // #docregion ngOnInit
+ ngOnInit() {
+ this.route.params
+ // (+) converts string 'id' to a number
+ .switchMap((params: Params) => this.service.getHero(+params['id']))
+ .subscribe((hero: Hero) => this.hero = hero);
+ }
+ // #enddocregion ngOnInit
+
+ // #docregion gotoHeroes
+ gotoHeroes() {
+ this.router.navigate(['/heroes']);
+ }
+ // #enddocregion gotoHeroes
+}
diff --git a/public/docs/_examples/router/ts/src/app/heroes/hero-detail.component.2.ts b/public/docs/_examples/router/ts/src/app/heroes/hero-detail.component.2.ts
new file mode 100644
index 0000000000..c3b69be965
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/heroes/hero-detail.component.2.ts
@@ -0,0 +1,47 @@
+// Snapshot version
+// #docregion
+import { Component, OnInit } from '@angular/core';
+import { ActivatedRoute, Router } from '@angular/router';
+
+import { Hero, HeroService } from './hero.service';
+
+@Component({
+ template: `
+ HEROES
+
+
"{{ hero.name }}"
+
+ Id: {{ hero.id }}
+
+ Name:
+
+
+
+ Back
+
+
+ `
+})
+export class HeroDetailComponent implements OnInit {
+ hero: Hero;
+
+ constructor(
+ private route: ActivatedRoute,
+ private router: Router,
+ private service: HeroService
+ ) {}
+
+ // #docregion snapshot
+ ngOnInit() {
+ // (+) converts string 'id' to a number
+ let id = +this.route.snapshot.params['id'];
+
+ this.service.getHero(id)
+ .then((hero: Hero) => this.hero = hero);
+ }
+ // #enddocregion snapshot
+
+ gotoHeroes() {
+ this.router.navigate(['/heroes']);
+ }
+}
diff --git a/public/docs/_examples/router/ts/src/app/heroes/hero-detail.component.ts b/public/docs/_examples/router/ts/src/app/heroes/hero-detail.component.ts
new file mode 100644
index 0000000000..8135d37d32
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/heroes/hero-detail.component.ts
@@ -0,0 +1,66 @@
+// #docplaster
+// #docregion
+// #docregion rxjs-operator-import
+import 'rxjs/add/operator/switchMap';
+// #enddocregion rxjs-operator-import
+import { Component, OnInit, HostBinding } from '@angular/core';
+import { Router, ActivatedRoute, Params } from '@angular/router';
+
+import { slideInDownAnimation } from '../animations';
+
+import { Hero, HeroService } from './hero.service';
+
+@Component({
+ template: `
+ HEROES
+
+
"{{ hero.name }}"
+
+ Id: {{ hero.id }}
+
+ Name:
+
+
+
+ Back
+
+
+ `,
+ animations: [ slideInDownAnimation ]
+})
+export class HeroDetailComponent implements OnInit {
+// #docregion host-bindings
+ @HostBinding('@routeAnimation') routeAnimation = true;
+ @HostBinding('style.display') display = 'block';
+ @HostBinding('style.position') position = 'absolute';
+// #enddocregion host-bindings
+
+ hero: Hero;
+
+ // #docregion ctor
+ constructor(
+ private route: ActivatedRoute,
+ private router: Router,
+ private service: HeroService
+ ) {}
+ // #enddocregion ctor
+
+ // #docregion ngOnInit
+ ngOnInit() {
+ this.route.params
+ // (+) converts string 'id' to a number
+ .switchMap((params: Params) => this.service.getHero(+params['id']))
+ .subscribe((hero: Hero) => this.hero = hero);
+ }
+ // #enddocregion ngOnInit
+
+ // #docregion gotoHeroes
+ gotoHeroes() {
+ let heroId = this.hero ? this.hero.id : null;
+ // Pass along the hero id if available
+ // so that the HeroList component can select that hero.
+ // Include a junk 'foo' property for fun.
+ this.router.navigate(['/heroes', { id: heroId, foo: 'foo' }]);
+ }
+ // #enddocregion gotoHeroes
+}
diff --git a/public/docs/_examples/router/ts/src/app/heroes/hero-list.component.1.ts b/public/docs/_examples/router/ts/src/app/heroes/hero-list.component.1.ts
new file mode 100644
index 0000000000..59552830a4
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/heroes/hero-list.component.1.ts
@@ -0,0 +1,52 @@
+// #docplaster
+// #docregion
+// TODO SOMEDAY: Feature Componetized like HeroCenter
+import { Component, OnInit } from '@angular/core';
+import { Router } from '@angular/router';
+
+import { Hero, HeroService } from './hero.service';
+
+@Component({
+ // #docregion template
+ template: `
+ HEROES
+
+
+ {{ hero.id }} {{ hero.name }}
+
+
+
+ Go to sidekicks
+ `
+ // #enddocregion template
+})
+export class HeroListComponent implements OnInit {
+ heroes: Promise;
+
+ // #docregion ctor
+ constructor(
+ private router: Router,
+ private service: HeroService
+ ) {}
+ // #enddocregion ctor
+
+ ngOnInit() {
+ this.heroes = this.service.getHeroes();
+ }
+
+ // #docregion select
+ onSelect(hero: Hero) {
+ // #docregion nav-to-detail
+ this.router.navigate(['/hero', hero.id]);
+ // #enddocregion nav-to-detail
+ }
+ // #enddocregion select
+}
+// #enddocregion
+
+/* A link parameters array
+// #docregion link-parameters-array
+['/hero', hero.id] // { 15 }
+// #enddocregion link-parameters-array
+*/
diff --git a/public/docs/_examples/router/ts/src/app/heroes/hero-list.component.ts b/public/docs/_examples/router/ts/src/app/heroes/hero-list.component.ts
new file mode 100644
index 0000000000..c7dcc3877e
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/heroes/hero-list.component.ts
@@ -0,0 +1,63 @@
+// #docplaster
+// #docregion
+// TODO SOMEDAY: Feature Componetized like CrisisCenter
+// #docregion rxjs-imports
+import 'rxjs/add/operator/switchMap';
+import { Observable } from 'rxjs/Observable';
+// #enddocregion rxjs-imports
+import { Component, OnInit } from '@angular/core';
+// #docregion import-router
+import { Router, ActivatedRoute, Params } from '@angular/router';
+// #enddocregion import-router
+
+import { Hero, HeroService } from './hero.service';
+
+@Component({
+ // #docregion template
+ template: `
+ HEROES
+
+
+ {{ hero.id }} {{ hero.name }}
+
+
+
+ Go to sidekicks
+ `
+ // #enddocregion template
+})
+// #docregion ctor
+export class HeroListComponent implements OnInit {
+ heroes: Observable;
+
+ private selectedId: number;
+
+ constructor(
+ private service: HeroService,
+ private route: ActivatedRoute,
+ private router: Router
+ ) {}
+
+ ngOnInit() {
+ this.heroes = this.route.params
+ .switchMap((params: Params) => {
+ this.selectedId = +params['id'];
+ return this.service.getHeroes();
+ });
+ }
+ // #enddocregion ctor
+
+ // #docregion isSelected
+ isSelected(hero: Hero) { return hero.id === this.selectedId; }
+ // #enddocregion isSelected
+
+ // #docregion select
+ onSelect(hero: Hero) {
+ this.router.navigate(['/hero', hero.id]);
+ }
+ // #enddocregion select
+// #docregion ctor
+}
+// #enddocregion
diff --git a/public/docs/_examples/router/ts/src/app/heroes/hero.service.ts b/public/docs/_examples/router/ts/src/app/heroes/hero.service.ts
new file mode 100644
index 0000000000..6e4e7bee60
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/heroes/hero.service.ts
@@ -0,0 +1,27 @@
+// #docregion
+import { Injectable } from '@angular/core';
+
+export class Hero {
+ constructor(public id: number, public name: string) { }
+}
+
+let HEROES = [
+ new Hero(11, 'Mr. Nice'),
+ new Hero(12, 'Narco'),
+ new Hero(13, 'Bombasto'),
+ new Hero(14, 'Celeritas'),
+ new Hero(15, 'Magneta'),
+ new Hero(16, 'RubberMan')
+];
+
+let heroesPromise = Promise.resolve(HEROES);
+
+@Injectable()
+export class HeroService {
+ getHeroes() { return heroesPromise; }
+
+ getHero(id: number | string) {
+ return heroesPromise
+ .then(heroes => heroes.find(hero => hero.id === +id));
+ }
+}
diff --git a/public/docs/_examples/router/ts/src/app/heroes/heroes-routing.module.ts b/public/docs/_examples/router/ts/src/app/heroes/heroes-routing.module.ts
new file mode 100644
index 0000000000..dbee521793
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/heroes/heroes-routing.module.ts
@@ -0,0 +1,24 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+import { HeroListComponent } from './hero-list.component';
+import { HeroDetailComponent } from './hero-detail.component';
+
+const heroesRoutes: Routes = [
+ { path: 'heroes', component: HeroListComponent },
+// #docregion hero-detail-route
+ { path: 'hero/:id', component: HeroDetailComponent }
+// #enddocregion hero-detail-route
+];
+
+@NgModule({
+ imports: [
+ RouterModule.forChild(heroesRoutes)
+ ],
+ exports: [
+ RouterModule
+ ]
+})
+export class HeroRoutingModule { }
+// #enddocregion
diff --git a/public/docs/_examples/router/ts/src/app/heroes/heroes.module.ts b/public/docs/_examples/router/ts/src/app/heroes/heroes.module.ts
new file mode 100644
index 0000000000..95ee64a182
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/heroes/heroes.module.ts
@@ -0,0 +1,33 @@
+// #docplaster
+// #docregion
+// #docregion v1
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+
+import { HeroListComponent } from './hero-list.component';
+import { HeroDetailComponent } from './hero-detail.component';
+
+import { HeroService } from './hero.service';
+
+// #enddocregion v1
+import { HeroRoutingModule } from './heroes-routing.module';
+
+// #docregion v1
+@NgModule({
+ imports: [
+ CommonModule,
+ FormsModule,
+// #enddocregion v1
+ HeroRoutingModule
+// #docregion v1
+ ],
+ declarations: [
+ HeroListComponent,
+ HeroDetailComponent
+ ],
+ providers: [ HeroService ]
+})
+export class HeroesModule {}
+// #enddocregion v1
+// #enddocregion
diff --git a/public/docs/_examples/router/ts/src/app/login-routing.module.ts b/public/docs/_examples/router/ts/src/app/login-routing.module.ts
new file mode 100644
index 0000000000..96d05e7972
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/login-routing.module.ts
@@ -0,0 +1,24 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+import { AuthGuard } from './auth-guard.service';
+import { AuthService } from './auth.service';
+import { LoginComponent } from './login.component';
+
+const loginRoutes: Routes = [
+ { path: 'login', component: LoginComponent }
+];
+
+@NgModule({
+ imports: [
+ RouterModule.forChild(loginRoutes)
+ ],
+ exports: [
+ RouterModule
+ ],
+ providers: [
+ AuthGuard,
+ AuthService
+ ]
+})
+export class LoginRoutingModule {}
diff --git a/public/docs/_examples/router/ts/src/app/login.component.1.ts b/public/docs/_examples/router/ts/src/app/login.component.1.ts
new file mode 100644
index 0000000000..ddee339011
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/login.component.1.ts
@@ -0,0 +1,46 @@
+// #docregion
+import { Component } from '@angular/core';
+import { Router } from '@angular/router';
+import { AuthService } from './auth.service';
+
+@Component({
+ template: `
+ LOGIN
+ {{message}}
+
+ Login
+ Logout
+
`
+})
+export class LoginComponent {
+ message: string;
+
+ constructor(public authService: AuthService, public router: Router) {
+ this.setMessage();
+ }
+
+ setMessage() {
+ this.message = 'Logged ' + (this.authService.isLoggedIn ? 'in' : 'out');
+ }
+
+ login() {
+ this.message = 'Trying to log in ...';
+
+ this.authService.login().subscribe(() => {
+ this.setMessage();
+ if (this.authService.isLoggedIn) {
+ // Get the redirect URL from our auth service
+ // If no redirect has been set, use the default
+ let redirect = this.authService.redirectUrl ? this.authService.redirectUrl : '/crisis-center/admin';
+
+ // Redirect the user
+ this.router.navigate([redirect]);
+ }
+ });
+ }
+
+ logout() {
+ this.authService.logout();
+ this.setMessage();
+ }
+}
diff --git a/public/docs/_examples/router/ts/src/app/login.component.ts b/public/docs/_examples/router/ts/src/app/login.component.ts
new file mode 100644
index 0000000000..41c88f4068
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/login.component.ts
@@ -0,0 +1,56 @@
+// #docregion
+import { Component } from '@angular/core';
+import { Router,
+ NavigationExtras } from '@angular/router';
+import { AuthService } from './auth.service';
+
+@Component({
+ template: `
+ LOGIN
+ {{message}}
+
+ Login
+ Logout
+
`
+})
+export class LoginComponent {
+ message: string;
+
+ constructor(public authService: AuthService, public router: Router) {
+ this.setMessage();
+ }
+
+ setMessage() {
+ this.message = 'Logged ' + (this.authService.isLoggedIn ? 'in' : 'out');
+ }
+
+ login() {
+ this.message = 'Trying to log in ...';
+
+ this.authService.login().subscribe(() => {
+ this.setMessage();
+ if (this.authService.isLoggedIn) {
+ // Get the redirect URL from our auth service
+ // If no redirect has been set, use the default
+ let redirect = this.authService.redirectUrl ? this.authService.redirectUrl : '/admin';
+
+ // #docregion preserve
+ // Set our navigation extras object
+ // that passes on our global query params and fragment
+ let navigationExtras: NavigationExtras = {
+ preserveQueryParams: true,
+ preserveFragment: true
+ };
+
+ // Redirect the user
+ this.router.navigate([redirect], navigationExtras);
+ // #enddocregion preserve
+ }
+ });
+ }
+
+ logout() {
+ this.authService.logout();
+ this.setMessage();
+ }
+}
diff --git a/public/docs/_examples/router/ts/src/app/not-found.component.ts b/public/docs/_examples/router/ts/src/app/not-found.component.ts
new file mode 100644
index 0000000000..2e74544e17
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/not-found.component.ts
@@ -0,0 +1,7 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ template: 'Page not found '
+})
+export class PageNotFoundComponent {}
diff --git a/public/docs/_examples/router/ts/src/app/selective-preloading-strategy.ts b/public/docs/_examples/router/ts/src/app/selective-preloading-strategy.ts
new file mode 100644
index 0000000000..395f1056ef
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/app/selective-preloading-strategy.ts
@@ -0,0 +1,24 @@
+// #docregion
+import 'rxjs/add/observable/of';
+import { Injectable } from '@angular/core';
+import { PreloadingStrategy, Route } from '@angular/router';
+import { Observable } from 'rxjs/Observable';
+
+@Injectable()
+export class SelectivePreloadingStrategy implements PreloadingStrategy {
+ preloadedModules: string[] = [];
+
+ preload(route: Route, load: () => Observable): Observable {
+ if (route.data && route.data['preload']) {
+ // add the route path to the preloaded module array
+ this.preloadedModules.push(route.path);
+
+ // log the route path to the console
+ console.log('Preloaded: ' + route.path);
+
+ return load();
+ } else {
+ return Observable.of(null);
+ }
+ }
+}
diff --git a/public/docs/_examples/router/ts/src/index.html b/public/docs/_examples/router/ts/src/index.html
new file mode 100644
index 0000000000..0fa6453c36
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/index.html
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+ Angular Router
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ loading...
+
+
+
+
diff --git a/public/docs/_examples/router/ts/src/main.ts b/public/docs/_examples/router/ts/src/main.ts
new file mode 100644
index 0000000000..f332d1d245
--- /dev/null
+++ b/public/docs/_examples/router/ts/src/main.ts
@@ -0,0 +1,6 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/security/e2e-spec.ts b/public/docs/_examples/security/e2e-spec.ts
new file mode 100644
index 0000000000..23d11cd12b
--- /dev/null
+++ b/public/docs/_examples/security/e2e-spec.ts
@@ -0,0 +1,37 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, By } from 'protractor';
+
+describe('Security E2E Tests', () => {
+ beforeAll(() => browser.get(''));
+
+ it('sanitizes innerHTML', () => {
+ let interpolated = element(By.className('e2e-inner-html-interpolated'));
+ expect(interpolated.getText())
+ .toContain('Template Syntax ');
+ let bound = element(By.className('e2e-inner-html-bound'));
+ expect(bound.getText()).toContain('Template alert("0wned") Syntax');
+ let bold = element(By.css('.e2e-inner-html-bound b'));
+ expect(bold.getText()).toContain('Syntax');
+ });
+
+ it('escapes untrusted URLs', () => {
+ let untrustedUrl = element(By.className('e2e-dangerous-url'));
+ expect(untrustedUrl.getAttribute('href')).toMatch(/^unsafe:javascript/);
+ });
+
+ it('binds trusted URLs', () => {
+ let trustedUrl = element(By.className('e2e-trusted-url'));
+ expect(trustedUrl.getAttribute('href')).toMatch(/^javascript:alert/);
+ });
+
+ it('escapes untrusted resource URLs', () => {
+ let iframe = element(By.className('e2e-iframe-untrusted-src'));
+ expect(iframe.getAttribute('src')).toBe('');
+ });
+
+ it('binds trusted resource URLs', () => {
+ let iframe = element(By.className('e2e-iframe-trusted-src'));
+ expect(iframe.getAttribute('src')).toMatch(/^https:\/\/fanyv88.com:443\/https\/www.youtube.com\//);
+ });
+});
diff --git a/public/docs/_examples/security/ts/example-config.json b/public/docs/_examples/security/ts/example-config.json
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/public/docs/_examples/security/ts/plnkr.json b/public/docs/_examples/security/ts/plnkr.json
new file mode 100644
index 0000000000..4c9e85ce1e
--- /dev/null
+++ b/public/docs/_examples/security/ts/plnkr.json
@@ -0,0 +1,9 @@
+{
+ "description": "Content Security",
+ "basePath": "src/",
+ "files": [
+ "!**/*.d.ts",
+ "!**/*.js"
+ ],
+ "tags": ["security"]
+}
diff --git a/public/docs/_examples/security/ts/src/app/app.component.ts b/public/docs/_examples/security/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..c30235e8e7
--- /dev/null
+++ b/public/docs/_examples/security/ts/src/app/app.component.ts
@@ -0,0 +1,13 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ template: `
+ Security
+
+
+ `
+})
+export class AppComponent {
+}
diff --git a/public/docs/_examples/security/ts/src/app/app.module.ts b/public/docs/_examples/security/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..21d880be3b
--- /dev/null
+++ b/public/docs/_examples/security/ts/src/app/app.module.ts
@@ -0,0 +1,18 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+import { AppComponent } from './app.component';
+import { BypassSecurityComponent } from './bypass-security.component';
+import { InnerHtmlBindingComponent } from './inner-html-binding.component';
+
+@NgModule({
+ imports: [ BrowserModule ],
+ declarations: [
+ AppComponent,
+ BypassSecurityComponent,
+ InnerHtmlBindingComponent
+ ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/security/ts/src/app/bypass-security.component.html b/public/docs/_examples/security/ts/src/app/bypass-security.component.html
new file mode 100644
index 0000000000..96adf058e2
--- /dev/null
+++ b/public/docs/_examples/security/ts/src/app/bypass-security.component.html
@@ -0,0 +1,17 @@
+
+Bypass Security Component
+
+
+An untrusted URL:
+Click me
+A trusted URL:
+Click me
+
+
+
+Resource URL:
+Showing: {{dangerousVideoUrl}}
+Trusted:
+
+Untrusted:
+
diff --git a/public/docs/_examples/security/ts/src/app/bypass-security.component.ts b/public/docs/_examples/security/ts/src/app/bypass-security.component.ts
new file mode 100644
index 0000000000..ff41e287ba
--- /dev/null
+++ b/public/docs/_examples/security/ts/src/app/bypass-security.component.ts
@@ -0,0 +1,38 @@
+// #docplaster
+// #docregion
+import { Component } from '@angular/core';
+import { DomSanitizer, SafeResourceUrl, SafeUrl } from '@angular/platform-browser';
+
+@Component({
+ selector: 'bypass-security',
+ templateUrl: './bypass-security.component.html',
+})
+export class BypassSecurityComponent {
+ dangerousUrl: string;
+ trustedUrl: SafeUrl;
+ dangerousVideoUrl: string;
+ videoUrl: SafeResourceUrl;
+
+ // #docregion trust-url
+ constructor(private sanitizer: DomSanitizer) {
+ // javascript: URLs are dangerous if attacker controlled.
+ // Angular sanitizes them in data binding, but you can
+ // explicitly tell Angular to trust this value:
+ this.dangerousUrl = 'javascript:alert("Hi there")';
+ this.trustedUrl = sanitizer.bypassSecurityTrustUrl(this.dangerousUrl);
+ // #enddocregion trust-url
+ this.updateVideoUrl('PUBnlbjZFAI');
+ }
+
+ // #docregion trust-video-url
+ updateVideoUrl(id: string) {
+ // Appending an ID to a YouTube URL is safe.
+ // Always make sure to construct SafeValue objects as
+ // close as possible to the input data so
+ // that it's easier to check if the value is safe.
+ this.dangerousVideoUrl = 'https://www.youtube.com/embed/' + id;
+ this.videoUrl =
+ this.sanitizer.bypassSecurityTrustResourceUrl(this.dangerousVideoUrl);
+ }
+ // #enddocregion trust-video-url
+}
diff --git a/public/docs/_examples/security/ts/src/app/inner-html-binding.component.html b/public/docs/_examples/security/ts/src/app/inner-html-binding.component.html
new file mode 100644
index 0000000000..fe540d25fe
--- /dev/null
+++ b/public/docs/_examples/security/ts/src/app/inner-html-binding.component.html
@@ -0,0 +1,6 @@
+
+Binding innerHTML
+Bound value:
+{{htmlSnippet}}
+Result of binding to innerHTML:
+
diff --git a/public/docs/_examples/security/ts/src/app/inner-html-binding.component.ts b/public/docs/_examples/security/ts/src/app/inner-html-binding.component.ts
new file mode 100644
index 0000000000..8319503686
--- /dev/null
+++ b/public/docs/_examples/security/ts/src/app/inner-html-binding.component.ts
@@ -0,0 +1,12 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'inner-html-binding',
+ templateUrl: './inner-html-binding.component.html',
+})
+// #docregion class
+export class InnerHtmlBindingComponent {
+ // For example, a user/attacker-controlled value from a URL.
+ htmlSnippet = 'Template Syntax ';
+}
diff --git a/public/docs/_examples/security/ts/src/index.html b/public/docs/_examples/security/ts/src/index.html
new file mode 100644
index 0000000000..d5dd11c038
--- /dev/null
+++ b/public/docs/_examples/security/ts/src/index.html
@@ -0,0 +1,26 @@
+
+
+
+
+ Angular Content Security
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
diff --git a/public/docs/_examples/security/ts/src/main.ts b/public/docs/_examples/security/ts/src/main.ts
new file mode 100644
index 0000000000..105b06712d
--- /dev/null
+++ b/public/docs/_examples/security/ts/src/main.ts
@@ -0,0 +1,6 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
+
diff --git a/public/docs/_examples/server-communication/dart/lib/hero_data.dart b/public/docs/_examples/server-communication/dart/lib/hero_data.dart
deleted file mode 100644
index 4220e6cd9d..0000000000
--- a/public/docs/_examples/server-communication/dart/lib/hero_data.dart
+++ /dev/null
@@ -1,10 +0,0 @@
-import 'package:http_in_memory_web_api/http_in_memory_web_api.dart';
-
-CreateDb heroData = () => {
- 'heroes': [
- {"id": "1", "name": "Windstorm"},
- {"id": "2", "name": "Bombasto"},
- {"id": "3", "name": "Magneta"},
- {"id": "4", "name": "Tornado"}
- ]
- };
diff --git a/public/docs/_examples/server-communication/dart/lib/toh/hero.dart b/public/docs/_examples/server-communication/dart/lib/toh/hero.dart
deleted file mode 100644
index b7dd9f00ae..0000000000
--- a/public/docs/_examples/server-communication/dart/lib/toh/hero.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// #docregion
-class Hero {
- final int id;
- final String name;
-
- Hero(this.id, this.name);
-
- factory Hero.fromJson(Map hero) {
- final _id = hero['id'];
- final id = _id is int ? _id : int.parse(_id);
- return new Hero(id,hero['name']);
- }
-
- Map toJson() => {'id': id, 'name': name};
-}
diff --git a/public/docs/_examples/server-communication/dart/lib/toh/hero_list_component.dart b/public/docs/_examples/server-communication/dart/lib/toh/hero_list_component.dart
deleted file mode 100644
index f51a98d35b..0000000000
--- a/public/docs/_examples/server-communication/dart/lib/toh/hero_list_component.dart
+++ /dev/null
@@ -1,58 +0,0 @@
-// #docregion
-import 'dart:async';
-import 'package:angular2/angular2.dart';
-import 'hero.dart';
-import 'hero_service.dart';
-
-@Component(
- selector: 'hero-list',
-// #docregion template
- template: '''
- Heroes:
-
- New Hero:
-
-
- Add Hero
-
- {{errorMessage}}
- ''',
-// #enddocregion template
- styles: const ['.error {color:red;}'])
-// #docregion component
-class HeroListComponent implements OnInit {
- final HeroService _heroService;
- String errorMessage;
- List heroes = [];
-
- HeroListComponent(this._heroService);
-
- bool get hasErrorMessage => errorMessage != null;
-
- Future ngOnInit() => getHeroes();
-
- // #docregion methods
- Future getHeroes() async {
- try {
- heroes = await _heroService.getHeroes();
- } catch (e) {
- errorMessage = e.toString();
- }
- }
-
- Future addHero(String name) async {
- name = name.trim();
- if (name.isEmpty) return;
- try {
- heroes.add(await _heroService.addHero(name));
- } catch (e) {
- errorMessage = e.toString();
- }
- }
- // #enddocregion methods
-}
-// #enddocregion component
diff --git a/public/docs/_examples/server-communication/dart/lib/toh/hero_service.dart b/public/docs/_examples/server-communication/dart/lib/toh/hero_service.dart
deleted file mode 100644
index f81d45be38..0000000000
--- a/public/docs/_examples/server-communication/dart/lib/toh/hero_service.dart
+++ /dev/null
@@ -1,41 +0,0 @@
-// #docplaster
-
-// #docregion
-import 'dart:async';
-import 'dart:convert';
-
-import 'package:angular2/angular2.dart';
-// #enddocregion v1
-// #docregion import-request-options
-import 'package:http/browser_client.dart';
-// #enddocregion import-request-options
-// #docregion v1
-import 'hero.dart';
-
-@Injectable()
-class HeroService {
- final String _heroesUrl = 'app/heroes';
- BrowserClient _http;
-
- HeroService(this._http);
-
-// #docregion methods
- Future> getHeroes() async {
- final response = await _http.get(_heroesUrl);
- final heroes = JSON
- .decode(response.body)['data']
- .map((value) => new Hero.fromJson(value))
- .toList();
- print(JSON.encode(heroes)); // eyeball results in the console
- return heroes;
- }
-
- Future addHero(String name) async {
- final headers = {'content-type': 'application/json'};
- final body = JSON.encode({'name': name});
- final response = await _http.post(_heroesUrl, headers: headers, body: body);
- return new Hero.fromJson(JSON.decode(response.body));
- }
-// #enddocregion methods
-}
-// #enddocregion
diff --git a/public/docs/_examples/server-communication/dart/lib/toh/toh_component.dart b/public/docs/_examples/server-communication/dart/lib/toh/toh_component.dart
deleted file mode 100644
index 3b2a6b27b4..0000000000
--- a/public/docs/_examples/server-communication/dart/lib/toh/toh_component.dart
+++ /dev/null
@@ -1,35 +0,0 @@
-import 'package:angular2/angular2.dart';
-import 'package:http_in_memory_web_api/http_in_memory_web_api.dart';
-import 'package:http/browser_client.dart';
-import 'package:server_communication/hero_data.dart';
-
-import 'hero_list_component.dart';
-import 'hero_service.dart';
-
-@Injectable()
-HttpClientInMemoryBackendService HttpClientInMemoryBackendServiceFactory() =>
- new HttpClientInMemoryBackendService(heroData); // in-mem server
-
-@Component(
- selector: 'my-toh',
-// #docregion template
- template: '''
- Tour of Heroes
-
- ''',
-// #enddocregion template
- providers: const [
- HeroService,
-//#enddocregion
-//#docregion in-mem-web-api-providers
-// in-memory web api providers
- const Provider(BrowserClient,
- useFactory: HttpClientInMemoryBackendServiceFactory)
-//#enddocregion in-mem-web-api-providers
-//#docregion
- ],
- directives: const [
- HeroListComponent
- ])
-class TohComponent {}
-// #enddocregion
diff --git a/public/docs/_examples/server-communication/dart/lib/wiki/wiki_component.dart b/public/docs/_examples/server-communication/dart/lib/wiki/wiki_component.dart
deleted file mode 100644
index 78d44f93bc..0000000000
--- a/public/docs/_examples/server-communication/dart/lib/wiki/wiki_component.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-// #docregion
-import 'dart:async';
-import 'package:angular2/angular2.dart';
-import 'wikipedia_service.dart';
-
-@Component(
- selector: 'my-wiki',
- template: '''
- Wikipedia Demo
- Fetches after each keystroke
-
-
- ''',
- providers: const [WikipediaService])
-class WikiComponent {
- final WikipediaService _wikipediaService;
- List items = [];
-
- WikiComponent(this._wikipediaService);
-
- Future search(String term) async {
- items = await this._wikipediaService.search(term);
- }
-}
diff --git a/public/docs/_examples/server-communication/dart/lib/wiki/wiki_smart_component.dart b/public/docs/_examples/server-communication/dart/lib/wiki/wiki_smart_component.dart
deleted file mode 100644
index 3be519471b..0000000000
--- a/public/docs/_examples/server-communication/dart/lib/wiki/wiki_smart_component.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-// #docregion
-import 'package:angular2/angular2.dart';
-import 'package:stream_transformers/stream_transformers.dart';
-
-import 'wikipedia_service.dart';
-
-@Component(
- selector: 'my-wiki-smart',
- template: '''
- Smarter Wikipedia Demo
- Fetches when typing stops
-
-
-
- ''',
- providers: const [WikipediaService])
-class WikiSmartComponent {
- final WikipediaService _wikipediaService;
- List items = [];
-
- WikiSmartComponent(this._wikipediaService) {
- _searchTermStream
- .transform(new Debounce(new Duration(milliseconds: 300)))
- .distinct()
- .transform(new FlatMapLatest(
- (term) => _wikipediaService.search(term).asStream()))
- .forEach((data) {
- items = data;
- });
- }
-
- final EventEmitter _searchTermStream = new EventEmitter();
-
- void search(String term) => _searchTermStream.add(term);
-}
diff --git a/public/docs/_examples/server-communication/dart/lib/wiki/wikipedia_service.dart b/public/docs/_examples/server-communication/dart/lib/wiki/wikipedia_service.dart
deleted file mode 100644
index d4314c3f08..0000000000
--- a/public/docs/_examples/server-communication/dart/lib/wiki/wikipedia_service.dart
+++ /dev/null
@@ -1,24 +0,0 @@
-// #docregion
-import 'dart:async';
-import 'package:angular2/angular2.dart';
-import 'package:jsonpadding/jsonpadding.dart';
-
-@Injectable()
-class WikipediaService {
- Future> search(String term) async {
- // #docregion call-jsonp
- Uri uri = new Uri(
- scheme: 'http',
- host: 'en.wikipedia.org',
- path: 'w/api.php',
- queryParameters: {
- 'search': term,
- 'action': 'opensearch',
- 'format': 'json'
- });
- // TODO: Error handling
- List result = await jsonp(uri);
- return result[1];
- // #enddocregion call-jsonp
- }
-}
diff --git a/public/docs/_examples/server-communication/dart/pubspec.yaml b/public/docs/_examples/server-communication/dart/pubspec.yaml
deleted file mode 100644
index 85706833e3..0000000000
--- a/public/docs/_examples/server-communication/dart/pubspec.yaml
+++ /dev/null
@@ -1,20 +0,0 @@
-# #docregion
-name: server_communication
-description: Server Communication
-version: 0.0.1
-environment:
- sdk: '>=1.13.0 <2.0.0'
-dependencies:
- angular2: 2.0.0-beta.8
- browser: ^0.10.0
- dart_to_js_script_rewriter: ^0.1.0
- http: ^0.11.3+3
- jsonpadding: ^0.1.0
- stream_transformers: ^0.3.0+3
- http_in_memory_web_api: ^0.0.1
-transformers:
-- angular2:
- platform_directives: 'package:angular2/common.dart#CORE_DIRECTIVES'
- platform_pipes: 'package:angular2/common.dart#COMMON_PIPES'
- entry_points: 'web/main.dart'
-- dart_to_js_script_rewriter
diff --git a/public/docs/_examples/server-communication/dart/web/heroes.json b/public/docs/_examples/server-communication/dart/web/heroes.json
deleted file mode 100644
index c6b5cc91df..0000000000
--- a/public/docs/_examples/server-communication/dart/web/heroes.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "data": [
- { "id": "1", "name": "Windstorm" },
- { "id": "2", "name": "Bombasto" },
- { "id": "3", "name": "Magneta" },
- { "id": "4", "name": "Tornado" }
- ]
-}
diff --git a/public/docs/_examples/server-communication/dart/web/index.html b/public/docs/_examples/server-communication/dart/web/index.html
deleted file mode 100644
index b6b40d9193..0000000000
--- a/public/docs/_examples/server-communication/dart/web/index.html
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
- Angular 2 Http Demo
-
-
-
-
-
-
- ToH Loading...
- Wiki Loading...
- WikiSmart loading...
-
-
-
diff --git a/public/docs/_examples/server-communication/dart/web/main.dart b/public/docs/_examples/server-communication/dart/web/main.dart
deleted file mode 100644
index d0892cf49b..0000000000
--- a/public/docs/_examples/server-communication/dart/web/main.dart
+++ /dev/null
@@ -1,11 +0,0 @@
-// #docregion
-import 'package:angular2/bootstrap.dart';
-import 'package:server_communication/toh/toh_component.dart';
-import 'package:server_communication/wiki/wiki_component.dart';
-import 'package:server_communication/wiki/wiki_smart_component.dart';
-
-main() {
- bootstrap(TohComponent);
- bootstrap(WikiComponent);
- bootstrap(WikiSmartComponent);
-}
diff --git a/public/docs/_examples/server-communication/e2e-spec.js b/public/docs/_examples/server-communication/e2e-spec.js
deleted file mode 100644
index 4525c9514f..0000000000
--- a/public/docs/_examples/server-communication/e2e-spec.js
+++ /dev/null
@@ -1,141 +0,0 @@
-describe('Server Communication', function () {
-
- beforeAll(function () {
- browser.get('');
- });
-
- describe('Tour of Heroes e2e tests', function () {
-
- var _initialHeroCount = 4;
- var _newHeroName = 'Mr. IQ';
- var _heroCountAfterAdd = 5;
-
- it('should display ' + _initialHeroCount + ' heroes after init', function () {
- var myTohComp = element(by.tagName('my-toh'));
- expect(myTohComp).toBeDefined(' must exist');
- var heroListComp = myTohComp.element(by.tagName('hero-list'));
- expect(heroListComp).toBeDefined(' must exist');
- var heroTags = heroListComp.all(by.tagName('li'));
- expect(heroTags.count()).toBe(_initialHeroCount);
- });
-
- it('should not add hero with empty name', function () {
- var myTohComp = element(by.tagName('my-toh'));
- expect(myTohComp).toBeDefined(' must exist');
- var addButton = myTohComp.element(by.tagName('button'));
- expect(addButton).toBeDefined('"Add Hero" button must be defined');
- addButton.click().then(function() {
- var heroListComp = myTohComp.element(by.tagName('hero-list'));
- var heroTags = heroListComp.all(by.tagName('li'));
- expect(heroTags.count()).toBe(_initialHeroCount, 'No new hero should be added');
- });
- })
-
- it('should add a new hero to the list', function () {
- var myTohComp = element(by.tagName('my-toh'));
- expect(myTohComp).toBeDefined(' must exist');
- var heroNameInput = myTohComp.element(by.tagName('input'));
- expect(heroNameInput).toBeDefined(' for hero name must exist');
- var addButton = myTohComp.element(by.tagName('button'));
- expect(addButton).toBeDefined('"Add Hero" button must be defined');
- sendKeys(heroNameInput, _newHeroName);
- addButton.click().then(function() {
- var heroListComp = myTohComp.element(by.tagName('hero-list'));
- var heroTags = heroListComp.all(by.tagName('li'));
- expect(heroTags.count()).toBe(_heroCountAfterAdd, 'A new hero should be added');
- var newHeroInList = heroTags.get(_heroCountAfterAdd - 1).getText();
- expect(newHeroInList).toBe(_newHeroName, 'The hero should be added to the end of the list');
- });
- })
- });
-
- describe('Wikipedia Demo e2e tests', function () {
-
- it('should initialize the demo with empty result list', function () {
- var myWikiComp = element(by.tagName('my-wiki'));
- expect(myWikiComp).toBeDefined(' must exist');
- var resultList = myWikiComp.all(by.tagName('li'));
- expect(resultList.count()).toBe(0, 'result list must be empty');
- });
-
- describe('Fetches after each keystroke', function () {
- it('should fetch results after "B"', function(done) {
- testForRefreshedResult('B', done);
- });
-
- it('should fetch results after "Ba"', function(done) {
- testForRefreshedResult('a', done);
- });
-
- it('should fetch results after "Bas"', function(done) {
- testForRefreshedResult('s', done);
- });
-
- it('should fetch results after "Basic"', function(done) {
- testForRefreshedResult('ic', done);
- });
- });
-
- function testForRefreshedResult(keyPressed, done) {
- testForResult('my-wiki', keyPressed, false, done)
- }
- });
-
- describe('Smarter Wikipedia Demo e2e tests', function () {
-
- it('should initialize the demo with empty result list', function () {
- var myWikiSmartComp = element(by.tagName('my-wiki-smart'));
- expect(myWikiSmartComp).toBeDefined(' must exist');
- var resultList = myWikiSmartComp.all(by.tagName('li'));
- expect(resultList.count()).toBe(0, 'result list must be empty');
- });
-
- it('should fetch results after "Java"', function(done) {
- testForNewResult('Java', done);
- });
-
- it('should fetch results after "JavaS"', function(done) {
- testForStaleResult('S', done);
- });
-
- it('should fetch results after "JavaSc"', function(done) {
- testForStaleResult('c', done);
- });
-
- it('should fetch results after "JavaScript"', function(done) {
- testForStaleResult('ript', done);
- });
-
-
- function testForNewResult(keyPressed, done) {
- testForResult('my-wiki-smart', keyPressed, false, done)
- }
-
- function testForStaleResult(keyPressed, done) {
- testForResult('my-wiki-smart', keyPressed, true, done)
- }
-
- });
-
- function testForResult(componentTagName, keyPressed, hasListBeforeSearch, done) {
- var searchWait = 1000; // Wait for wikipedia but not so long that tests timeout
- var wikiComponent = element(by.tagName(componentTagName));
- expect(wikiComponent).toBeDefined('<' + componentTagName + '> must exist');
- var searchBox = wikiComponent.element(by.tagName('input'));
- expect(searchBox).toBeDefined(' for search must exist');
-
- searchBox.sendKeys(keyPressed).then(function () {
- var resultList = wikiComponent.all(by.tagName('li'));
-
- if (hasListBeforeSearch) {
- expect(resultList.count()).toBeGreaterThan(0, 'result list should not be empty before search');
- }
-
- setTimeout(function() {
- expect(resultList.count()).toBeGreaterThan(0, 'result list should not be empty after search');
- done();
- }, searchWait);
- });
- }
-
-});
diff --git a/public/docs/_examples/server-communication/e2e-spec.ts b/public/docs/_examples/server-communication/e2e-spec.ts
new file mode 100644
index 0000000000..a85c7489f8
--- /dev/null
+++ b/public/docs/_examples/server-communication/e2e-spec.ts
@@ -0,0 +1,138 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by } from 'protractor';
+
+describe('Server Communication', function () {
+
+ beforeAll(function () {
+ browser.get('');
+ });
+
+ describe('Tour of Heroes (Observable)', function () {
+
+ let initialHeroCount = 4;
+ let newHeroName = 'Mr. IQ';
+ let heroCountAfterAdd = 5;
+
+ let heroListComp = element(by.tagName('hero-list'));
+ let addButton = heroListComp.element(by.tagName('button'));
+ let heroTags = heroListComp.all(by.tagName('li'));
+ let heroNameInput = heroListComp.element(by.tagName('input'));
+
+ it('should exist', function() {
+ expect(heroListComp).toBeDefined(' must exist');
+ });
+
+ it('should display ' + initialHeroCount + ' heroes after init', function () {
+ expect(heroTags.count()).toBe(initialHeroCount);
+ });
+
+ it('should not add hero with empty name', function () {
+ expect(addButton).toBeDefined('"Add Hero" button must be defined');
+ addButton.click().then(function() {
+ expect(heroTags.count()).toBe(initialHeroCount, 'No new hero should be added');
+ });
+ });
+
+ it('should add a new hero to the list', function () {
+ expect(heroNameInput).toBeDefined(' for hero name must exist');
+ expect(addButton).toBeDefined('"Add Hero" button must be defined');
+ heroNameInput.sendKeys(newHeroName);
+ addButton.click().then(function() {
+ expect(heroTags.count()).toBe(heroCountAfterAdd, 'A new hero should be added');
+ let newHeroInList = heroTags.get(heroCountAfterAdd - 1).getText();
+ expect(newHeroInList).toBe(newHeroName, 'The hero should be added to the end of the list');
+ });
+ });
+ });
+
+ describe('Wikipedia Demo', function () {
+
+ it('should initialize the demo with empty result list', function () {
+ let myWikiComp = element(by.tagName('my-wiki'));
+ expect(myWikiComp).toBeDefined(' must exist');
+ let resultList = myWikiComp.all(by.tagName('li'));
+ expect(resultList.count()).toBe(0, 'result list must be empty');
+ });
+
+ describe('Fetches after each keystroke', function () {
+ it('should fetch results after "B"', function(done: any) {
+ testForRefreshedResult('B', done);
+ });
+
+ it('should fetch results after "Ba"', function(done: any) {
+ testForRefreshedResult('a', done);
+ });
+
+ it('should fetch results after "Bas"', function(done: any) {
+ testForRefreshedResult('s', done);
+ });
+
+ it('should fetch results after "Basic"', function(done: any) {
+ testForRefreshedResult('ic', done);
+ });
+ });
+
+ function testForRefreshedResult(keyPressed: string, done: () => void) {
+ testForResult('my-wiki', keyPressed, false, done);
+ }
+ });
+
+ describe('Smarter Wikipedia Demo', function () {
+
+ it('should initialize the demo with empty result list', function () {
+ let myWikiSmartComp = element(by.tagName('my-wiki-smart'));
+ expect(myWikiSmartComp).toBeDefined(' must exist');
+ let resultList = myWikiSmartComp.all(by.tagName('li'));
+ expect(resultList.count()).toBe(0, 'result list must be empty');
+ });
+
+ it('should fetch results after "Java"', function(done: any) {
+ testForNewResult('Java', done);
+ });
+
+ it('should fetch results after "JavaS"', function(done: any) {
+ testForStaleResult('S', done);
+ });
+
+ it('should fetch results after "JavaSc"', function(done: any) {
+ testForStaleResult('c', done);
+ });
+
+ it('should fetch results after "JavaScript"', function(done: any) {
+ testForStaleResult('ript', done);
+ });
+
+
+ function testForNewResult(keyPressed: string, done: () => void) {
+ testForResult('my-wiki-smart', keyPressed, false, done);
+ }
+
+ function testForStaleResult(keyPressed: string, done: () => void) {
+ testForResult('my-wiki-smart', keyPressed, true, done);
+ }
+
+ });
+
+ function testForResult(componentTagName: string, keyPressed: string, hasListBeforeSearch: boolean, done: () => void) {
+ let searchWait = 1000; // Wait for wikipedia but not so long that tests timeout
+ let wikiComponent = element(by.tagName(componentTagName));
+ expect(wikiComponent).toBeDefined('<' + componentTagName + '> must exist');
+ let searchBox = wikiComponent.element(by.tagName('input'));
+ expect(searchBox).toBeDefined(' for search must exist');
+
+ searchBox.sendKeys(keyPressed).then(function () {
+ let resultList = wikiComponent.all(by.tagName('li'));
+
+ if (hasListBeforeSearch) {
+ expect(resultList.count()).toBeGreaterThan(0, 'result list should not be empty before search');
+ }
+
+ setTimeout(function() {
+ expect(resultList.count()).toBeGreaterThan(0, 'result list should not be empty after search');
+ done();
+ }, searchWait);
+ });
+ }
+
+});
diff --git a/public/docs/_examples/server-communication/ts/.gitignore b/public/docs/_examples/server-communication/ts/.gitignore
deleted file mode 100644
index 2cb7d2a2e9..0000000000
--- a/public/docs/_examples/server-communication/ts/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-**/*.js
diff --git a/public/docs/_examples/server-communication/ts/app/hero-data.ts b/public/docs/_examples/server-communication/ts/app/hero-data.ts
deleted file mode 100644
index 29f58fe663..0000000000
--- a/public/docs/_examples/server-communication/ts/app/hero-data.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-// #docregion
-export class HeroData {
- createDb() {
- let heroes = [
- { "id": "1", "name": "Windstorm" },
- { "id": "2", "name": "Bombasto" },
- { "id": "3", "name": "Magneta" },
- { "id": "4", "name": "Tornado" }
- ];
- return {heroes};
- }
-}
diff --git a/public/docs/_examples/server-communication/ts/app/heroes.json b/public/docs/_examples/server-communication/ts/app/heroes.json
deleted file mode 100644
index c6b5cc91df..0000000000
--- a/public/docs/_examples/server-communication/ts/app/heroes.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "data": [
- { "id": "1", "name": "Windstorm" },
- { "id": "2", "name": "Bombasto" },
- { "id": "3", "name": "Magneta" },
- { "id": "4", "name": "Tornado" }
- ]
-}
diff --git a/public/docs/_examples/server-communication/ts/app/main.ts b/public/docs/_examples/server-communication/ts/app/main.ts
deleted file mode 100644
index c992809065..0000000000
--- a/public/docs/_examples/server-communication/ts/app/main.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-//#docregion
-import {bootstrap} from 'angular2/platform/browser';
-
-// #docregion import-rxjs
-// Add all operators to Observable
-import 'rxjs/Rx';
-// #enddocregion import-rxjs
-
-import {WikiComponent} from './wiki/wiki.component';
-import {WikiSmartComponent} from './wiki/wiki-smart.component';
-import {TohComponent} from './toh/toh.component';
-
-bootstrap(WikiComponent);
-bootstrap(WikiSmartComponent);
-bootstrap(TohComponent);
\ No newline at end of file
diff --git a/public/docs/_examples/server-communication/ts/app/toh/hero-list.component.1.ts b/public/docs/_examples/server-communication/ts/app/toh/hero-list.component.1.ts
deleted file mode 100644
index 2a96ce2df3..0000000000
--- a/public/docs/_examples/server-communication/ts/app/toh/hero-list.component.1.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-// #docregion
-import {Component, OnInit} from 'angular2/core';
-import {Hero} from './hero';
-import {HeroService} from './hero.service.1';
-
-@Component({
- selector: 'hero-list',
-// #docregion template
- template: `
- Heroes:
-
- New Hero:
-
-
- Add Hero
-
- {{errorMessage}}
- `,
- // #enddocregion template
- styles: ['.error {color:red;}']
-})
-// #docregion component
-export class HeroListComponent implements OnInit {
-
- constructor (private _heroService: HeroService) {}
-
- errorMessage: string;
- heroes:Hero[];
-
- ngOnInit() { this.getHeroes(); }
-
- // #docregion methods
- getHeroes() {
- this._heroService.getHeroes()
- .then(
- heroes => this.heroes = heroes,
- error => this.errorMessage = error);
- }
-
- addHero (name: string) {
- if (!name) {return;}
- this._heroService.addHero(name)
- .then(
- hero => this.heroes.push(hero),
- error => this.errorMessage = error);
- }
- // #enddocregion methods
-}
-// #enddocregion component
diff --git a/public/docs/_examples/server-communication/ts/app/toh/hero-list.component.ts b/public/docs/_examples/server-communication/ts/app/toh/hero-list.component.ts
deleted file mode 100644
index a55cf35a72..0000000000
--- a/public/docs/_examples/server-communication/ts/app/toh/hero-list.component.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-// #docregion
-import {Component, OnInit} from 'angular2/core';
-import {Hero} from './hero';
-import {HeroService} from './hero.service';
-
-@Component({
- selector: 'hero-list',
- template: `
- Heroes:
-
- New Hero:
-
-
- Add Hero
-
- {{errorMessage}}
- `,
- styles: ['.error {color:red;}']
-})
-// #docregion component
-export class HeroListComponent implements OnInit {
-
- constructor (private _heroService: HeroService) {}
-
- errorMessage: string;
- heroes:Hero[];
-
- ngOnInit() { this.getHeroes(); }
-
- // #docregion methods
- // #docregion getHeroes
- getHeroes() {
- this._heroService.getHeroes()
- .subscribe(
- heroes => this.heroes = heroes,
- error => this.errorMessage = error);
- }
- // #enddocregion getHeroes
-
- // #docregion addHero
- addHero (name: string) {
- if (!name) {return;}
- this._heroService.addHero(name)
- .subscribe(
- hero => this.heroes.push(hero),
- error => this.errorMessage = error);
- }
- // #enddocregion addHero
- // #enddocregion methods
-}
-// #enddocregion component
diff --git a/public/docs/_examples/server-communication/ts/app/toh/hero.service.1.ts b/public/docs/_examples/server-communication/ts/app/toh/hero.service.1.ts
deleted file mode 100644
index d5734fffc5..0000000000
--- a/public/docs/_examples/server-communication/ts/app/toh/hero.service.1.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Promise version */
-// #docplaster
-
-// #docregion
-import {Injectable} from 'angular2/core';
-import {Http, Response} from 'angular2/http';
-import {Headers, RequestOptions} from 'angular2/http';
-import {Hero} from './hero';
-
-@Injectable()
-export class HeroService {
- constructor (private http: Http) {}
-
- // URL to web api
- private _heroesUrl = 'app/heroes.json';
-
- // #docregion methods
- getHeroes () {
- return this.http.get(this._heroesUrl)
- .toPromise()
- .then(res => res.json().data, this.handleError)
- .then(data => { console.log(data); return data; }); // eyeball results in the console
- }
-
- addHero (name: string) : Promise {
- let body = JSON.stringify({ name });
- let headers = new Headers({ 'Content-Type': 'application/json' });
- let options = new RequestOptions({ headers: headers });
-
- return this.http.post(this._heroesUrl, body, options)
- .toPromise()
- .then(res => res.json().data)
- .catch(this.handleError);
- }
-
- private handleError (error: any) {
- // in a real world app, we may send the error to some remote logging infrastructure
- // instead of just logging it to the console
- console.error(error);
- return Promise.reject(error.message || error.json().error || 'Server error');
- }
-// #enddocregion methods
-}
-// #enddocregion
diff --git a/public/docs/_examples/server-communication/ts/app/toh/hero.service.ts b/public/docs/_examples/server-communication/ts/app/toh/hero.service.ts
deleted file mode 100644
index 7ff9805ac0..0000000000
--- a/public/docs/_examples/server-communication/ts/app/toh/hero.service.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-// #docplaster
-
-// #docregion
-// #docregion v1
-import {Injectable} from 'angular2/core';
-import {Http, Response} from 'angular2/http';
-// #enddocregion v1
-// #docregion import-request-options
-import {Headers, RequestOptions} from 'angular2/http';
-// #enddocregion import-request-options
-// #docregion v1
-import {Hero} from './hero';
-import {Observable} from 'rxjs/Observable';
-
-@Injectable()
-export class HeroService {
- constructor (private http: Http) {}
-// #enddocregion
-// #enddocregion v1
-
- /*
- // #docregion endpoint-json
- private _heroesUrl = 'app/heroes.json'; // URL to JSON file
- // #enddocregion endpoint-json
- */
-// #docregion
-// #docregion v1
-
- // #docregion endpoint
- private _heroesUrl = 'app/heroes'; // URL to web api
- // #enddocregion endpoint
-
- // #docregion methods
- // #docregion error-handling
- getHeroes () {
- // #docregion http-get, http-get-v1
- return this.http.get(this._heroesUrl)
- .map(res => res.json().data)
- // #enddocregion v1, http-get-v1, error-handling
- .do(data => console.log(data)) // eyeball results in the console
- // #docregion v1, http-get-v1, error-handling
- .catch(this.handleError);
- // #enddocregion http-get, http-get-v1
- }
- // #enddocregion error-handling
- // #enddocregion v1
-
- // #docregion addhero
- addHero (name: string) : Observable {
-
- let body = JSON.stringify({ name });
- //#docregion headers
- let headers = new Headers({ 'Content-Type': 'application/json' });
- let options = new RequestOptions({ headers: headers });
-
- return this.http.post(this._heroesUrl, body, options)
- //#enddocregion headers
- .map(res => res.json().data)
- .catch(this.handleError)
- }
- // #enddocregion addhero
-
- // #docregion v1
- // #docregion error-handling
- private handleError (error: Response) {
- // in a real world app, we may send the error to some remote logging infrastructure
- // instead of just logging it to the console
- console.error(error);
- return Observable.throw(error.json().error || 'Server error');
- }
- // #enddocregion error-handling
- // #enddocregion methods
-}
-// #enddocregion
diff --git a/public/docs/_examples/server-communication/ts/app/toh/hero.ts b/public/docs/_examples/server-communication/ts/app/toh/hero.ts
deleted file mode 100644
index bf664b0eec..0000000000
--- a/public/docs/_examples/server-communication/ts/app/toh/hero.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-// #docregion
-export class Hero {
- constructor(
- public id:number,
- public name:string) { }
-}
diff --git a/public/docs/_examples/server-communication/ts/app/toh/toh.component.ts b/public/docs/_examples/server-communication/ts/app/toh/toh.component.ts
deleted file mode 100644
index bc93e5c9c9..0000000000
--- a/public/docs/_examples/server-communication/ts/app/toh/toh.component.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-// #docplaster
-
-// #docregion
-import {Component} from 'angular2/core';
-import {HTTP_PROVIDERS} from 'angular2/http';
-
-import {Hero} from './hero';
-import {HeroListComponent} from './hero-list.component';
-import {HeroService} from './hero.service';
-//#enddocregion
-
-//#docregion in-mem-web-api-imports
-import {provide} from 'angular2/core';
-import {XHRBackend} from 'angular2/http';
-
-// in-memory web api imports
-import {InMemoryBackendService,
- SEED_DATA} from 'a2-in-memory-web-api/core';
-import {HeroData} from '../hero-data';
-// #enddocregion in-mem-web-api-imports
-//#docregion
-
-@Component({
- selector: 'my-toh',
-// #docregion template
- template: `
- Tour of Heroes
-
- `,
- // #enddocregion template
- directives:[HeroListComponent],
- providers: [
- HTTP_PROVIDERS,
- HeroService,
-//#enddocregion
-//#docregion in-mem-web-api-providers
- // in-memory web api providers
- provide(XHRBackend, { useClass: InMemoryBackendService }), // in-mem server
- provide(SEED_DATA, { useClass: HeroData }) // in-mem server data
-//#enddocregion in-mem-web-api-providers
-//#docregion
- ]
-})
-export class TohComponent { }
-// #enddocregion
diff --git a/public/docs/_examples/server-communication/ts/app/wiki/wiki-smart.component.ts b/public/docs/_examples/server-communication/ts/app/wiki/wiki-smart.component.ts
deleted file mode 100644
index dad9dacaf6..0000000000
--- a/public/docs/_examples/server-communication/ts/app/wiki/wiki-smart.component.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-// #docregion
-import {Component} from 'angular2/core';
-import {JSONP_PROVIDERS} from 'angular2/http';
-import {Observable} from 'rxjs/Observable';
-// #docregion import-subject
-import {Subject} from 'rxjs/Subject';
-// #enddocregion import-subject
-
-import {WikipediaService} from './wikipedia.service';
-
-@Component({
- selector: 'my-wiki-smart',
- template: `
- Smarter Wikipedia Demo
- Fetches when typing stops
-
-
-
-
- `,
- providers:[JSONP_PROVIDERS, WikipediaService]
-})
-export class WikiSmartComponent {
-
- constructor (private _wikipediaService: WikipediaService) { }
-
- // #docregion subject
- private _searchTermStream = new Subject();
-
- search(term:string) { this._searchTermStream.next(term); }
- // #enddocregion subject
-
- // #docregion observable-operators
- items:Observable = this._searchTermStream
- .debounceTime(300)
- .distinctUntilChanged()
- .switchMap((term:string) => this._wikipediaService.search(term));
-// #enddocregion observable-operators
-}
diff --git a/public/docs/_examples/server-communication/ts/app/wiki/wiki.component.ts b/public/docs/_examples/server-communication/ts/app/wiki/wiki.component.ts
deleted file mode 100644
index c6b6e9888a..0000000000
--- a/public/docs/_examples/server-communication/ts/app/wiki/wiki.component.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-// #docregion
-import {Component} from 'angular2/core';
-import {JSONP_PROVIDERS} from 'angular2/http';
-import {Observable} from 'rxjs/Observable';
-
-import {WikipediaService} from './wikipedia.service';
-
-@Component({
- selector: 'my-wiki',
- template: `
- Wikipedia Demo
- Fetches after each keystroke
-
-
-
-
- `,
- providers:[JSONP_PROVIDERS, WikipediaService]
-})
-export class WikiComponent {
-
- constructor (private _wikipediaService: WikipediaService) {}
-
- items: Observable;
-
- search (term: string) {
- this.items = this._wikipediaService.search(term);
- }
-}
diff --git a/public/docs/_examples/server-communication/ts/app/wiki/wikipedia.service.1.ts b/public/docs/_examples/server-communication/ts/app/wiki/wikipedia.service.1.ts
deleted file mode 100644
index b88038f2f2..0000000000
--- a/public/docs/_examples/server-communication/ts/app/wiki/wikipedia.service.1.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-// Create the query string by hand
-// #docregion
-import {Injectable} from 'angular2/core';
-import {Jsonp} from 'angular2/http';
-
-@Injectable()
-export class WikipediaService {
- constructor(private jsonp: Jsonp) { }
-
- // TODO: Add error handling
- search(term: string) {
-
- let wikiUrl = 'http://en.wikipedia.org/w/api.php';
-
- // #docregion query-string
- let queryString =
- `?search=${term}&action=opensearch&format=json&callback=JSONP_CALLBACK`
-
- return this.jsonp
- .get(wikiUrl + queryString)
- .map(request => request.json()[1]);
- // #enddocregion query-string
- }
-}
diff --git a/public/docs/_examples/server-communication/ts/app/wiki/wikipedia.service.ts b/public/docs/_examples/server-communication/ts/app/wiki/wikipedia.service.ts
deleted file mode 100644
index 01b328c3b3..0000000000
--- a/public/docs/_examples/server-communication/ts/app/wiki/wikipedia.service.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-// #docregion
-import {Injectable} from 'angular2/core';
-import {Jsonp, URLSearchParams} from 'angular2/http';
-
-@Injectable()
-export class WikipediaService {
- constructor(private jsonp: Jsonp) {}
-
- search (term: string) {
-
- let wikiUrl = 'http://en.wikipedia.org/w/api.php';
-
- // #docregion search-parameters
- var params = new URLSearchParams();
- params.set('search', term); // the user's search value
- params.set('action', 'opensearch');
- params.set('format', 'json');
- params.set('callback', 'JSONP_CALLBACK');
- // #enddocregion search-parameters
-
- // #docregion call-jsonp
- // TODO: Add error handling
- return this.jsonp
- .get(wikiUrl, { search: params })
- .map(request => request.json()[1]);
- // #enddocregion call-jsonp
- }
-}
diff --git a/public/docs/_examples/server-communication/ts/index.html b/public/docs/_examples/server-communication/ts/index.html
deleted file mode 100644
index 94c08df802..0000000000
--- a/public/docs/_examples/server-communication/ts/index.html
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
- Angular 2 Http Demo
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ToH Loading...
- Wiki Loading...
- WikiSmart Loading...
-
-
-
diff --git a/public/docs/_examples/server-communication/ts/plnkr.json b/public/docs/_examples/server-communication/ts/plnkr.json
index fd35eda20d..fe966be012 100644
--- a/public/docs/_examples/server-communication/ts/plnkr.json
+++ b/public/docs/_examples/server-communication/ts/plnkr.json
@@ -1,9 +1,10 @@
{
"description": "Http",
+ "basePath": "src/",
"files":[
"!**/*.d.ts",
"!**/*.js",
"!**/*.[1].*"
],
"tags": ["http", "jsonp"]
-}
\ No newline at end of file
+}
diff --git a/public/docs/_examples/server-communication/ts/src/app/app.component.ts b/public/docs/_examples/server-communication/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..780d044cab
--- /dev/null
+++ b/public/docs/_examples/server-communication/ts/src/app/app.component.ts
@@ -0,0 +1,13 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ template: `
+
+
+
+
+ `
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/server-communication/ts/src/app/app.module.1.ts b/public/docs/_examples/server-communication/ts/src/app/app.module.1.ts
new file mode 100644
index 0000000000..fb7012aa02
--- /dev/null
+++ b/public/docs/_examples/server-communication/ts/src/app/app.module.1.ts
@@ -0,0 +1,23 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { FormsModule } from '@angular/forms';
+import { HttpModule, JsonpModule } from '@angular/http';
+
+import { AppComponent } from './app.component';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ FormsModule,
+ HttpModule,
+ JsonpModule
+ ],
+ declarations: [ AppComponent ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule {
+}
+
+
+
diff --git a/public/docs/_examples/server-communication/ts/src/app/app.module.ts b/public/docs/_examples/server-communication/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..fd0c720c3c
--- /dev/null
+++ b/public/docs/_examples/server-communication/ts/src/app/app.module.ts
@@ -0,0 +1,46 @@
+// #docplaster
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { FormsModule } from '@angular/forms';
+import { HttpModule, JsonpModule } from '@angular/http';
+
+
+import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
+import { HeroData } from './hero-data';
+import { requestOptionsProvider } from './default-request-options.service';
+
+import { AppComponent } from './app.component';
+
+import { HeroListComponent } from './toh/hero-list.component';
+import { HeroListPromiseComponent } from './toh/hero-list.component.promise';
+
+import { WikiComponent } from './wiki/wiki.component';
+import { WikiSmartComponent } from './wiki/wiki-smart.component';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ FormsModule,
+ HttpModule,
+ JsonpModule,
+ // #docregion in-mem-web-api
+ InMemoryWebApiModule.forRoot(HeroData)
+ // #enddocregion in-mem-web-api
+ ],
+ declarations: [
+ AppComponent,
+ HeroListComponent,
+ HeroListPromiseComponent,
+ WikiComponent,
+ WikiSmartComponent
+ ],
+// #docregion provide-default-request-options
+ providers: [ requestOptionsProvider ],
+// #enddocregion provide-default-request-options
+ bootstrap: [ AppComponent ]
+})
+export class AppModule {}
+
+
+
diff --git a/public/docs/_examples/server-communication/ts/src/app/default-request-options.service.ts b/public/docs/_examples/server-communication/ts/src/app/default-request-options.service.ts
new file mode 100644
index 0000000000..9ec52daa80
--- /dev/null
+++ b/public/docs/_examples/server-communication/ts/src/app/default-request-options.service.ts
@@ -0,0 +1,16 @@
+// #docregion
+import { Injectable } from '@angular/core';
+import { BaseRequestOptions, RequestOptions } from '@angular/http';
+
+@Injectable()
+export class DefaultRequestOptions extends BaseRequestOptions {
+
+ constructor() {
+ super();
+
+ // Set the default 'Content-Type' header
+ this.headers.set('Content-Type', 'application/json');
+ }
+}
+
+export const requestOptionsProvider = { provide: RequestOptions, useClass: DefaultRequestOptions };
diff --git a/public/docs/_examples/server-communication/ts/src/app/hero-data.ts b/public/docs/_examples/server-communication/ts/src/app/hero-data.ts
new file mode 100644
index 0000000000..4db6aca115
--- /dev/null
+++ b/public/docs/_examples/server-communication/ts/src/app/hero-data.ts
@@ -0,0 +1,13 @@
+// #docregion
+import { InMemoryDbService } from 'angular-in-memory-web-api';
+export class HeroData implements InMemoryDbService {
+ createDb() {
+ let heroes = [
+ { id: 1, name: 'Windstorm' },
+ { id: 2, name: 'Bombasto' },
+ { id: 3, name: 'Magneta' },
+ { id: 4, name: 'Tornado' }
+ ];
+ return {heroes};
+ }
+}
diff --git a/public/docs/_examples/server-communication/ts/src/app/heroes.json b/public/docs/_examples/server-communication/ts/src/app/heroes.json
new file mode 100644
index 0000000000..dfb589066b
--- /dev/null
+++ b/public/docs/_examples/server-communication/ts/src/app/heroes.json
@@ -0,0 +1,8 @@
+{
+ "data": [
+ { "id": 1, "name": "Windstorm" },
+ { "id": 2, "name": "Bombasto" },
+ { "id": 3, "name": "Magneta" },
+ { "id": 4, "name": "Tornado" }
+ ]
+}
diff --git a/public/docs/_examples/server-communication/ts/src/app/toh/hero-list.component.html b/public/docs/_examples/server-communication/ts/src/app/toh/hero-list.component.html
new file mode 100644
index 0000000000..65ca9cfbb7
--- /dev/null
+++ b/public/docs/_examples/server-communication/ts/src/app/toh/hero-list.component.html
@@ -0,0 +1,11 @@
+
+Tour of Heroes ({{mode}})
+Heroes:
+
+
+New hero name:
+Add Hero
+
+{{errorMessage}}
diff --git a/public/docs/_examples/server-communication/ts/src/app/toh/hero-list.component.promise.ts b/public/docs/_examples/server-communication/ts/src/app/toh/hero-list.component.promise.ts
new file mode 100644
index 0000000000..4bbe7eade2
--- /dev/null
+++ b/public/docs/_examples/server-communication/ts/src/app/toh/hero-list.component.promise.ts
@@ -0,0 +1,40 @@
+// #docregion
+// Promise Version
+import { Component, OnInit } from '@angular/core';
+import { Hero } from './hero';
+import { HeroService } from './hero.service.promise';
+
+@Component({
+ selector: 'hero-list-promise',
+ templateUrl: './hero-list.component.html',
+ providers: [ HeroService ],
+ styles: ['.error {color:red;}']
+})
+// #docregion component
+export class HeroListPromiseComponent implements OnInit {
+ errorMessage: string;
+ heroes: Hero[];
+ mode = 'Promise';
+
+ constructor (private heroService: HeroService) {}
+
+ ngOnInit() { this.getHeroes(); }
+
+ // #docregion methods
+ getHeroes() {
+ this.heroService.getHeroes()
+ .then(
+ heroes => this.heroes = heroes,
+ error => this.errorMessage = error);
+ }
+
+ addHero (name: string) {
+ if (!name) { return; }
+ this.heroService.addHero(name)
+ .then(
+ hero => this.heroes.push(hero),
+ error => this.errorMessage = error);
+ }
+ // #enddocregion methods
+}
+// #enddocregion component
diff --git a/public/docs/_examples/server-communication/ts/src/app/toh/hero-list.component.ts b/public/docs/_examples/server-communication/ts/src/app/toh/hero-list.component.ts
new file mode 100644
index 0000000000..8cca504762
--- /dev/null
+++ b/public/docs/_examples/server-communication/ts/src/app/toh/hero-list.component.ts
@@ -0,0 +1,44 @@
+// #docregion
+// Observable Version
+import { Component, OnInit } from '@angular/core';
+import { Hero } from './hero';
+import { HeroService } from './hero.service';
+
+@Component({
+ selector: 'hero-list',
+ templateUrl: './hero-list.component.html',
+ providers: [ HeroService ],
+ styles: ['.error {color:red;}']
+})
+// #docregion component
+export class HeroListComponent implements OnInit {
+ errorMessage: string;
+ heroes: Hero[];
+ mode = 'Observable';
+
+ constructor (private heroService: HeroService) {}
+
+ ngOnInit() { this.getHeroes(); }
+
+ // #docregion methods
+ // #docregion getHeroes
+ getHeroes() {
+ this.heroService.getHeroes()
+ .subscribe(
+ heroes => this.heroes = heroes,
+ error => this.errorMessage = error);
+ }
+ // #enddocregion getHeroes
+
+ // #docregion addHero
+ addHero(name: string) {
+ if (!name) { return; }
+ this.heroService.create(name)
+ .subscribe(
+ hero => this.heroes.push(hero),
+ error => this.errorMessage = error);
+ }
+ // #enddocregion addHero
+ // #enddocregion methods
+}
+// #enddocregion component
diff --git a/public/docs/_examples/server-communication/ts/src/app/toh/hero.service.promise.ts b/public/docs/_examples/server-communication/ts/src/app/toh/hero.service.promise.ts
new file mode 100644
index 0000000000..e38bd4bebf
--- /dev/null
+++ b/public/docs/_examples/server-communication/ts/src/app/toh/hero.service.promise.ts
@@ -0,0 +1,60 @@
+// #docplaster
+// #docregion
+// Promise Version
+import { Injectable } from '@angular/core';
+import { Http, Response } from '@angular/http';
+import { Headers, RequestOptions } from '@angular/http';
+
+// #docregion rxjs-imports
+import 'rxjs/add/operator/toPromise';
+// #enddocregion rxjs-imports
+
+import { Hero } from './hero';
+
+@Injectable()
+export class HeroService {
+ // URL to web api
+ private heroesUrl = 'app/heroes';
+
+ constructor (private http: Http) {}
+
+ // #docregion methods
+ getHeroes (): Promise {
+ return this.http.get(this.heroesUrl)
+ .toPromise()
+ .then(this.extractData)
+ .catch(this.handleError);
+ }
+
+ addHero (name: string): Promise {
+ let headers = new Headers({ 'Content-Type': 'application/json' });
+ let options = new RequestOptions({ headers: headers });
+
+ return this.http.post(this.heroesUrl, { name }, options)
+ .toPromise()
+ .then(this.extractData)
+ .catch(this.handleError);
+ }
+
+ private extractData(res: Response) {
+ let body = res.json();
+ return body.data || { };
+ }
+
+ private handleError (error: Response | any) {
+ // In a real world app, we might use a remote logging infrastructure
+ let errMsg: string;
+ if (error instanceof Response) {
+ const body = error.json() || '';
+ const err = body.error || JSON.stringify(body);
+ errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
+ } else {
+ errMsg = error.message ? error.message : error.toString();
+ }
+ console.error(errMsg);
+ return Promise.reject(errMsg);
+ }
+
+// #enddocregion methods
+}
+// #enddocregion
diff --git a/public/docs/_examples/server-communication/ts/src/app/toh/hero.service.ts b/public/docs/_examples/server-communication/ts/src/app/toh/hero.service.ts
new file mode 100644
index 0000000000..4f0da49021
--- /dev/null
+++ b/public/docs/_examples/server-communication/ts/src/app/toh/hero.service.ts
@@ -0,0 +1,80 @@
+// #docplaster
+// #docregion
+// Observable Version
+// #docregion v1
+import { Injectable } from '@angular/core';
+import { Http, Response } from '@angular/http';
+// #enddocregion v1
+// #docregion import-request-options
+import { Headers, RequestOptions } from '@angular/http';
+// #enddocregion import-request-options
+// #docregion v1
+
+// #docregion rxjs-imports
+import { Observable } from 'rxjs/Observable';
+import 'rxjs/add/operator/catch';
+import 'rxjs/add/operator/map';
+// #enddocregion rxjs-imports
+
+import { Hero } from './hero';
+
+@Injectable()
+export class HeroService {
+ // #docregion endpoint
+ private heroesUrl = 'api/heroes'; // URL to web API
+ // #enddocregion endpoint
+
+ // #docregion ctor
+ constructor (private http: Http) {}
+ // #enddocregion ctor
+
+ // #docregion methods, error-handling, http-get
+ getHeroes(): Observable {
+ return this.http.get(this.heroesUrl)
+ .map(this.extractData)
+ .catch(this.handleError);
+ }
+ // #enddocregion error-handling, http-get, v1
+
+ // #docregion create, create-sig
+ create(name: string): Observable {
+ // #enddocregion create-sig
+ let headers = new Headers({ 'Content-Type': 'application/json' });
+ let options = new RequestOptions({ headers: headers });
+
+ return this.http.post(this.heroesUrl, { name }, options)
+ .map(this.extractData)
+ .catch(this.handleError);
+ }
+ // #enddocregion create
+
+ // #docregion v1, extract-data
+ private extractData(res: Response) {
+ let body = res.json();
+ return body.data || { };
+ }
+ // #enddocregion extract-data
+ // #docregion error-handling
+
+ private handleError (error: Response | any) {
+ // In a real world app, you might use a remote logging infrastructure
+ let errMsg: string;
+ if (error instanceof Response) {
+ const body = error.json() || '';
+ const err = body.error || JSON.stringify(body);
+ errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
+ } else {
+ errMsg = error.message ? error.message : error.toString();
+ }
+ console.error(errMsg);
+ return Observable.throw(errMsg);
+ }
+ // #enddocregion error-handling, methods
+}
+// #enddocregion
+
+/*
+ // #docregion endpoint-json
+ private heroesUrl = 'app/heroes.json'; // URL to JSON file
+ // #enddocregion endpoint-json
+*/
diff --git a/public/docs/_examples/server-communication/ts/src/app/toh/hero.ts b/public/docs/_examples/server-communication/ts/src/app/toh/hero.ts
new file mode 100644
index 0000000000..09b8d295ce
--- /dev/null
+++ b/public/docs/_examples/server-communication/ts/src/app/toh/hero.ts
@@ -0,0 +1,6 @@
+// #docregion
+export class Hero {
+ constructor(
+ public id: number,
+ public name: string) { }
+}
diff --git a/public/docs/_examples/server-communication/ts/src/app/wiki/wiki-smart.component.ts b/public/docs/_examples/server-communication/ts/src/app/wiki/wiki-smart.component.ts
new file mode 100644
index 0000000000..fc453a820e
--- /dev/null
+++ b/public/docs/_examples/server-communication/ts/src/app/wiki/wiki-smart.component.ts
@@ -0,0 +1,47 @@
+/* tslint:disable: member-ordering forin */
+// #docplaster
+// #docregion
+import { Component, OnInit } from '@angular/core';
+
+// #docregion rxjs-imports
+import { Observable } from 'rxjs/Observable';
+import 'rxjs/add/operator/debounceTime';
+import 'rxjs/add/operator/distinctUntilChanged';
+import 'rxjs/add/operator/switchMap';
+
+// #docregion import-subject
+import { Subject } from 'rxjs/Subject';
+// #enddocregion import-subject
+
+import { WikipediaService } from './wikipedia.service';
+
+@Component({
+ selector: 'my-wiki-smart',
+ template: `
+ Smarter Wikipedia Demo
+ Search when typing stops
+
+ `,
+ providers: [ WikipediaService ]
+})
+export class WikiSmartComponent implements OnInit {
+ items: Observable;
+
+ constructor (private wikipediaService: WikipediaService) {}
+
+ // #docregion subject
+ private searchTermStream = new Subject();
+ search(term: string) { this.searchTermStream.next(term); }
+ // #enddocregion subject
+
+ ngOnInit() {
+ // #docregion observable-operators
+ this.items = this.searchTermStream
+ .debounceTime(300)
+ .distinctUntilChanged()
+ .switchMap((term: string) => this.wikipediaService.search(term));
+ // #enddocregion observable-operators
+ }
+}
diff --git a/public/docs/_examples/server-communication/ts/src/app/wiki/wiki.component.ts b/public/docs/_examples/server-communication/ts/src/app/wiki/wiki.component.ts
new file mode 100644
index 0000000000..4230df12a1
--- /dev/null
+++ b/public/docs/_examples/server-communication/ts/src/app/wiki/wiki.component.ts
@@ -0,0 +1,26 @@
+// #docregion
+import { Component } from '@angular/core';
+import { Observable } from 'rxjs/Observable';
+
+import { WikipediaService } from './wikipedia.service';
+
+@Component({
+ selector: 'my-wiki',
+ template: `
+ Wikipedia Demo
+ Search after each keystroke
+
+ `,
+ providers: [ WikipediaService ]
+})
+export class WikiComponent {
+ items: Observable;
+
+ constructor (private wikipediaService: WikipediaService) { }
+
+ search (term: string) {
+ this.items = this.wikipediaService.search(term);
+ }
+}
diff --git a/public/docs/_examples/server-communication/ts/src/app/wiki/wikipedia.service.1.ts b/public/docs/_examples/server-communication/ts/src/app/wiki/wikipedia.service.1.ts
new file mode 100644
index 0000000000..5cbcb7d707
--- /dev/null
+++ b/public/docs/_examples/server-communication/ts/src/app/wiki/wikipedia.service.1.ts
@@ -0,0 +1,26 @@
+// Create the query string by hand
+// #docregion
+import { Injectable } from '@angular/core';
+import { Jsonp } from '@angular/http';
+
+import 'rxjs/add/operator/map';
+
+@Injectable()
+export class WikipediaService {
+ constructor(private jsonp: Jsonp) { }
+
+ // TODO: Add error handling
+ search(term: string) {
+
+ let wikiUrl = 'http://en.wikipedia.org/w/api.php';
+
+ // #docregion query-string
+ let queryString =
+ `?search=${term}&action=opensearch&format=json&callback=JSONP_CALLBACK`;
+
+ return this.jsonp
+ .get(wikiUrl + queryString)
+ .map(response => response.json()[1]);
+ // #enddocregion query-string
+ }
+}
diff --git a/public/docs/_examples/server-communication/ts/src/app/wiki/wikipedia.service.ts b/public/docs/_examples/server-communication/ts/src/app/wiki/wikipedia.service.ts
new file mode 100644
index 0000000000..a38167d1c6
--- /dev/null
+++ b/public/docs/_examples/server-communication/ts/src/app/wiki/wikipedia.service.ts
@@ -0,0 +1,30 @@
+// #docregion
+import { Injectable } from '@angular/core';
+import { Jsonp, URLSearchParams } from '@angular/http';
+
+import 'rxjs/add/operator/map';
+
+@Injectable()
+export class WikipediaService {
+ constructor(private jsonp: Jsonp) {}
+
+ search (term: string) {
+
+ let wikiUrl = 'http://en.wikipedia.org/w/api.php';
+
+ // #docregion search-parameters
+ let params = new URLSearchParams();
+ params.set('search', term); // the user's search value
+ params.set('action', 'opensearch');
+ params.set('format', 'json');
+ params.set('callback', 'JSONP_CALLBACK');
+ // #enddocregion search-parameters
+
+ // #docregion call-jsonp
+ // TODO: Add error handling
+ return this.jsonp
+ .get(wikiUrl, { search: params })
+ .map(response => response.json()[1]);
+ // #enddocregion call-jsonp
+ }
+}
diff --git a/public/docs/_examples/server-communication/ts/src/index.html b/public/docs/_examples/server-communication/ts/src/index.html
new file mode 100644
index 0000000000..5c51f21c91
--- /dev/null
+++ b/public/docs/_examples/server-communication/ts/src/index.html
@@ -0,0 +1,27 @@
+
+
+
+
+ Angular Http Demo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
diff --git a/public/docs/_examples/server-communication/ts/src/main.ts b/public/docs/_examples/server-communication/ts/src/main.ts
new file mode 100644
index 0000000000..6b6532d428
--- /dev/null
+++ b/public/docs/_examples/server-communication/ts/src/main.ts
@@ -0,0 +1,5 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/setup/e2e-spec.ts b/public/docs/_examples/setup/e2e-spec.ts
new file mode 100644
index 0000000000..73921707ee
--- /dev/null
+++ b/public/docs/_examples/setup/e2e-spec.ts
@@ -0,0 +1,17 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by } from 'protractor';
+
+describe('QuickStart E2E Tests', function () {
+
+ let expectedMsg = 'Hello Angular';
+
+ beforeEach(function () {
+ browser.get('');
+ });
+
+ it(`should display: ${expectedMsg}`, function () {
+ expect(element(by.css('h1')).getText()).toEqual(expectedMsg);
+ });
+
+});
diff --git a/public/docs/_examples/setup/ts/example-config.json b/public/docs/_examples/setup/ts/example-config.json
new file mode 100644
index 0000000000..eb33c943c7
--- /dev/null
+++ b/public/docs/_examples/setup/ts/example-config.json
@@ -0,0 +1,3 @@
+{
+ "unittesting": true
+}
diff --git a/public/docs/_examples/setup/ts/non-essential-files.txt b/public/docs/_examples/setup/ts/non-essential-files.txt
new file mode 100644
index 0000000000..3c9cdde9dc
--- /dev/null
+++ b/public/docs/_examples/setup/ts/non-essential-files.txt
@@ -0,0 +1,13 @@
+.git
+.gitignore
+.travis.yml
+*.spec*.ts
+CHANGELOG.md
+e2e
+favicon.ico
+karma.conf.js
+karma-test-shim.js
+LICENSE
+non-essential-files.txt
+protractor.config.js
+README.md
diff --git a/public/docs/_examples/setup/ts/plnkr.json b/public/docs/_examples/setup/ts/plnkr.json
new file mode 100644
index 0000000000..22b528eec5
--- /dev/null
+++ b/public/docs/_examples/setup/ts/plnkr.json
@@ -0,0 +1,13 @@
+{
+ "description": "QuickStart Setup",
+ "basePath": "src/",
+ "files": [
+ "app/app.component.ts",
+ "app/app.module.ts",
+ "index.html",
+ "main.ts",
+ "styles.css"
+ ],
+ "open": "app/app.component.ts",
+ "tags": ["quickstart", "setup", "seed"]
+}
diff --git a/public/docs/_examples/setup/ts/quickstart-specs.plnkr.json b/public/docs/_examples/setup/ts/quickstart-specs.plnkr.json
new file mode 100644
index 0000000000..a7dfedb595
--- /dev/null
+++ b/public/docs/_examples/setup/ts/quickstart-specs.plnkr.json
@@ -0,0 +1,13 @@
+{
+ "description": "Quickstart AppComponent Testing",
+ "basePath": "src/",
+ "files":[
+ "browser-test-shim.js",
+ "app/app.component.ts",
+ "app/app.component.spec.ts",
+ "quickstart-specs.html"
+ ],
+ "main": "quickstart-specs.html",
+ "open": "app/app.component.spec.ts",
+ "tags": ["quickstart", "setup", "testing"]
+}
diff --git a/public/docs/_examples/setup/ts/src/app/app.component.spec.ts b/public/docs/_examples/setup/ts/src/app/app.component.spec.ts
new file mode 100644
index 0000000000..7769024464
--- /dev/null
+++ b/public/docs/_examples/setup/ts/src/app/app.component.spec.ts
@@ -0,0 +1,33 @@
+import { AppComponent } from './app.component';
+
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { DebugElement } from '@angular/core';
+
+describe('AppComponent', function () {
+ let de: DebugElement;
+ let comp: AppComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ AppComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(AppComponent);
+ comp = fixture.componentInstance;
+ de = fixture.debugElement.query(By.css('h1'));
+ });
+
+ it('should create component', () => expect(comp).toBeDefined() );
+
+ it('should have expected text', () => {
+ fixture.detectChanges();
+ const h1 = de.nativeElement;
+ expect(h1.innerText).toMatch(/angular/i,
+ ' should say something about "Angular"');
+ });
+});
diff --git a/public/docs/_examples/setup/ts/src/app/app.component.ts b/public/docs/_examples/setup/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..1ef28fc5c4
--- /dev/null
+++ b/public/docs/_examples/setup/ts/src/app/app.component.ts
@@ -0,0 +1,8 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ template: `Hello {{name}} `
+})
+export class AppComponent { name = 'Angular'; }
diff --git a/public/docs/_examples/setup/ts/src/app/app.module.ts b/public/docs/_examples/setup/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..50a0e6eb47
--- /dev/null
+++ b/public/docs/_examples/setup/ts/src/app/app.module.ts
@@ -0,0 +1,11 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { AppComponent } from './app.component';
+
+@NgModule({
+ imports: [ BrowserModule ],
+ declarations: [ AppComponent ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/setup/ts/src/index.html b/public/docs/_examples/setup/ts/src/index.html
new file mode 100644
index 0000000000..58e5112308
--- /dev/null
+++ b/public/docs/_examples/setup/ts/src/index.html
@@ -0,0 +1,28 @@
+
+
+
+
+ Angular Quickstart Seed
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/public/docs/_examples/setup/ts/src/main.ts b/public/docs/_examples/setup/ts/src/main.ts
new file mode 100644
index 0000000000..02d58dceac
--- /dev/null
+++ b/public/docs/_examples/setup/ts/src/main.ts
@@ -0,0 +1,5 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/setup/ts/src/quickstart-specs.html b/public/docs/_examples/setup/ts/src/quickstart-specs.html
new file mode 100644
index 0000000000..9bc81ccf2e
--- /dev/null
+++ b/public/docs/_examples/setup/ts/src/quickstart-specs.html
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+ 1st Specs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/public/docs/_examples/setup/ts/src/systemjs.config.extras.js b/public/docs/_examples/setup/ts/src/systemjs.config.extras.js
new file mode 100644
index 0000000000..027dfe58cf
--- /dev/null
+++ b/public/docs/_examples/setup/ts/src/systemjs.config.extras.js
@@ -0,0 +1,11 @@
+/**
+ * Add barrels and stuff
+ * Adjust as necessary for your application needs.
+ */
+// (function (global) {
+// System.config({
+// packages: {
+// // add packages here
+// }
+// });
+// })(this);
diff --git a/public/docs/_examples/structural-directives/dart/lib/heavy_loader_component.dart b/public/docs/_examples/structural-directives/dart/lib/heavy_loader_component.dart
deleted file mode 100644
index 647542accc..0000000000
--- a/public/docs/_examples/structural-directives/dart/lib/heavy_loader_component.dart
+++ /dev/null
@@ -1,32 +0,0 @@
-// #docregion
-import 'dart:async';
-
-import 'package:angular2/angular2.dart';
-
-int nextId = 1;
-
-@Component(
- selector: 'heavy-loader',
- template: 'heavy loader #{{id}} on duty! ')
-class HeavyLoaderComponent implements OnInit, OnDestroy {
- int id = nextId++;
- @Input() List logs;
-
- // Mock todo: get 10,000 rows of data from the server
- ngOnInit() => _log(
- "heavy-loader $id initialized, loading 10,000 rows of data from the server");
-
- // Mock todo: clean-up
- ngOnDestroy() => _log("heavy-loader $id destroyed, cleaning up");
-
- _log(String msg) {
- logs.add(msg);
- _tick();
- }
-
- /// Triggers the next round of Angular change detection
- /// after one turn of the browser event loop
- /// ensuring display of msg added in onDestroy
- _tick() => new Future(() {});
-}
-// #enddocregion
diff --git a/public/docs/_examples/structural-directives/dart/lib/structural_directives_component.dart b/public/docs/_examples/structural-directives/dart/lib/structural_directives_component.dart
deleted file mode 100644
index 477b372bb0..0000000000
--- a/public/docs/_examples/structural-directives/dart/lib/structural_directives_component.dart
+++ /dev/null
@@ -1,21 +0,0 @@
-// #docplaster
-// #docregion
-import 'package:angular2/angular2.dart';
-
-import 'heavy_loader_component.dart';
-import 'unless_directive.dart';
-
-@Component(
- selector: 'structural-directives',
- templateUrl: 'structural_directives_component.html',
- styles: const ['button { min-width: 100px; }'],
- directives: const [UnlessDirective, HeavyLoaderComponent])
-class StructuralDirectivesComponent {
- List heroes = ['Mr. Nice', 'Narco', 'Bombasto'];
- bool condition = true;
- bool isVisible = true;
- List logs = [];
- String status = 'ready';
-
- get hero => heroes[0];
-}
diff --git a/public/docs/_examples/structural-directives/dart/lib/structural_directives_component.html b/public/docs/_examples/structural-directives/dart/lib/structural_directives_component.html
deleted file mode 100644
index 2ea022222a..0000000000
--- a/public/docs/_examples/structural-directives/dart/lib/structural_directives_component.html
+++ /dev/null
@@ -1,108 +0,0 @@
-
-
-Structural Directives
-
-
-
-{{hero}}
-{{hero}}
-
-
-
- In Mission
- Ready
- Unknown
-
-
-
-
-
-
-
- Set 'condition' to {{condition ? 'False': 'True'}}
-
-
-
-
- condition is true and ngIf is true.
-
-
- condition is false and ngIf is false.
-
-
-
-
- condition is false and myUnless is true.
-
-
-
- condition is true and myUnless is false.
-
-
-
-
-
-
-
- show | hide
-
-
-
-
- if | !if
-
-
-
-heavy-loader log:
-{{message}}
-
-
-
-
-
-
- Hip!
-
-
-
- Hip!
-
-
-
- Hooray!
-
-
-
-
-
-
-
-
-
- Our heroes are true!
-
-
-
-
-
- Our heroes are true!
-
-
-
-
-
-
-
-
-
-
-{{ hero }}
-
-
-
- {{ hero }}
-
-
diff --git a/public/docs/_examples/structural-directives/dart/lib/unless_directive.dart b/public/docs/_examples/structural-directives/dart/lib/unless_directive.dart
deleted file mode 100644
index 7760658b48..0000000000
--- a/public/docs/_examples/structural-directives/dart/lib/unless_directive.dart
+++ /dev/null
@@ -1,31 +0,0 @@
-// #docplaster
-// #docregion
-// #docregion unless-declaration
-import 'package:angular2/angular2.dart';
-// #enddocregion unless-declaration
-
-// #docregion unless-declaration
-@Directive(selector: '[myUnless]')
-class UnlessDirective {
- // #enddocregion unless-declaration
-
- // #docregion unless-constructor
- TemplateRef _templateRef;
- ViewContainerRef _viewContainer;
-
- UnlessDirective(this._templateRef, this._viewContainer);
- // #enddocregion unless-constructor
-
- // #docregion unless-set
- @Input()
- set myUnless(bool condition) {
- if (!condition) {
- _viewContainer.createEmbeddedView(_templateRef);
- } else {
- _viewContainer.clear();
- }
- }
- // #enddocregion unless-set
- // #docregion unless-declaration
-}
-// #enddocregion unless-declaration
diff --git a/public/docs/_examples/structural-directives/dart/pubspec.yaml b/public/docs/_examples/structural-directives/dart/pubspec.yaml
deleted file mode 100644
index 24255bb66f..0000000000
--- a/public/docs/_examples/structural-directives/dart/pubspec.yaml
+++ /dev/null
@@ -1,15 +0,0 @@
-# #docregion
-name: structural_directives
-description: Structural directives example
-version: 0.0.1
-environment:
- sdk: '>=1.13.0 <2.0.0'
-dependencies:
- angular2: 2.0.0-beta.8
- browser: ^0.10.0
- dart_to_js_script_rewriter: ^0.1.0
-transformers:
-- angular2:
- platform_directives: 'package:angular2/common.dart#CORE_DIRECTIVES'
- entry_points: web/main.dart
-- dart_to_js_script_rewriter
diff --git a/public/docs/_examples/structural-directives/dart/web/index.html b/public/docs/_examples/structural-directives/dart/web/index.html
deleted file mode 100644
index 38da87dc69..0000000000
--- a/public/docs/_examples/structural-directives/dart/web/index.html
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
- Angular 2 Structural Directives
-
-
-
-
-
-
- Loading...
-
-
-
diff --git a/public/docs/_examples/structural-directives/dart/web/main.dart b/public/docs/_examples/structural-directives/dart/web/main.dart
deleted file mode 100644
index 2c00f66c65..0000000000
--- a/public/docs/_examples/structural-directives/dart/web/main.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-// #docregion
-import 'package:angular2/bootstrap.dart';
-import 'package:structural_directives/structural_directives_component.dart';
-
-main() {
- bootstrap(StructuralDirectivesComponent);
-}
diff --git a/public/docs/_examples/structural-directives/e2e-spec.js b/public/docs/_examples/structural-directives/e2e-spec.js
deleted file mode 100644
index a2ed0455b9..0000000000
--- a/public/docs/_examples/structural-directives/e2e-spec.js
+++ /dev/null
@@ -1,64 +0,0 @@
-describe('Structural Directives', function () {
-
- // tests interact - so we need beforeEach instead of beforeAll
- beforeEach(function () {
- browser.get('');
- });
-
- it('should be able to use ngFor, ngIf and ngWhen together', function () {
- var allDivEles = element.all(by.css('structural-directives > div'));
- expect(allDivEles.get(0).getText()).toEqual('Mr. Nice');
- expect(allDivEles.get(1).getText()).toEqual('Mr. Nice');
- expect(allDivEles.get(4).getText()).toEqual('Ready');
- });
-
- it('should be able to toggle ngIf with a button', function () {
- var setConditionButtonEle = element.all(by.css('button')).get(0);
- var conditionTrueEles = element.all(by.cssContainingText('p', 'condition is true'));
- var conditionFalseEles = element.all(by.cssContainingText('p', 'condition is false'));
- expect(conditionTrueEles.count()).toBe(2, 'should be two condition true elements');
- expect(conditionFalseEles.count()).toBe(0, 'should be no condition false elements');
- setConditionButtonEle.click().then(function() {
- expect(conditionTrueEles.count()).toBe(0, 'should be no condition true elements');
- expect(conditionFalseEles.count()).toBe(2, 'should be two condition false elements');
- });
- });
-
- it('should be able to compare use of ngIf with changing css visibility', function () {
- var setConditionButtonEle = element.all(by.css('button')).get(0);
- var ngIfButtonEle = element(by.cssContainingText('button', 'if | !if'));
- var ngIfParentEle = ngIfButtonEle.element(by.xpath('..'));
- var ngIfSiblingEle = ngIfParentEle.element(by.css('heavy-loader'));
- var cssButtonEle = element(by.cssContainingText('button', 'show | hide'));
- var cssSiblingEle = cssButtonEle.element(by.xpath('..')).element(by.css('heavy-loader'));
- var setConditionText;
- setConditionButtonEle.getText().then(function(text) {
- setConditionText = text;
- expect(ngIfButtonEle.isPresent()).toBe(true, 'should be able to find ngIfButton');
- expect(cssButtonEle.isPresent()).toBe(true, 'should be able to find cssButton');
- expect(ngIfParentEle.isPresent()).toBe(true, 'should be able to find ngIfButton parent');
- expect(ngIfSiblingEle.isPresent()).toBe(true, 'should be able to find ngIfButton sibling');
- expect(cssSiblingEle.isPresent()).toBe(true, 'should be able to find cssButton sibling');
- return ngIfButtonEle.click();
- }).then(function() {
- expect(ngIfSiblingEle.isPresent()).toBe(false, 'now should NOT be able to find ngIfButton sibling');
- expect(setConditionButtonEle.getText()).not.toEqual(setConditionText);
- return cssButtonEle.click();
- }).then(function() {
- expect(cssSiblingEle.isPresent()).toBe(true, 'now should still be able to find cssButton sibling');
- expect(cssSiblingEle.isDisplayed()).toBe(false, 'now cssButton sibling should NOT be visible');
- return ngIfButtonEle.click();
- }).then(function() {
- expect(setConditionButtonEle.getText()).toEqual(setConditionText);
- });
- });
-
- it('should be able to use *ngIf ', function () {
- var setConditionButtonEle = element.all(by.css('button')).get(0);
- var displayEles = element.all(by.cssContainingText('p', 'Our heroes are true!'));
- expect(displayEles.count()).toBe(2, "should be displaying two ngIf elements");
- setConditionButtonEle.click().then(function() {
- expect(displayEles.count()).toBe(0, "should nog longer be displaying ngIf elements");
- });
- });
-});
diff --git a/public/docs/_examples/structural-directives/e2e-spec.ts b/public/docs/_examples/structural-directives/e2e-spec.ts
new file mode 100644
index 0000000000..51f30bf0bb
--- /dev/null
+++ b/public/docs/_examples/structural-directives/e2e-spec.ts
@@ -0,0 +1,58 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by } from 'protractor';
+
+describe('Structural Directives', function () {
+
+ beforeAll(function () {
+ browser.get('');
+ });
+
+ it('first div should show hero name with *ngIf', function () {
+ const allDivs = element.all(by.tagName('div'));
+ expect(allDivs.get(0).getText()).toEqual('Mr. Nice');
+ });
+
+ it('first li should show hero name with *ngFor', function () {
+ const allLis = element.all(by.tagName('li'));
+ expect(allLis.get(0).getText()).toEqual('Mr. Nice');
+ });
+
+ it('ngSwitch have three instances', function () {
+ const happyHeroEls = element.all(by.tagName('happy-hero'));
+ expect(happyHeroEls.count()).toEqual(3);
+ });
+
+ it('should toggle *ngIf="hero" with a button', function () {
+ const toggleHeroButton = element.all(by.cssContainingText('button', 'Toggle hero')).get(0);
+ const paragraph = element.all(by.cssContainingText('p', 'I turned the corner'));
+ expect(paragraph.get(0).getText()).toContain('I waved');
+ toggleHeroButton.click().then(() => {
+ expect(paragraph.get(0).getText()).not.toContain('I waved');
+ });
+ });
+
+ it('should have only one "Hip!" (the other is erased)', function () {
+ const paragraph = element.all(by.cssContainingText('p', 'Hip!'));
+ expect(paragraph.count()).toEqual(1);
+ });
+
+ it('myUnless should show 3 paragraph (A)s and (B)s at the start', function () {
+ const paragraph = element.all(by.css('p.unless'));
+ expect(paragraph.count()).toEqual(3);
+ for (let i = 0; i < 3; i++) {
+ expect(paragraph.get(i).getText()).toContain('(A)');
+ }
+ });
+
+ it('myUnless should show 1 paragraph (B) after toggling condition', function () {
+ const toggleConditionButton = element.all(by.cssContainingText('button', 'Toggle condition')).get(0);
+ const paragraph = element.all(by.css('p.unless'));
+
+ toggleConditionButton.click().then(() => {
+ expect(paragraph.count()).toEqual(1);
+ expect(paragraph.get(0).getText()).toContain('(B)');
+ });
+ });
+});
+
diff --git a/public/docs/_examples/structural-directives/ts/.gitignore b/public/docs/_examples/structural-directives/ts/.gitignore
deleted file mode 100644
index 2cb7d2a2e9..0000000000
--- a/public/docs/_examples/structural-directives/ts/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-**/*.js
diff --git a/public/docs/_examples/structural-directives/ts/app/heavy-loader.component.ts b/public/docs/_examples/structural-directives/ts/app/heavy-loader.component.ts
deleted file mode 100644
index 1b22384f75..0000000000
--- a/public/docs/_examples/structural-directives/ts/app/heavy-loader.component.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-// #docregion
-import {Component, Input, Output} from 'angular2/core';
-
-let nextId = 1;
-
-@Component({
- selector: 'heavy-loader',
- template: 'heavy loader #{{id}} on duty! '
-})
-export class HeavyLoaderComponent {
- id = nextId++;
- @Input() logs: string[];
-
- ngOnInit() {
- // Mock todo: get 10,000 rows of data from the server
- this._log(`heavy-loader ${this.id} initialized,
- loading 10,000 rows of data from the server`);
- }
-
- ngOnDestroy() {
- // Mock todo: clean-up
- this._log(`heavy-loader ${this.id} destroyed, cleaning up`);
- }
-
- private _log(msg: string) {
- this.logs.push(msg);
- this._tick();
- }
-
- // Triggers the next round of Angular change detection
- // after one turn of the browser event loop
- // ensuring display of msg added in onDestroy
- private _tick() { setTimeout(() => { }, 0); }
-}
-// #enddocregion
diff --git a/public/docs/_examples/structural-directives/ts/app/main.ts b/public/docs/_examples/structural-directives/ts/app/main.ts
deleted file mode 100644
index da28d75daf..0000000000
--- a/public/docs/_examples/structural-directives/ts/app/main.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import {bootstrap} from 'angular2/platform/browser';
-import {StructuralDirectivesComponent} from './structural-directives.component';
-
-bootstrap(StructuralDirectivesComponent);
diff --git a/public/docs/_examples/structural-directives/ts/app/structural-directives.component.html b/public/docs/_examples/structural-directives/ts/app/structural-directives.component.html
deleted file mode 100644
index c7aa615932..0000000000
--- a/public/docs/_examples/structural-directives/ts/app/structural-directives.component.html
+++ /dev/null
@@ -1,109 +0,0 @@
-
-
-Structural Directives
-
-
-
-{{hero}}
-{{hero}}
-
-
-
- In Mission
- Ready
- Unknown
-
-
-
-
-
-
-
- Set 'condition' to {{condition ? 'False': 'True'}}
-
-
-
-
- condition is true and ngIf is true.
-
-
- condition is false and ngIf is false.
-
-
-
-
- condition is false and myUnless is true.
-
-
-
- condition is true and myUnless is false.
-
-
-
-
-
-
-
- show | hide
-
-
-
-
- if | !if
-
-
-
-heavy-loader log:
-{{message}}
-
-
-
-
-
-
- Hip!
-
-
-
- Hip!
-
-
-
- Hooray!
-
-
-
-
-
-
-
-
-
- Our heroes are true!
-
-
-
-
-
- Our heroes are true!
-
-
-
-
-
-
-
-
-
-
-{{ hero }}
-
-
-
- {{ hero }}
-
-
-
diff --git a/public/docs/_examples/structural-directives/ts/app/structural-directives.component.ts b/public/docs/_examples/structural-directives/ts/app/structural-directives.component.ts
deleted file mode 100644
index 4174edb05f..0000000000
--- a/public/docs/_examples/structural-directives/ts/app/structural-directives.component.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-// #docplaster
-// #docregion
-import {Component, Input, Output} from 'angular2/core';
-import {UnlessDirective} from './unless.directive';
-import {HeavyLoaderComponent} from './heavy-loader.component';
-
-@Component({
- selector: 'structural-directives',
- templateUrl: 'app/structural-directives.component.html',
- styles: ['button { min-width: 100px; }'],
- directives: [UnlessDirective, HeavyLoaderComponent]
-})
-export class StructuralDirectivesComponent {
- heroes = ['Mr. Nice', 'Narco', 'Bombasto'];
- hero = this.heroes[0];
- condition = true;
- isVisible = true;
- logs: string[] = [];
- status = 'ready';
-}
-//#enddocregion
diff --git a/public/docs/_examples/structural-directives/ts/app/unless.directive.ts b/public/docs/_examples/structural-directives/ts/app/unless.directive.ts
deleted file mode 100644
index 76f84b6408..0000000000
--- a/public/docs/_examples/structural-directives/ts/app/unless.directive.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-// #docplaster
-// #docregion
-// #docregion unless-declaration
-import {Directive, Input} from 'angular2/core';
-
-// #enddocregion unless-declaration
-import {TemplateRef, ViewContainerRef} from 'angular2/core';
-
-// #docregion unless-declaration
-@Directive({ selector: '[myUnless]' })
-export class UnlessDirective {
- // #enddocregion unless-declaration
-
- // #docregion unless-constructor
- constructor(
- private _templateRef: TemplateRef,
- private _viewContainer: ViewContainerRef
- ) { }
- // #enddocregion unless-constructor
-
- // #docregion unless-set
- @Input() set myUnless(condition: boolean) {
- if (!condition) {
- this._viewContainer.createEmbeddedView(this._templateRef);
- } else {
- this._viewContainer.clear();
- }
- }
- // #enddocregion unless-set
- // #docregion unless-declaration
-}
-// #enddocregion unless-declaration
-// #enddocregion
diff --git a/public/docs/_examples/structural-directives/ts/index.html b/public/docs/_examples/structural-directives/ts/index.html
deleted file mode 100644
index 3716c56686..0000000000
--- a/public/docs/_examples/structural-directives/ts/index.html
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
- Angular 2 Structural Directives
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Loading...
-
-
-
diff --git a/public/docs/_examples/structural-directives/ts/plnkr.json b/public/docs/_examples/structural-directives/ts/plnkr.json
index 32bfd6302a..58a26d7b4f 100644
--- a/public/docs/_examples/structural-directives/ts/plnkr.json
+++ b/public/docs/_examples/structural-directives/ts/plnkr.json
@@ -1,6 +1,11 @@
{
"description": "Structural directives",
- "files": ["!**/*.d.ts", "!**/*.js"],
+ "basePath": "src/",
+ "files": [
+ "!**/*.d.ts",
+ "!**/*.js",
+ "!app/scrap.txt"
+ ],
"tags": [
"structural", "directives", "template", "ngIf",
"ngSwitch", "ngFor"
diff --git a/public/docs/_examples/structural-directives/ts/src/app/app.component.css b/public/docs/_examples/structural-directives/ts/src/app/app.component.css
new file mode 100644
index 0000000000..e28be894f8
--- /dev/null
+++ b/public/docs/_examples/structural-directives/ts/src/app/app.component.css
@@ -0,0 +1,70 @@
+/* #docregion */
+button {
+ min-width: 100px;
+ font-size: 100%;
+}
+
+.box {
+ border: 1px solid gray;
+ max-width: 600px;
+ padding: 4px;
+}
+.choices {
+ font-style: italic;
+}
+
+code, .code {
+ background-color: #eee;
+ color: black;
+ font-family: Courier, sans-serif;
+ font-size: 85%;
+}
+
+div.code {
+ width: 400px;
+}
+
+.heroic {
+ font-size: 150%;
+ font-weight: bold;
+}
+
+hr {
+ margin: 40px 0
+}
+
+.odd {
+ background-color: palegoldenrod;
+}
+
+td, th {
+ text-align: left;
+ vertical-align: top;
+}
+
+/* #docregion p-span */
+p span { color: red; font-size: 70%; }
+/* #enddocregion p-span */
+
+.unless {
+ border: 2px solid;
+ padding: 6px;
+}
+
+p.unless {
+ width: 500px;
+}
+
+button.a, span.a, .unless.a {
+ color: red;
+ border-color: gold;
+ background-color: yellow;
+ font-size: 100%;
+}
+
+button.b, span.b, .unless.b {
+ color: black;
+ border-color: green;
+ background-color: lightgreen;
+ font-size: 100%;
+}
diff --git a/public/docs/_examples/structural-directives/ts/src/app/app.component.html b/public/docs/_examples/structural-directives/ts/src/app/app.component.html
new file mode 100644
index 0000000000..49c4928aad
--- /dev/null
+++ b/public/docs/_examples/structural-directives/ts/src/app/app.component.html
@@ -0,0 +1,250 @@
+
+
+Structural Directives
+
+Conditional display of hero
+
+
+
+{{hero.name}}
+
+
+
+List of heroes
+
+
+
+
+
+
+
+
+NgIf
+
+
+
+ Expression is true and ngIf is true.
+ This paragraph is in the DOM.
+
+
+ Expression is false and ngIf is false.
+ This paragraph is not in the DOM.
+
+
+
+
+
+ Expression sets display to "block".
+ This paragraph is visible.
+
+
+ Expression sets display to "none".
+ This paragraph is hidden but still in the DOM.
+
+
+
+NgIf with template
+<ng-template> element
+
+
+ {{hero.name}}
+
+
+
+template attribute
+
+{{hero.name}}
+
+
+
+
+<ng-container>
+
+*ngIf with a <ng-container>
+
+Toggle hero
+
+
+
+ I turned the corner
+
+ and saw {{hero.name}}. I waved
+
+ and continued on my way.
+
+
+
+
+ I turned the corner
+
+ and saw {{hero.name}}. I waved
+
+ and continued on my way.
+
+
+
+<select> with <span>
+
+
+ Pick your favorite hero
+ ( show sad )
+
+
+
+
+ {{h.name}} ({{h.emotion}})
+
+
+
+
+
+<select> with <ng-container>
+
+
+ Pick your favorite hero
+ ( show sad )
+
+
+
+
+ {{h.name}} ({{h.emotion}})
+
+
+
+
+
+
+
+
+NgFor
+
+
+
+
<div *ngFor="let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd">
+
+
+ ({{i}}) {{hero.name}}
+
+
+
+
<div template="ngFor let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd">
+
+
+ ({{i}}) {{hero.name}}
+
+
+
+
<template ngFor let-hero [ngForOf]="heroes" let-i="index" let-odd="odd" [ngForTrackBy]="trackById">
+
+
+ ({{i}}) {{hero.name}}
+
+
+
+
+
+
+NgSwitch
+
+Pick your favorite hero
+
+
+ {{h.name}}
+
+ None of the above
+
+
+NgSwitch
+
+
+
+
+
+
+
+
+
+
+NgSwitch with template attribute
+
+
+
+
+
+
+
+
+
+NgSwitch with <ng-template>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<template>
+
+Hip!
+
+ Hip!
+
+Hooray!
+
+
+
+
+UnlessDirective
+
+ The condition is currently
+ {{condition}} .
+
+ Toggle condition to {{condition ? 'false' : 'true'}}
+
+
+
+
+ (A) This paragraph is displayed because the condition is false.
+
+
+
+ (B) Although the condition is true,
+ this paragraph is displayed because myUnless is set to false.
+
+
+
+
+UnlessDirective with template
+
+
+Show this sentence unless the condition is true.
+
+
+
+ (A) <p template="myUnless condition" class="code unless">
+
+
+
+
+ (A) <template [myUnless]="condition">
+
+
+
diff --git a/public/docs/_examples/structural-directives/ts/src/app/app.component.ts b/public/docs/_examples/structural-directives/ts/src/app/app.component.ts
new file mode 100644
index 0000000000..ff6f0e65a1
--- /dev/null
+++ b/public/docs/_examples/structural-directives/ts/src/app/app.component.ts
@@ -0,0 +1,23 @@
+// #docregion
+import { Component } from '@angular/core';
+
+import { Hero, heroes } from './hero';
+
+@Component({
+ selector: 'my-app',
+ templateUrl: './app.component.html',
+ styleUrls: [ './app.component.css' ]
+})
+export class AppComponent {
+ heroes = heroes;
+ hero = this.heroes[0];
+
+ condition = false;
+ logs: string[] = [];
+ showSad = true;
+ status = 'ready';
+
+ // #docregion trackByHero
+ trackById(index: number, hero: Hero): number { return hero.id; }
+ // #enddocregion trackByHero
+}
diff --git a/public/docs/_examples/structural-directives/ts/src/app/app.module.ts b/public/docs/_examples/structural-directives/ts/src/app/app.module.ts
new file mode 100644
index 0000000000..b6ffb456c9
--- /dev/null
+++ b/public/docs/_examples/structural-directives/ts/src/app/app.module.ts
@@ -0,0 +1,19 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+import { BrowserModule } from '@angular/platform-browser';
+
+import { AppComponent } from './app.component';
+import { heroSwitchComponents } from './hero-switch.components';
+import { UnlessDirective } from './unless.directive';
+
+@NgModule({
+ imports: [ BrowserModule, FormsModule ],
+ declarations: [
+ AppComponent,
+ heroSwitchComponents,
+ UnlessDirective
+ ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/structural-directives/ts/src/app/hero-switch.components.ts b/public/docs/_examples/structural-directives/ts/src/app/hero-switch.components.ts
new file mode 100644
index 0000000000..6608422d15
--- /dev/null
+++ b/public/docs/_examples/structural-directives/ts/src/app/hero-switch.components.ts
@@ -0,0 +1,43 @@
+// #docregion
+import { Component, Input } from '@angular/core';
+import { Hero } from './hero';
+
+@Component({
+ selector: 'happy-hero',
+ template: `Wow. You like {{hero.name}}. What a happy hero ... just like you.`
+})
+export class HappyHeroComponent {
+ @Input() hero: Hero;
+}
+
+@Component({
+ selector: 'sad-hero',
+ template: `You like {{hero.name}}? Such a sad hero. Are you sad too?`
+})
+export class SadHeroComponent {
+ @Input() hero: Hero;
+}
+
+@Component({
+ selector: 'confused-hero',
+ template: `Are you as confused as {{hero.name}}?`
+})
+export class ConfusedHeroComponent {
+ @Input() hero: Hero;
+}
+
+@Component({
+ selector: 'unknown-hero',
+ template: `{{message}}`
+})
+export class UnknownHeroComponent {
+ @Input() hero: Hero;
+ get message() {
+ return this.hero && this.hero.name ?
+ `${this.hero.name} is strange and mysterious.` :
+ 'Are you feeling indecisive?';
+ }
+}
+
+export const heroSwitchComponents =
+ [ HappyHeroComponent, SadHeroComponent, ConfusedHeroComponent, UnknownHeroComponent ];
diff --git a/public/docs/_examples/structural-directives/ts/src/app/hero.ts b/public/docs/_examples/structural-directives/ts/src/app/hero.ts
new file mode 100644
index 0000000000..a1de3b3b82
--- /dev/null
+++ b/public/docs/_examples/structural-directives/ts/src/app/hero.ts
@@ -0,0 +1,13 @@
+// #docregion
+export class Hero {
+ id: number;
+ name: string;
+ emotion?: string;
+}
+
+export const heroes: Hero[] = [
+ { id: 1, name: 'Mr. Nice', emotion: 'happy'},
+ { id: 2, name: 'Narco', emotion: 'sad' },
+ { id: 3, name: 'Windstorm', emotion: 'confused' },
+ { id: 4, name: 'Magneta'}
+];
diff --git a/public/docs/_examples/structural-directives/ts/src/app/scrap.txt b/public/docs/_examples/structural-directives/ts/src/app/scrap.txt
new file mode 100644
index 0000000000..96426d37f0
--- /dev/null
+++ b/public/docs/_examples/structural-directives/ts/src/app/scrap.txt
@@ -0,0 +1,21 @@
+// interesting but unused code
+ heroChooser(picker: HTMLFieldSetElement) {
+ let choices = picker.children;
+ this.favoriteHero = undefined;
+ for (let i = 0; i < choices.length; i++) {
+ let choice = choices[i].children[0] as HTMLInputElement;
+ if (choice.checked) { this.favoriteHero = this.heroes[i]; }
+ }
+ }
+
+
+Switch with *ngFor repeated switchCases using <ng-container>
+
+
+ Your favorite hero is ...
+
+ {{hero.name}}
+
+ None of the above
+
+
diff --git a/public/docs/_examples/structural-directives/ts/src/app/unless.directive.ts b/public/docs/_examples/structural-directives/ts/src/app/unless.directive.ts
new file mode 100644
index 0000000000..470bbd932f
--- /dev/null
+++ b/public/docs/_examples/structural-directives/ts/src/app/unless.directive.ts
@@ -0,0 +1,51 @@
+// #docplaster
+// #docregion
+// #docregion no-docs, skeleton
+import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
+
+// #enddocregion skeleton
+/**
+ * Add the template content to the DOM unless the condition is true.
+// #enddocregion no-docs
+ *
+ * If the expression assigned to `myUnless` evaluates to a truthy value
+ * then the templated elements are removed removed from the DOM,
+ * the templated elements are (re)inserted into the DOM.
+ *
+ *
+ * Congrats! Everything is great!
+ *
+ *
+ * ### Syntax
+ *
+ * - `...
`
+ * - `...
`
+ * - `...
`
+ *
+// #docregion no-docs
+ */
+// #docregion skeleton
+@Directive({ selector: '[myUnless]'})
+export class UnlessDirective {
+ // #enddocregion skeleton
+ private hasView = false;
+
+ // #docregion ctor
+ constructor(
+ private templateRef: TemplateRef,
+ private viewContainer: ViewContainerRef) { }
+ // #enddocregion ctor
+
+ // #docregion set
+ @Input() set myUnless(condition: boolean) {
+ if (!condition && !this.hasView) {
+ this.viewContainer.createEmbeddedView(this.templateRef);
+ this.hasView = true;
+ } else if (condition && this.hasView) {
+ this.viewContainer.clear();
+ this.hasView = false;
+ }
+ }
+ // #enddocregion set
+ // #docregion skeleton
+}
diff --git a/public/docs/_examples/structural-directives/ts/src/index.html b/public/docs/_examples/structural-directives/ts/src/index.html
new file mode 100644
index 0000000000..ce7a33266d
--- /dev/null
+++ b/public/docs/_examples/structural-directives/ts/src/index.html
@@ -0,0 +1,27 @@
+
+
+
+
+ Angular Structural Directives
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
diff --git a/public/docs/_examples/structural-directives/ts/src/main.ts b/public/docs/_examples/structural-directives/ts/src/main.ts
new file mode 100644
index 0000000000..105b06712d
--- /dev/null
+++ b/public/docs/_examples/structural-directives/ts/src/main.ts
@@ -0,0 +1,6 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
+
diff --git a/public/docs/_examples/style-guide/e2e-spec.ts b/public/docs/_examples/style-guide/e2e-spec.ts
new file mode 100644
index 0000000000..d143ae5573
--- /dev/null
+++ b/public/docs/_examples/style-guide/e2e-spec.ts
@@ -0,0 +1,191 @@
+'use strict'; // necessary for es6 output in node
+
+import { browser, element, by } from 'protractor';
+
+describe('Style Guide', function () {
+ it('01-01', function () {
+ browser.get('#/01-01');
+
+ let pre = element(by.tagName('toh-heroes > pre'));
+ expect(pre.getText()).toContain('Bombasto');
+ expect(pre.getText()).toContain('Tornado');
+ expect(pre.getText()).toContain('Magneta');
+ });
+
+ it('02-07', function () {
+ browser.get('#/02-07');
+
+ let hero = element(by.tagName('toh-hero > div'));
+ let users = element(by.tagName('admin-users > div'));
+
+ expect(hero.getText()).toBe('hero component');
+ expect(users.getText()).toBe('users component');
+ });
+
+ it('02-08', function () {
+ browser.get('#/02-08');
+
+ let input = element(by.tagName('input[tohvalidate]'));
+ expect(input.isPresent()).toBe(true);
+ });
+
+ it('03-01', function () {
+ browser.get('#/03-01');
+
+ let div = element(by.tagName('sg-app > div'));
+ expect(div.getText()).toBe('The expected error is 42');
+ });
+
+ it('03-02', function () {
+ browser.get('#/03-02');
+
+ let divs = element.all(by.tagName('sg-app > div'));
+ expect(divs.get(0).getText()).toBe('Heroes url: api/heroes');
+ expect(divs.get(1).getText()).toBe('Villains url: api/villains');
+ });
+
+ it('03-03', function () {
+ browser.get('#/03-03');
+
+ let div = element(by.tagName('sg-app > div'));
+ expect(div.getText()).toBe('Our hero is RubberMan and He is so elastic');
+ });
+
+ it('03-04', function () {
+ browser.get('#/03-04');
+
+ let buttons = element.all(by.tagName('sg-app > button'));
+ expect(buttons.get(0).getText()).toBe('Show toast');
+ expect(buttons.get(1).getText()).toBe('Hide toast');
+ });
+
+ it('03-06', function () {
+ browser.get('#/03-06');
+
+ let div = element(by.tagName('sg-app > div'));
+ expect(div.getText()).toBe('Actual favorite: Windstorm');
+
+ let lis = element.all(by.tagName('sg-app > ul > li'));
+ expect(lis.get(0).getText()).toBe('Windstorm');
+ expect(lis.get(1).getText()).toBe('Bombasto');
+ expect(lis.get(2).getText()).toBe('Magneta');
+ expect(lis.get(3).getText()).toBe('Tornado');
+ });
+
+ it('04-10', function () {
+ browser.get('#/04-10');
+
+ let div = element(by.tagName('sg-app > toh-heroes > div'));
+ expect(div.getText()).toBe('This is heroes component');
+ });
+
+ it('05-02', function () {
+ browser.get('#/05-02');
+
+ let button = element(by.tagName('sg-app > toh-hero-button > button'));
+ expect(button.getText()).toBe('Hero button');
+ });
+
+ it('05-03', function () {
+ browser.get('#/05-03');
+
+ let button = element(by.tagName('sg-app > toh-hero-button > button'));
+ expect(button.getText()).toBe('Hero button');
+ });
+
+ it('05-04', function () {
+ browser.get('#/05-04');
+
+ let h2 = element(by.tagName('sg-app > toh-heroes > div > h2'));
+ expect(h2.getText()).toBe('My Heroes');
+ });
+
+ it('05-12', function () {
+ browser.get('#/05-12');
+
+ let button = element(by.tagName('sg-app > toh-hero-button > button'));
+ expect(button.getText()).toBe('OK');
+ });
+
+ it('05-13', function () {
+ browser.get('#/05-13');
+
+ let button = element(by.tagName('sg-app > toh-hero-button > button'));
+ expect(button.getText()).toBe('OK');
+ });
+
+ it('05-14', function () {
+ browser.get('#/05-14');
+
+ let toast = element(by.tagName('sg-app > toh-toast'));
+ expect(toast.getText()).toBe('...');
+ });
+
+ it('05-15', function () {
+ browser.get('#/05-15');
+
+ let heroList = element(by.tagName('sg-app > toh-hero-list'));
+ expect(heroList.getText()).toBe('...');
+ });
+
+ it('05-16', function () {
+ browser.get('#/05-16');
+
+ let hero = element(by.tagName('sg-app > toh-hero'));
+ expect(hero.getText()).toBe('...');
+ });
+
+ it('05-17', function () {
+ browser.get('#/05-17');
+
+ let section = element(by.tagName('sg-app > toh-hero-list > section'));
+ expect(section.getText()).toContain('Our list of heroes');
+ expect(section.getText()).toContain('Total powers');
+ expect(section.getText()).toContain('Average power');
+ });
+
+ it('06-01', function () {
+ browser.get('#/06-01');
+
+ let div = element(by.tagName('sg-app > div[tohhighlight]'));
+ expect(div.getText()).toBe('Bombasta');
+ });
+
+ it('06-03', function () {
+ browser.get('#/06-03');
+
+ let input = element(by.tagName('input[tohvalidator]'));
+ expect(input.isPresent()).toBe(true);
+ });
+
+ it('07-01', function () {
+ browser.get('#/07-01');
+
+ let lis = element.all(by.tagName('sg-app > ul > li'));
+ expect(lis.get(0).getText()).toBe('Windstorm');
+ expect(lis.get(1).getText()).toBe('Bombasto');
+ expect(lis.get(2).getText()).toBe('Magneta');
+ expect(lis.get(3).getText()).toBe('Tornado');
+ });
+
+ it('07-03', function () {
+ browser.get('#/07-03');
+
+ let pre = element(by.tagName('toh-heroes > pre'));
+ expect(pre.getText()).toContain('[]');
+ });
+
+ it('07-04', function () {
+ browser.get('#/07-04');
+
+ let pre = element(by.tagName('toh-app > pre'));
+ expect(pre.getText()).toContain('[]');
+ });
+
+ it('09-01', function () {
+ browser.get('#/09-01');
+
+ let button = element(by.tagName('sg-app > toh-hero-button > button'));
+ expect(button.getText()).toBe('OK');
+ });
+});
diff --git a/public/docs/_examples/style-guide/ts/.gitignore b/public/docs/_examples/style-guide/ts/.gitignore
new file mode 100644
index 0000000000..bd6423cecb
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/.gitignore
@@ -0,0 +1,2 @@
+*.js
+!systemjs.custom.js
diff --git a/public/docs/_examples/style-guide/ts/example-config.json b/public/docs/_examples/style-guide/ts/example-config.json
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/public/docs/_examples/style-guide/ts/plnkr.json b/public/docs/_examples/style-guide/ts/plnkr.json
new file mode 100644
index 0000000000..bf9e9681c5
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/plnkr.json
@@ -0,0 +1,9 @@
+{
+ "description": "Style Guide",
+ "basePath": "src/",
+ "files":[
+ "!**/*.d.ts",
+ "!**/*.js"
+ ],
+ "tags": ["style guide, styleguide"]
+}
diff --git a/public/docs/_examples/style-guide/ts/src/01-01/app/app.component.css b/public/docs/_examples/style-guide/ts/src/01-01/app/app.component.css
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/public/docs/_examples/style-guide/ts/src/01-01/app/app.component.ts b/public/docs/_examples/style-guide/ts/src/01-01/app/app.component.ts
new file mode 100644
index 0000000000..d5bb953540
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/01-01/app/app.component.ts
@@ -0,0 +1,14 @@
+// #docregion
+import { Component } from '@angular/core';
+
+import { HeroService } from './heroes';
+
+@Component({
+ selector: 'toh-app',
+ template: `
+
+ `,
+ styleUrls: ['./app.component.css'],
+ providers: [ HeroService ]
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/style-guide/ts/src/01-01/app/app.module.ts b/public/docs/_examples/style-guide/ts/src/01-01/app/app.module.ts
new file mode 100644
index 0000000000..53f29ea8cb
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/01-01/app/app.module.ts
@@ -0,0 +1,27 @@
+// #docplaster
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { RouterModule } from '@angular/router';
+
+import { AppComponent } from './app.component';
+import { HeroesComponent } from './heroes/heroes.component';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ // #enddocregion
+ RouterModule.forChild([{ path: '01-01', component: AppComponent }])
+ // #docregion
+ ],
+ declarations: [
+ AppComponent,
+ HeroesComponent
+ ],
+ exports: [ AppComponent ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
+// #enddocregion
+
+
diff --git a/public/docs/_examples/style-guide/ts/src/01-01/app/heroes/hero.component.avoid.ts b/public/docs/_examples/style-guide/ts/src/01-01/app/heroes/hero.component.avoid.ts
new file mode 100644
index 0000000000..853e6ab64e
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/01-01/app/heroes/hero.component.avoid.ts
@@ -0,0 +1,49 @@
+// #docregion
+/* avoid */
+
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { BrowserModule } from '@angular/platform-browser';
+import { NgModule, Component, OnInit } from '@angular/core';
+
+class Hero {
+ id: number;
+ name: string;
+}
+
+@Component({
+ selector: 'my-app',
+ template: `
+ {{title}}
+ {{heroes | json}}
+ `,
+ styleUrls: ['app/app.component.css']
+})
+class AppComponent implements OnInit {
+ title = 'Tour of Heroes';
+
+ heroes: Hero[] = [];
+
+ ngOnInit() {
+ getHeroes().then(heroes => this.heroes = heroes);
+ }
+}
+
+@NgModule({
+ imports: [ BrowserModule ],
+ declarations: [ AppComponent ],
+ exports: [ AppComponent ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
+
+platformBrowserDynamic().bootstrapModule(AppModule);
+
+const HEROES: Hero[] = [
+ {id: 1, name: 'Bombasto'},
+ {id: 2, name: 'Tornado'},
+ {id: 3, name: 'Magneta'},
+];
+
+function getHeroes(): Promise {
+ return Promise.resolve(HEROES); // TODO: get hero data from the server;
+}
diff --git a/public/docs/_examples/style-guide/ts/src/01-01/app/heroes/heroes.component.ts b/public/docs/_examples/style-guide/ts/src/01-01/app/heroes/heroes.component.ts
new file mode 100644
index 0000000000..9e3546db90
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/01-01/app/heroes/heroes.component.ts
@@ -0,0 +1,21 @@
+// #docregion
+import { Component, OnInit } from '@angular/core';
+
+import { Hero, HeroService } from './shared';
+
+@Component({
+ selector: 'toh-heroes',
+ template: `
+ {{heroes | json}}
+ `
+})
+export class HeroesComponent implements OnInit {
+ heroes: Hero[] = [];
+
+ constructor(private heroService: HeroService) {}
+
+ ngOnInit() {
+ this.heroService.getHeroes()
+ .then(heroes => this.heroes = heroes);
+ }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/01-01/app/heroes/index.ts b/public/docs/_examples/style-guide/ts/src/01-01/app/heroes/index.ts
new file mode 100644
index 0000000000..a8d7f1d422
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/01-01/app/heroes/index.ts
@@ -0,0 +1,2 @@
+export * from './shared';
+export * from './heroes.component';
diff --git a/public/docs/_examples/style-guide/ts/src/01-01/app/heroes/shared/hero.model.ts b/public/docs/_examples/style-guide/ts/src/01-01/app/heroes/shared/hero.model.ts
new file mode 100644
index 0000000000..8f7cc205c8
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/01-01/app/heroes/shared/hero.model.ts
@@ -0,0 +1,5 @@
+// #docregion
+export class Hero {
+ id: number;
+ name: string;
+}
diff --git a/public/docs/_examples/style-guide/ts/src/01-01/app/heroes/shared/hero.service.ts b/public/docs/_examples/style-guide/ts/src/01-01/app/heroes/shared/hero.service.ts
new file mode 100644
index 0000000000..d94e5bacac
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/01-01/app/heroes/shared/hero.service.ts
@@ -0,0 +1,11 @@
+// #docregion
+import { Injectable } from '@angular/core';
+
+import { HEROES } from './mock-heroes';
+
+@Injectable()
+export class HeroService {
+ getHeroes() {
+ return Promise.resolve(HEROES);
+ }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/01-01/app/heroes/shared/index.ts b/public/docs/_examples/style-guide/ts/src/01-01/app/heroes/shared/index.ts
new file mode 100644
index 0000000000..c0c1a87eb2
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/01-01/app/heroes/shared/index.ts
@@ -0,0 +1,3 @@
+export * from './hero.model';
+export * from './hero.service';
+export * from './mock-heroes';
diff --git a/public/docs/_examples/style-guide/ts/src/01-01/app/heroes/shared/mock-heroes.ts b/public/docs/_examples/style-guide/ts/src/01-01/app/heroes/shared/mock-heroes.ts
new file mode 100644
index 0000000000..2e9a69f59d
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/01-01/app/heroes/shared/mock-heroes.ts
@@ -0,0 +1,8 @@
+// #docregion
+import { Hero } from './hero.model';
+
+export const HEROES: Hero[] = [
+ {id: 1, name: 'Bombasto'},
+ {id: 2, name: 'Tornado'},
+ {id: 3, name: 'Magneta'},
+];
diff --git a/public/docs/_examples/style-guide/ts/src/01-01/app/index.ts b/public/docs/_examples/style-guide/ts/src/01-01/app/index.ts
new file mode 100644
index 0000000000..fe8300f1dd
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/01-01/app/index.ts
@@ -0,0 +1,2 @@
+export * from './heroes';
+export * from './app.component';
diff --git a/public/docs/_examples/style-guide/ts/src/01-01/main.ts b/public/docs/_examples/style-guide/ts/src/01-01/main.ts
new file mode 100644
index 0000000000..7e8269bd65
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/01-01/main.ts
@@ -0,0 +1,6 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/style-guide/ts/src/02-05/app/app.component.ts b/public/docs/_examples/style-guide/ts/src/02-05/app/app.component.ts
new file mode 100644
index 0000000000..66ebfa954e
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/02-05/app/app.component.ts
@@ -0,0 +1,10 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'toh-app',
+ template: `
+ Tour of Heroes
+ `
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/style-guide/ts/src/02-05/app/app.module.ts b/public/docs/_examples/style-guide/ts/src/02-05/app/app.module.ts
new file mode 100644
index 0000000000..306ec125e0
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/02-05/app/app.module.ts
@@ -0,0 +1,23 @@
+// #docplaster
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { RouterModule } from '@angular/router';
+
+import { AppComponent } from './app.component';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ // #enddocregion
+ RouterModule.forChild([{ path: '02-05', component: AppComponent }])
+ // #docregion
+ ],
+ declarations: [
+ AppComponent
+ ],
+ exports: [ AppComponent ],
+ bootstrap: [ AppComponent ]
+})
+export class AppModule { }
+// #enddocregion
diff --git a/public/docs/_examples/style-guide/ts/src/02-05/main.ts b/public/docs/_examples/style-guide/ts/src/02-05/main.ts
new file mode 100644
index 0000000000..6c32161f84
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/02-05/main.ts
@@ -0,0 +1,8 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app/app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule)
+ .then(success => console.log(`Bootstrap success`))
+ .catch(err => console.error(err));
diff --git a/public/docs/_examples/style-guide/ts/src/02-07/app/app.component.ts b/public/docs/_examples/style-guide/ts/src/02-07/app/app.component.ts
new file mode 100644
index 0000000000..c82e12624d
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/02-07/app/app.component.ts
@@ -0,0 +1,10 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'sg-app',
+ template: `
+
+
+ `
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/style-guide/ts/src/02-07/app/app.module.ts b/public/docs/_examples/style-guide/ts/src/02-07/app/app.module.ts
new file mode 100644
index 0000000000..4320fe67d5
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/02-07/app/app.module.ts
@@ -0,0 +1,19 @@
+import { NgModule } from '@angular/core';
+import { RouterModule } from '@angular/router';
+
+import { AppComponent } from './app.component';
+import { HeroComponent } from './heroes';
+import { UsersComponent } from './users';
+
+@NgModule({
+ imports: [
+ RouterModule.forChild([{ path: '02-07', component: AppComponent }])
+ ],
+ declarations: [
+ AppComponent,
+ HeroComponent,
+ UsersComponent
+ ],
+ exports: [ AppComponent ]
+})
+export class AppModule {}
diff --git a/public/docs/_examples/style-guide/ts/src/02-07/app/heroes/hero.component.avoid.ts b/public/docs/_examples/style-guide/ts/src/02-07/app/heroes/hero.component.avoid.ts
new file mode 100644
index 0000000000..976fcb6cdf
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/02-07/app/heroes/hero.component.avoid.ts
@@ -0,0 +1,11 @@
+// #docregion
+import { Component } from '@angular/core';
+// #docregion example
+/* avoid */
+
+// HeroComponent is in the Tour of Heroes feature
+@Component({
+ selector: 'hero'
+})
+export class HeroComponent {}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/02-07/app/heroes/hero.component.ts b/public/docs/_examples/style-guide/ts/src/02-07/app/heroes/hero.component.ts
new file mode 100644
index 0000000000..44c04dd855
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/02-07/app/heroes/hero.component.ts
@@ -0,0 +1,13 @@
+// #docplaster
+// #docregion
+import { Component } from '@angular/core';
+
+// #docregion example
+@Component({
+ // #enddocregion example
+ template: 'hero component
',
+ // #docregion example
+ selector: 'toh-hero'
+})
+export class HeroComponent {}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/02-07/app/heroes/index.ts b/public/docs/_examples/style-guide/ts/src/02-07/app/heroes/index.ts
new file mode 100644
index 0000000000..084f36d703
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/02-07/app/heroes/index.ts
@@ -0,0 +1 @@
+export * from './hero.component';
diff --git a/public/docs/_examples/style-guide/ts/src/02-07/app/index.ts b/public/docs/_examples/style-guide/ts/src/02-07/app/index.ts
new file mode 100644
index 0000000000..fc87f976b3
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/02-07/app/index.ts
@@ -0,0 +1,3 @@
+export * from './heroes';
+export * from './users';
+export * from './app.component';
diff --git a/public/docs/_examples/style-guide/ts/src/02-07/app/users/index.ts b/public/docs/_examples/style-guide/ts/src/02-07/app/users/index.ts
new file mode 100644
index 0000000000..475ba6d2a7
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/02-07/app/users/index.ts
@@ -0,0 +1 @@
+export * from './users.component';
diff --git a/public/docs/_examples/style-guide/ts/src/02-07/app/users/users.component.avoid.ts b/public/docs/_examples/style-guide/ts/src/02-07/app/users/users.component.avoid.ts
new file mode 100644
index 0000000000..9a5bd936e9
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/02-07/app/users/users.component.avoid.ts
@@ -0,0 +1,11 @@
+// #docregion
+import { Component } from '@angular/core';
+// #docregion example
+/* avoid */
+
+// UsersComponent is in an Admin feature
+@Component({
+ selector: 'users'
+})
+export class UsersComponent {}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/02-07/app/users/users.component.ts b/public/docs/_examples/style-guide/ts/src/02-07/app/users/users.component.ts
new file mode 100644
index 0000000000..2fb6d54ebe
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/02-07/app/users/users.component.ts
@@ -0,0 +1,13 @@
+// #docplaster
+// #docregion
+import { Component } from '@angular/core';
+
+// #docregion example
+@Component({
+ // #enddocregion example
+ template: 'users component
',
+ // #docregion example
+ selector: 'admin-users'
+})
+export class UsersComponent {}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/02-08/app/app.component.ts b/public/docs/_examples/style-guide/ts/src/02-08/app/app.component.ts
new file mode 100644
index 0000000000..bf27aeaf8a
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/02-08/app/app.component.ts
@@ -0,0 +1,7 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'sg-app',
+ template: ' '
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/style-guide/ts/src/02-08/app/app.module.ts b/public/docs/_examples/style-guide/ts/src/02-08/app/app.module.ts
new file mode 100644
index 0000000000..e840cc50a5
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/02-08/app/app.module.ts
@@ -0,0 +1,19 @@
+import { NgModule } from '@angular/core';
+import { RouterModule } from '@angular/router';
+
+import { AppComponent } from './app.component';
+import { InputHighlightDirective,
+ ValidateDirective } from './shared';
+
+@NgModule({
+ imports: [
+ RouterModule.forChild([{ path: '02-08', component: AppComponent }])
+ ],
+ declarations: [
+ AppComponent,
+ InputHighlightDirective,
+ ValidateDirective
+ ],
+ exports: [ AppComponent ]
+})
+export class AppModule {}
diff --git a/public/docs/_examples/style-guide/ts/src/02-08/app/index.ts b/public/docs/_examples/style-guide/ts/src/02-08/app/index.ts
new file mode 100644
index 0000000000..ebe5c92f03
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/02-08/app/index.ts
@@ -0,0 +1,2 @@
+export * from './shared';
+export * from './app.component';
diff --git a/public/docs/_examples/style-guide/ts/src/02-08/app/shared/index.ts b/public/docs/_examples/style-guide/ts/src/02-08/app/shared/index.ts
new file mode 100644
index 0000000000..b844b75492
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/02-08/app/shared/index.ts
@@ -0,0 +1,2 @@
+export * from './input-highlight.directive';
+export * from './validate.directive';
diff --git a/public/docs/_examples/style-guide/ts/src/02-08/app/shared/input-highlight.directive.ts b/public/docs/_examples/style-guide/ts/src/02-08/app/shared/input-highlight.directive.ts
new file mode 100644
index 0000000000..fd74771981
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/02-08/app/shared/input-highlight.directive.ts
@@ -0,0 +1,10 @@
+// #docregion
+import { Directive, ElementRef } from '@angular/core';
+
+@Directive({ selector: 'input'})
+/** Highlight the attached input text element in blue */
+export class InputHighlightDirective {
+ constructor(el: ElementRef) {
+ el.nativeElement.style.backgroundColor = 'powderblue';
+ }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/02-08/app/shared/validate.directive.avoid.ts b/public/docs/_examples/style-guide/ts/src/02-08/app/shared/validate.directive.avoid.ts
new file mode 100644
index 0000000000..b038f37075
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/02-08/app/shared/validate.directive.avoid.ts
@@ -0,0 +1,10 @@
+// #docregion
+import { Directive } from '@angular/core';
+// #docregion example
+/* avoid */
+
+@Directive({
+ selector: '[validate]'
+})
+export class ValidateDirective {}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/02-08/app/shared/validate.directive.ts b/public/docs/_examples/style-guide/ts/src/02-08/app/shared/validate.directive.ts
new file mode 100644
index 0000000000..039afb846f
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/02-08/app/shared/validate.directive.ts
@@ -0,0 +1,9 @@
+// #docregion
+import { Directive } from '@angular/core';
+
+// #docregion example
+@Directive({
+ selector: '[tohValidate]'
+})
+export class ValidateDirective {}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/03-01/app/app.component.ts b/public/docs/_examples/style-guide/ts/src/03-01/app/app.component.ts
new file mode 100644
index 0000000000..cb9479d2d9
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-01/app/app.component.ts
@@ -0,0 +1,18 @@
+import { Component, OnInit } from '@angular/core';
+
+import { ExceptionService } from './core';
+
+@Component({
+ selector: 'sg-app',
+ template: 'The expected error is {{errorCode}}
',
+ providers: [ExceptionService]
+})
+export class AppComponent implements OnInit {
+ errorCode: number;
+
+ constructor(private exceptionService: ExceptionService) { }
+
+ ngOnInit() {
+ this.errorCode = this.exceptionService.getException();
+ }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/03-01/app/app.module.ts b/public/docs/_examples/style-guide/ts/src/03-01/app/app.module.ts
new file mode 100644
index 0000000000..48079f21c7
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-01/app/app.module.ts
@@ -0,0 +1,15 @@
+import { NgModule } from '@angular/core';
+import { RouterModule } from '@angular/router';
+
+import { AppComponent } from './app.component';
+
+@NgModule({
+ imports: [
+ RouterModule.forChild([{ path: '03-01', component: AppComponent }])
+ ],
+ declarations: [
+ AppComponent
+ ],
+ exports: [ AppComponent ]
+})
+export class AppModule {}
diff --git a/public/docs/_examples/style-guide/ts/src/03-01/app/core/exception.service.avoid.ts b/public/docs/_examples/style-guide/ts/src/03-01/app/core/exception.service.avoid.ts
new file mode 100644
index 0000000000..0a22811fe3
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-01/app/core/exception.service.avoid.ts
@@ -0,0 +1,11 @@
+// #docregion
+import { Injectable } from '@angular/core';
+
+@Injectable()
+// #docregion example
+/* avoid */
+
+export class exceptionService {
+ constructor() { }
+}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/03-01/app/core/exception.service.ts b/public/docs/_examples/style-guide/ts/src/03-01/app/core/exception.service.ts
new file mode 100644
index 0000000000..dd77b4f7dc
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-01/app/core/exception.service.ts
@@ -0,0 +1,14 @@
+// #docplaster
+// #docregion
+import { Injectable } from '@angular/core';
+
+@Injectable()
+// #docregion example
+export class ExceptionService {
+ constructor() { }
+ // #enddocregion example
+ // testing harness
+ getException() { return 42; }
+ // #docregion example
+}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/03-01/app/core/index.ts b/public/docs/_examples/style-guide/ts/src/03-01/app/core/index.ts
new file mode 100644
index 0000000000..8acaa4bcf9
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-01/app/core/index.ts
@@ -0,0 +1 @@
+export * from './exception.service';
diff --git a/public/docs/_examples/style-guide/ts/src/03-01/app/index.ts b/public/docs/_examples/style-guide/ts/src/03-01/app/index.ts
new file mode 100644
index 0000000000..e120e2dbfd
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-01/app/index.ts
@@ -0,0 +1,2 @@
+export * from './core';
+export * from './app.component';
diff --git a/public/docs/_examples/style-guide/ts/src/03-02/app/app.component.ts b/public/docs/_examples/style-guide/ts/src/03-02/app/app.component.ts
new file mode 100644
index 0000000000..132ea54c85
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-02/app/app.component.ts
@@ -0,0 +1,19 @@
+import { Component } from '@angular/core';
+
+import { heroesUrl, mockHeroes, VILLAINS_URL } from './core';
+
+@Component({
+ selector: 'sg-app',
+ template: `
+ Heroes url: {{heroesUrl}}
+ Villains url: {{villainsUrl}}
+
+ Mock Heroes
+ {{hero}}
+ `
+})
+export class AppComponent {
+ heroes = mockHeroes; // prefer
+ heroesUrl = heroesUrl; // prefer
+ villainsUrl = VILLAINS_URL; // tolerate
+}
diff --git a/public/docs/_examples/style-guide/ts/src/03-02/app/app.module.ts b/public/docs/_examples/style-guide/ts/src/03-02/app/app.module.ts
new file mode 100644
index 0000000000..2db4012ebf
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-02/app/app.module.ts
@@ -0,0 +1,17 @@
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { RouterModule } from '@angular/router';
+
+import { AppComponent } from './app.component';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ RouterModule.forChild([{ path: '03-02', component: AppComponent }])
+ ],
+ declarations: [
+ AppComponent
+ ],
+ exports: [ AppComponent ]
+})
+export class AppModule {}
diff --git a/public/docs/_examples/style-guide/ts/src/03-02/app/core/data.service.ts b/public/docs/_examples/style-guide/ts/src/03-02/app/core/data.service.ts
new file mode 100644
index 0000000000..5c26478c7b
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-02/app/core/data.service.ts
@@ -0,0 +1,4 @@
+// #docregion
+export const mockHeroes = ['Sam', 'Jill']; // prefer
+export const heroesUrl = 'api/heroes'; // prefer
+export const VILLAINS_URL = 'api/villains'; // tolerate
diff --git a/public/docs/_examples/style-guide/ts/src/03-02/app/core/index.ts b/public/docs/_examples/style-guide/ts/src/03-02/app/core/index.ts
new file mode 100644
index 0000000000..2ba773ede8
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-02/app/core/index.ts
@@ -0,0 +1 @@
+export * from './data.service';
diff --git a/public/docs/_examples/style-guide/ts/src/03-02/app/index.ts b/public/docs/_examples/style-guide/ts/src/03-02/app/index.ts
new file mode 100644
index 0000000000..e120e2dbfd
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-02/app/index.ts
@@ -0,0 +1,2 @@
+export * from './core';
+export * from './app.component';
diff --git a/public/docs/_examples/style-guide/ts/src/03-03/app/app.component.ts b/public/docs/_examples/style-guide/ts/src/03-03/app/app.component.ts
new file mode 100644
index 0000000000..3ca522bc45
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-03/app/app.component.ts
@@ -0,0 +1,18 @@
+import { Component, OnInit } from '@angular/core';
+
+import { Hero, HeroCollectorService } from './core';
+
+@Component({
+ selector: 'sg-app',
+ template: 'Our hero is {{hero.name}} and {{hero.power}}
',
+ providers: [HeroCollectorService]
+})
+export class AppComponent implements OnInit {
+ hero: Hero;
+
+ constructor(private heroCollectorService: HeroCollectorService) { }
+
+ ngOnInit() {
+ this.hero = this.heroCollectorService.getHero();
+ }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/03-03/app/app.module.ts b/public/docs/_examples/style-guide/ts/src/03-03/app/app.module.ts
new file mode 100644
index 0000000000..29b3d2e765
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-03/app/app.module.ts
@@ -0,0 +1,15 @@
+import { NgModule } from '@angular/core';
+import { RouterModule } from '@angular/router';
+
+import { AppComponent } from './app.component';
+
+@NgModule({
+ imports: [
+ RouterModule.forChild([{ path: '03-03', component: AppComponent }])
+ ],
+ declarations: [
+ AppComponent
+ ],
+ exports: [ AppComponent ]
+})
+export class AppModule {}
diff --git a/public/docs/_examples/style-guide/ts/src/03-03/app/core/hero-collector.service.avoid.ts b/public/docs/_examples/style-guide/ts/src/03-03/app/core/hero-collector.service.avoid.ts
new file mode 100644
index 0000000000..f481af18b6
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-03/app/core/hero-collector.service.avoid.ts
@@ -0,0 +1,15 @@
+// #docregion
+// #docregion example
+/* avoid */
+
+import { Injectable } from '@angular/core';
+
+import { IHero } from './hero.model.avoid';
+
+@Injectable()
+export class HeroCollectorService {
+ hero: IHero;
+
+ constructor() { }
+}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/03-03/app/core/hero-collector.service.ts b/public/docs/_examples/style-guide/ts/src/03-03/app/core/hero-collector.service.ts
new file mode 100644
index 0000000000..1df5c0deb0
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-03/app/core/hero-collector.service.ts
@@ -0,0 +1,25 @@
+// #docplaster
+// #docregion
+// #docregion example
+import { Injectable } from '@angular/core';
+
+import { Hero } from './hero.model';
+
+@Injectable()
+export class HeroCollectorService {
+ hero: Hero;
+
+ constructor() { }
+ // #enddocregion example
+ // testing harness
+ getHero() {
+ this.hero = {
+ name: 'RubberMan',
+ power: 'He is so elastic'
+ };
+
+ return this.hero;
+ }
+ // #docregion example
+}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/03-03/app/core/hero.model.avoid.ts b/public/docs/_examples/style-guide/ts/src/03-03/app/core/hero.model.avoid.ts
new file mode 100644
index 0000000000..ce93b2c59a
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-03/app/core/hero.model.avoid.ts
@@ -0,0 +1,14 @@
+// #docregion
+// #docregion example
+/* avoid */
+
+export interface IHero {
+ name: string;
+ power: string;
+}
+
+export class Hero implements IHero {
+ name: string;
+ power: string;
+}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/03-03/app/core/hero.model.ts b/public/docs/_examples/style-guide/ts/src/03-03/app/core/hero.model.ts
new file mode 100644
index 0000000000..c3277621cb
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-03/app/core/hero.model.ts
@@ -0,0 +1,7 @@
+// #docregion
+// #docregion example
+export class Hero {
+ name: string;
+ power: string;
+}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/03-03/app/core/index.ts b/public/docs/_examples/style-guide/ts/src/03-03/app/core/index.ts
new file mode 100644
index 0000000000..17ad67b0b1
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-03/app/core/index.ts
@@ -0,0 +1,2 @@
+export * from './hero-collector.service';
+export * from './hero.model';
diff --git a/public/docs/_examples/style-guide/ts/src/03-03/app/index.ts b/public/docs/_examples/style-guide/ts/src/03-03/app/index.ts
new file mode 100644
index 0000000000..e120e2dbfd
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-03/app/index.ts
@@ -0,0 +1,2 @@
+export * from './core';
+export * from './app.component';
diff --git a/public/docs/_examples/style-guide/ts/src/03-04/app/app.component.ts b/public/docs/_examples/style-guide/ts/src/03-04/app/app.component.ts
new file mode 100644
index 0000000000..555c9e9441
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-04/app/app.component.ts
@@ -0,0 +1,27 @@
+import { Component, OnInit } from '@angular/core';
+
+import { ToastService } from './core';
+
+@Component({
+ selector: 'sg-app',
+ template: `
+ Show toast
+ Hide toast
+ `,
+ providers: [ToastService]
+})
+export class AppComponent implements OnInit {
+ constructor(private toastService: ToastService) { }
+
+ hide() {
+ this.toastService.hide();
+ }
+
+ show() {
+ this.toastService.show();
+ }
+
+ ngOnInit() {
+ this.toastService.activate('Hello style-guide!');
+ }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/03-04/app/app.module.ts b/public/docs/_examples/style-guide/ts/src/03-04/app/app.module.ts
new file mode 100644
index 0000000000..a5a8d5bb4e
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-04/app/app.module.ts
@@ -0,0 +1,17 @@
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { RouterModule } from '@angular/router';
+
+import { AppComponent } from './app.component';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ RouterModule.forChild([{ path: '03-04', component: AppComponent }])
+ ],
+ declarations: [
+ AppComponent
+ ],
+ exports: [ AppComponent ]
+})
+export class AppModule {}
diff --git a/public/docs/_examples/style-guide/ts/src/03-04/app/core/index.ts b/public/docs/_examples/style-guide/ts/src/03-04/app/core/index.ts
new file mode 100644
index 0000000000..e78b628f9c
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-04/app/core/index.ts
@@ -0,0 +1 @@
+export * from './toast.service';
diff --git a/public/docs/_examples/style-guide/ts/src/03-04/app/core/toast.service.avoid.ts b/public/docs/_examples/style-guide/ts/src/03-04/app/core/toast.service.avoid.ts
new file mode 100644
index 0000000000..0f3a7c25ea
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-04/app/core/toast.service.avoid.ts
@@ -0,0 +1,27 @@
+// #docregion
+// #docregion example
+/* avoid */
+
+import { Injectable } from '@angular/core';
+
+@Injectable()
+export class ToastService {
+ message: string;
+
+ private _toastCount: number;
+
+ hide() {
+ this._toastCount--;
+ this._log();
+ }
+
+ show() {
+ this._toastCount++;
+ this._log();
+ }
+
+ private _log() {
+ console.log(this.message);
+ }
+}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/03-04/app/core/toast.service.ts b/public/docs/_examples/style-guide/ts/src/03-04/app/core/toast.service.ts
new file mode 100644
index 0000000000..ab148a1732
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-04/app/core/toast.service.ts
@@ -0,0 +1,32 @@
+// #docplaster
+// #docregion
+// #docregion example
+import { Injectable } from '@angular/core';
+
+@Injectable()
+export class ToastService {
+ message: string;
+
+ private toastCount: number;
+
+ hide() {
+ this.toastCount--;
+ this.log();
+ }
+
+ show() {
+ this.toastCount++;
+ this.log();
+ }
+
+ private log() {
+ console.log(this.message);
+ }
+ // #enddocregion example
+ // testing harness
+ activate(message: string) {
+ this.message = message;
+ }
+ // #docregion example
+}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/03-04/app/index.ts b/public/docs/_examples/style-guide/ts/src/03-04/app/index.ts
new file mode 100644
index 0000000000..e120e2dbfd
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-04/app/index.ts
@@ -0,0 +1,2 @@
+export * from './core';
+export * from './app.component';
diff --git a/public/docs/_examples/style-guide/ts/src/03-06/app/app.component.html b/public/docs/_examples/style-guide/ts/src/03-06/app/app.component.html
new file mode 100644
index 0000000000..67fb0d5964
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-06/app/app.component.html
@@ -0,0 +1,6 @@
+Actual favorite: {{favorite?.name}}
+
diff --git a/public/docs/_examples/style-guide/ts/src/03-06/app/app.component.ts b/public/docs/_examples/style-guide/ts/src/03-06/app/app.component.ts
new file mode 100644
index 0000000000..8ec308bc6a
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-06/app/app.component.ts
@@ -0,0 +1,21 @@
+import { Component, OnInit } from '@angular/core';
+
+import { Hero, HeroService } from './heroes';
+import { ExceptionService, SpinnerService, ToastService } from './core';
+
+@Component({
+ selector: 'sg-app',
+ templateUrl: './app.component.html',
+ providers: [HeroService, ExceptionService, SpinnerService, ToastService]
+})
+export class AppComponent implements OnInit {
+ favorite: Hero;
+ heroes: Hero[];
+
+ constructor(private heroService: HeroService) { }
+
+ ngOnInit() {
+ this.heroService.getHero(1).subscribe(hero => this.favorite = hero);
+ this.heroService.getHeroes().subscribe(heroes => this.heroes = heroes);
+ }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/03-06/app/app.module.ts b/public/docs/_examples/style-guide/ts/src/03-06/app/app.module.ts
new file mode 100644
index 0000000000..f259ce23a2
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-06/app/app.module.ts
@@ -0,0 +1,17 @@
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { RouterModule } from '@angular/router';
+
+import { AppComponent } from './app.component';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ RouterModule.forChild([{ path: '03-06', component: AppComponent }])
+ ],
+ declarations: [
+ AppComponent
+ ],
+ exports: [ AppComponent ]
+})
+export class AppModule {}
diff --git a/public/docs/_examples/style-guide/ts/src/03-06/app/core/exception.service.ts b/public/docs/_examples/style-guide/ts/src/03-06/app/core/exception.service.ts
new file mode 100644
index 0000000000..7180c88e6b
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-06/app/core/exception.service.ts
@@ -0,0 +1,4 @@
+import { Injectable } from '@angular/core';
+
+@Injectable()
+export class ExceptionService { }
diff --git a/public/docs/_examples/style-guide/ts/src/03-06/app/core/index.ts b/public/docs/_examples/style-guide/ts/src/03-06/app/core/index.ts
new file mode 100644
index 0000000000..e4e6723f91
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-06/app/core/index.ts
@@ -0,0 +1,6 @@
+// #docregion
+// #docregion example
+export * from './exception.service';
+export * from './spinner';
+export * from './toast';
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/03-06/app/core/spinner/index.ts b/public/docs/_examples/style-guide/ts/src/03-06/app/core/spinner/index.ts
new file mode 100644
index 0000000000..1d619300c0
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-06/app/core/spinner/index.ts
@@ -0,0 +1,3 @@
+// #docregion
+export * from './spinner.component';
+export * from './spinner.service';
diff --git a/public/docs/_examples/style-guide/ts/src/03-06/app/core/spinner/spinner.component.ts b/public/docs/_examples/style-guide/ts/src/03-06/app/core/spinner/spinner.component.ts
new file mode 100644
index 0000000000..1fd2a01500
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-06/app/core/spinner/spinner.component.ts
@@ -0,0 +1,16 @@
+import { Component, OnDestroy, OnInit } from '@angular/core';
+
+import { SpinnerService } from './spinner.service';
+
+@Component({
+ selector: 'toh-spinner',
+ template: 'spinner
'
+})
+
+export class SpinnerComponent implements OnDestroy, OnInit {
+ constructor(private spinnerService: SpinnerService) { }
+
+ ngOnInit() { }
+
+ ngOnDestroy() { }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/03-06/app/core/spinner/spinner.service.ts b/public/docs/_examples/style-guide/ts/src/03-06/app/core/spinner/spinner.service.ts
new file mode 100644
index 0000000000..ad5d2ed6e0
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-06/app/core/spinner/spinner.service.ts
@@ -0,0 +1,12 @@
+import { Injectable } from '@angular/core';
+
+export interface ISpinnerState { }
+
+@Injectable()
+export class SpinnerService {
+ spinnerState: any;
+
+ show() { }
+
+ hide() { }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/03-06/app/core/toast/index.ts b/public/docs/_examples/style-guide/ts/src/03-06/app/core/toast/index.ts
new file mode 100644
index 0000000000..01b41aff98
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-06/app/core/toast/index.ts
@@ -0,0 +1,3 @@
+// #docregion
+export * from './toast.component';
+export * from './toast.service';
diff --git a/public/docs/_examples/style-guide/ts/src/03-06/app/core/toast/toast.component.ts b/public/docs/_examples/style-guide/ts/src/03-06/app/core/toast/toast.component.ts
new file mode 100644
index 0000000000..dd0bba5eba
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-06/app/core/toast/toast.component.ts
@@ -0,0 +1,13 @@
+import { Component, OnInit } from '@angular/core';
+
+import { ToastService } from './toast.service';
+
+@Component({
+ selector: 'toh-toast',
+ template: 'toast
'
+})
+export class ToastComponent implements OnInit {
+ constructor(toastService: ToastService) { }
+
+ ngOnInit() { }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/03-06/app/core/toast/toast.service.ts b/public/docs/_examples/style-guide/ts/src/03-06/app/core/toast/toast.service.ts
new file mode 100644
index 0000000000..e92e75ee45
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-06/app/core/toast/toast.service.ts
@@ -0,0 +1,6 @@
+import { Injectable } from '@angular/core';
+
+@Injectable()
+export class ToastService {
+ activate: (message?: string, title?: string) => void;
+}
diff --git a/public/docs/_examples/style-guide/ts/src/03-06/app/heroes/index.ts b/public/docs/_examples/style-guide/ts/src/03-06/app/heroes/index.ts
new file mode 100644
index 0000000000..c3da79f741
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-06/app/heroes/index.ts
@@ -0,0 +1 @@
+export * from './shared';
diff --git a/public/docs/_examples/style-guide/ts/src/03-06/app/heroes/shared/hero.model.ts b/public/docs/_examples/style-guide/ts/src/03-06/app/heroes/shared/hero.model.ts
new file mode 100644
index 0000000000..c3277621cb
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-06/app/heroes/shared/hero.model.ts
@@ -0,0 +1,7 @@
+// #docregion
+// #docregion example
+export class Hero {
+ name: string;
+ power: string;
+}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/03-06/app/heroes/shared/hero.service.avoid.ts b/public/docs/_examples/style-guide/ts/src/03-06/app/heroes/shared/hero.service.avoid.ts
new file mode 100644
index 0000000000..8287c567a7
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-06/app/heroes/shared/hero.service.avoid.ts
@@ -0,0 +1,32 @@
+// #docregion
+// #docregion example
+/* avoid */
+
+import { ExceptionService, SpinnerService, ToastService } from '../../core';
+import { Http } from '@angular/http';
+import { Injectable } from '@angular/core';
+import { Hero } from './hero.model';
+// #enddocregion example
+
+@Injectable()
+export class HeroService {
+
+ constructor(
+ private exceptionService: ExceptionService,
+ private spinnerService: SpinnerService,
+ private toastService: ToastService,
+ private http: Http
+ ) { }
+
+ getHero(id: number) {
+ return this.http.get(`api/heroes/${id}`)
+ .map(response => response.json().data as Hero);
+ }
+
+ getHeroes() {
+ return this.http.get(`api/heroes`)
+ .map(response => response.json().data as Hero[]);
+ }
+
+}
+
diff --git a/public/docs/_examples/style-guide/ts/src/03-06/app/heroes/shared/hero.service.ts b/public/docs/_examples/style-guide/ts/src/03-06/app/heroes/shared/hero.service.ts
new file mode 100644
index 0000000000..5792cd1ab2
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-06/app/heroes/shared/hero.service.ts
@@ -0,0 +1,32 @@
+// #docregion
+// #docregion example
+import { Injectable } from '@angular/core';
+import { Http } from '@angular/http';
+
+import { Hero } from './hero.model';
+import { ExceptionService, SpinnerService, ToastService } from '../../core';
+// #enddocregion example
+
+@Injectable()
+export class HeroService {
+ cachedHeroes: Hero[];
+
+ constructor(
+ private exceptionService: ExceptionService,
+ private spinnerService: SpinnerService,
+ private toastService: ToastService,
+ private http: Http
+ ) { }
+
+ getHero(id: number) {
+ return this.http.get(`api/heroes/${id}`)
+ .map(response => response.json().data as Hero);
+ }
+
+ getHeroes() {
+ return this.http.get(`api/heroes`)
+ .map(response => response.json().data as Hero[]);
+ }
+
+}
+
diff --git a/public/docs/_examples/style-guide/ts/src/03-06/app/heroes/shared/index.ts b/public/docs/_examples/style-guide/ts/src/03-06/app/heroes/shared/index.ts
new file mode 100644
index 0000000000..dbb150d3f8
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-06/app/heroes/shared/index.ts
@@ -0,0 +1,2 @@
+export * from './hero.model';
+export * from './hero.service';
diff --git a/public/docs/_examples/style-guide/ts/src/03-06/app/index.ts b/public/docs/_examples/style-guide/ts/src/03-06/app/index.ts
new file mode 100644
index 0000000000..cf861e261a
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-06/app/index.ts
@@ -0,0 +1,3 @@
+export * from './heroes';
+export * from './core';
+export * from './app.component';
diff --git a/public/docs/_examples/style-guide/ts/src/03-06/app/shared/toast/toast.component.ts b/public/docs/_examples/style-guide/ts/src/03-06/app/shared/toast/toast.component.ts
new file mode 100644
index 0000000000..e1c1ae6665
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/03-06/app/shared/toast/toast.component.ts
@@ -0,0 +1,13 @@
+import { Component, OnInit } from '@angular/core';
+
+import { ToastService } from '../../core';
+
+@Component({
+ selector: 'toh-toast',
+ template: 'toast
'
+})
+export class ToastComponent implements OnInit {
+ constructor(toastService: ToastService) { }
+
+ ngOnInit() { }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/04-08/app/app.component.ts b/public/docs/_examples/style-guide/ts/src/04-08/app/app.component.ts
new file mode 100644
index 0000000000..fdd8e6ef56
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-08/app/app.component.ts
@@ -0,0 +1,8 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'sg-app',
+ template: ' '
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/style-guide/ts/src/04-08/app/app.module.ts b/public/docs/_examples/style-guide/ts/src/04-08/app/app.module.ts
new file mode 100644
index 0000000000..25568b7fb4
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-08/app/app.module.ts
@@ -0,0 +1,28 @@
+// #docplaster
+// #docregion
+// #docregion example
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+// #enddocregion example
+import { RouterModule } from '@angular/router';
+// #docregion example
+
+import { AppComponent } from './app.component';
+import { HeroesComponent } from './heroes/heroes.component';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+// #enddocregion example
+ RouterModule.forChild([{ path: '04-08', component: AppComponent }])
+// #docregion example
+ ],
+ declarations: [
+ AppComponent,
+ HeroesComponent
+ ],
+ exports: [ AppComponent ],
+ entryComponents: [ AppComponent ]
+})
+export class AppModule {}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/04-08/app/heroes/heroes.component.html b/public/docs/_examples/style-guide/ts/src/04-08/app/heroes/heroes.component.html
new file mode 100644
index 0000000000..1244e68a4a
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-08/app/heroes/heroes.component.html
@@ -0,0 +1 @@
+This is heroes component
diff --git a/public/docs/_examples/style-guide/ts/src/04-08/app/heroes/heroes.component.ts b/public/docs/_examples/style-guide/ts/src/04-08/app/heroes/heroes.component.ts
new file mode 100644
index 0000000000..e2df4c91fd
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-08/app/heroes/heroes.component.ts
@@ -0,0 +1,11 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'toh-heroes',
+ templateUrl: './heroes.component.html'
+})
+export class HeroesComponent implements OnInit {
+ constructor() { /* ... */ }
+
+ ngOnInit() { /* ... */ }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/04-10/app/app.component.ts b/public/docs/_examples/style-guide/ts/src/04-10/app/app.component.ts
new file mode 100644
index 0000000000..fdd8e6ef56
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-10/app/app.component.ts
@@ -0,0 +1,8 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'sg-app',
+ template: ' '
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/style-guide/ts/src/04-10/app/app.module.ts b/public/docs/_examples/style-guide/ts/src/04-10/app/app.module.ts
new file mode 100644
index 0000000000..78106657ad
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-10/app/app.module.ts
@@ -0,0 +1,30 @@
+// #docplaster
+// #docregion
+// #docregion example
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+// #enddocregion example
+import { RouterModule } from '@angular/router';
+// #docregion example
+
+import { AppComponent } from './app.component';
+import { HeroesComponent } from './heroes/heroes.component';
+import { SharedModule } from './shared/shared.module';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ SharedModule,
+// #enddocregion example
+ RouterModule.forChild([{ path: '04-10', component: AppComponent }])
+// #docregion example
+ ],
+ declarations: [
+ AppComponent,
+ HeroesComponent
+ ],
+ exports: [ AppComponent ],
+ entryComponents: [ AppComponent ]
+})
+export class AppModule {}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/04-10/app/heroes/heroes.component.html b/public/docs/_examples/style-guide/ts/src/04-10/app/heroes/heroes.component.html
new file mode 100644
index 0000000000..170f76aee1
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-10/app/heroes/heroes.component.html
@@ -0,0 +1,8 @@
+
+This is heroes component
+
+
diff --git a/public/docs/_examples/style-guide/ts/src/04-10/app/heroes/heroes.component.ts b/public/docs/_examples/style-guide/ts/src/04-10/app/heroes/heroes.component.ts
new file mode 100644
index 0000000000..376567650e
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-10/app/heroes/heroes.component.ts
@@ -0,0 +1,27 @@
+// #docregion
+import { Component } from '@angular/core';
+
+import { FilterTextService } from '../shared/filter-text/filter-text.service';
+
+@Component({
+ selector: 'toh-heroes',
+ templateUrl: './heroes.component.html'
+})
+export class HeroesComponent {
+
+ heroes = [
+ { id: 1, name: 'Windstorm' },
+ { id: 2, name: 'Bombasto' },
+ { id: 3, name: 'Magneta' },
+ { id: 4, name: 'Tornado' }
+ ];
+
+ filteredHeroes = this.heroes;
+
+ constructor(private filterService: FilterTextService) { }
+
+ filterChanged(searchText: string) {
+ this.filteredHeroes = this.filterService.filter(searchText, ['id', 'name'], this.heroes);
+ }
+}
+
diff --git a/public/docs/_examples/style-guide/ts/src/04-10/app/shared/filter-text/filter-text.component.ts b/public/docs/_examples/style-guide/ts/src/04-10/app/shared/filter-text/filter-text.component.ts
new file mode 100644
index 0000000000..fffe4bf0b7
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-10/app/shared/filter-text/filter-text.component.ts
@@ -0,0 +1,26 @@
+// #docregion
+import { Component, EventEmitter, Output } from '@angular/core';
+
+@Component({
+ selector: 'toh-filter-text',
+ template: ' '
+})
+export class FilterTextComponent {
+ @Output() changed: EventEmitter;
+
+ filter: string;
+
+ constructor() {
+ this.changed = new EventEmitter();
+ }
+
+ clear() {
+ this.filter = '';
+ }
+
+ filterChanged(event: any) {
+ event.preventDefault();
+ console.log(`Filter Changed: ${this.filter}`);
+ this.changed.emit(this.filter);
+ }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/04-10/app/shared/filter-text/filter-text.service.ts b/public/docs/_examples/style-guide/ts/src/04-10/app/shared/filter-text/filter-text.service.ts
new file mode 100644
index 0000000000..87978e10e5
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-10/app/shared/filter-text/filter-text.service.ts
@@ -0,0 +1,30 @@
+// #docregion
+import { Injectable } from '@angular/core';
+
+@Injectable()
+export class FilterTextService {
+ constructor() {
+ console.log('Created an instance of FilterTextService');
+ }
+
+ filter(data: string, props: Array, originalList: Array) {
+ let filteredList: any[];
+ if (data && props && originalList) {
+ data = data.toLowerCase();
+ let filtered = originalList.filter(item => {
+ let match = false;
+ for (let prop of props) {
+ if (item[prop].toString().toLowerCase().indexOf(data) > -1) {
+ match = true;
+ break;
+ }
+ };
+ return match;
+ });
+ filteredList = filtered;
+ } else {
+ filteredList = originalList;
+ }
+ return filteredList;
+ }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/04-10/app/shared/init-caps.pipe.ts b/public/docs/_examples/style-guide/ts/src/04-10/app/shared/init-caps.pipe.ts
new file mode 100644
index 0000000000..5019bcb234
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-10/app/shared/init-caps.pipe.ts
@@ -0,0 +1,7 @@
+// #docregion
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({ name: 'initCaps' })
+export class InitCapsPipe implements PipeTransform {
+ transform = (value: string) => value;
+}
diff --git a/public/docs/_examples/style-guide/ts/src/04-10/app/shared/shared.module.ts b/public/docs/_examples/style-guide/ts/src/04-10/app/shared/shared.module.ts
new file mode 100644
index 0000000000..6160abcc84
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-10/app/shared/shared.module.ts
@@ -0,0 +1,24 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+
+import { FilterTextComponent } from './filter-text/filter-text.component';
+import { FilterTextService } from './filter-text/filter-text.service';
+import { InitCapsPipe } from './init-caps.pipe';
+
+@NgModule({
+ imports: [CommonModule, FormsModule],
+ declarations: [
+ FilterTextComponent,
+ InitCapsPipe
+ ],
+ providers: [FilterTextService],
+ exports: [
+ CommonModule,
+ FormsModule,
+ FilterTextComponent,
+ InitCapsPipe
+ ]
+})
+export class SharedModule { }
diff --git a/public/docs/_examples/style-guide/ts/src/04-11/app/app.component.ts b/public/docs/_examples/style-guide/ts/src/04-11/app/app.component.ts
new file mode 100644
index 0000000000..693619a982
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-11/app/app.component.ts
@@ -0,0 +1,12 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'toh-app',
+ template: `
+
+
+
+ `
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/style-guide/ts/src/04-11/app/app.module.ts b/public/docs/_examples/style-guide/ts/src/04-11/app/app.module.ts
new file mode 100644
index 0000000000..ef3c156bcf
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-11/app/app.module.ts
@@ -0,0 +1,30 @@
+// #docplaster
+// #docregion
+// #docregion example
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+// #enddocregion example
+import { RouterModule } from '@angular/router';
+// #docregion example
+
+import { AppComponent } from './app.component';
+import { HeroesComponent } from './heroes/heroes.component';
+import { CoreModule } from './core/core.module';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ CoreModule,
+// #enddocregion example
+ RouterModule.forChild([{ path: '04-11', component: AppComponent }])
+// #docregion example
+ ],
+ declarations: [
+ AppComponent,
+ HeroesComponent
+ ],
+ exports: [ AppComponent ],
+ entryComponents: [ AppComponent ]
+})
+export class AppModule {}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/04-11/app/core/core.module.ts b/public/docs/_examples/style-guide/ts/src/04-11/app/core/core.module.ts
new file mode 100644
index 0000000000..4ba5c79a14
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-11/app/core/core.module.ts
@@ -0,0 +1,19 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { LoggerService } from './logger.service';
+import { NavComponent } from './nav/nav.component';
+import { SpinnerComponent } from './spinner/spinner.component';
+import { SpinnerService } from './spinner/spinner.service';
+
+@NgModule({
+ imports: [
+ CommonModule // we use ngFor
+ ],
+ exports: [NavComponent, SpinnerComponent],
+ declarations: [NavComponent, SpinnerComponent],
+ providers: [LoggerService, SpinnerService]
+})
+export class CoreModule { }
+
diff --git a/public/docs/_examples/style-guide/ts/src/04-11/app/core/index.ts b/public/docs/_examples/style-guide/ts/src/04-11/app/core/index.ts
new file mode 100644
index 0000000000..098f40c7d5
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-11/app/core/index.ts
@@ -0,0 +1,4 @@
+// #docregion
+export * from './logger.service';
+export * from './spinner/spinner.service';
+export * from './nav/nav.component';
diff --git a/public/docs/_examples/style-guide/ts/src/04-11/app/core/logger.service.ts b/public/docs/_examples/style-guide/ts/src/04-11/app/core/logger.service.ts
new file mode 100644
index 0000000000..9c7080f07a
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-11/app/core/logger.service.ts
@@ -0,0 +1,13 @@
+// #docregion
+import { Injectable } from '@angular/core';
+
+@Injectable()
+export class LoggerService {
+ log(msg: string) {
+ console.log(msg);
+ }
+
+ error(msg: string) {
+ console.error(msg);
+ }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/04-11/app/core/nav/nav.component.css b/public/docs/_examples/style-guide/ts/src/04-11/app/core/nav/nav.component.css
new file mode 100644
index 0000000000..c7903fd25c
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-11/app/core/nav/nav.component.css
@@ -0,0 +1,63 @@
+/*#docregion*/
+.mdl-layout__header {
+ display: flex;
+ position: fixed;
+ background-color: #222;
+}
+
+.nav-link {
+ padding: 0 1em;
+ width: 100px;
+ color: rgba(255,255,255,.6);
+ text-align: center;
+ text-decoration: none;
+}
+
+.nav-link.router-link-active {
+ color: rgba(255,255,255, 1);
+}
+
+.nav-link.router-link-active::after {
+ height: 3px;
+ width: 100%;
+ display: block;
+ content: " ";
+ bottom: 0;
+ left: 0;
+ position: inherit;
+ background: rgb(83,109,254);
+}
+
+.md-title-icon > i {
+ background-image: url("assets/ng.png");
+ background-repeat: no-repeat;
+ background-position: center center;
+ padding: 1em 2em;
+}
+
+.mdl-layout__header-row {
+ height: 56px;
+ padding: 0 16px 0 72px;
+ padding-left: 8px;
+ background-color: #673AB7;
+ background: #0033FF;
+ background-color: #222;
+}
+
+#reset-button {
+ position: fixed;
+ right: 2em;
+ top: 1em;
+}
+
+@media (max-width: 480px) {
+ #reset-button {
+ display: none
+ }
+}
+
+@media (max-width: 320px) {
+ a.nav-link {
+ font-size: 12px;
+ }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/04-11/app/core/nav/nav.component.html b/public/docs/_examples/style-guide/ts/src/04-11/app/core/nav/nav.component.html
new file mode 100644
index 0000000000..b3c7e441e0
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-11/app/core/nav/nav.component.html
@@ -0,0 +1,14 @@
+
+
+
+
Tour of Heroes
+
+
+
+
+
+
diff --git a/public/docs/_examples/style-guide/ts/src/04-11/app/core/nav/nav.component.ts b/public/docs/_examples/style-guide/ts/src/04-11/app/core/nav/nav.component.ts
new file mode 100644
index 0000000000..7e21016e2b
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-11/app/core/nav/nav.component.ts
@@ -0,0 +1,19 @@
+// #docregion
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'toh-nav',
+ templateUrl: './nav.component.html',
+ styleUrls: ['./nav.component.css'],
+})
+export class NavComponent implements OnInit {
+ menuItems = [
+ 'Heroes',
+ 'Villains',
+ 'Other'
+ ];
+
+ ngOnInit() { }
+
+ constructor() { }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/04-11/app/core/spinner/spinner.component.css b/public/docs/_examples/style-guide/ts/src/04-11/app/core/spinner/spinner.component.css
new file mode 100644
index 0000000000..afad0fe8e3
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-11/app/core/spinner/spinner.component.css
@@ -0,0 +1,21 @@
+/*#docregion*/
+.spinner {
+ position: absolute;
+ left: 7em;
+ top: 20em;
+ position: absolute;
+ background-color: blue;
+ height: .3em;
+ width: 6em;
+ margin:-60px 0 0 -60px;
+ -webkit-animation:spin 4s linear infinite;
+ -moz-animation:spin 4s linear infinite;
+ animation:spin 4s linear infinite;
+}
+@-moz-keyframes spin { 100% { -moz-transform: rotate(360deg); } }
+@-webkit-keyframes spin { 100% { -webkit-transform: rotate(360deg); } }
+@keyframes spin { 100% { -webkit-transform: rotate(360deg); transform:rotate(360deg); } }
+
+.spinner-hidden {
+ display:none;
+}
diff --git a/public/docs/_examples/style-guide/ts/src/04-11/app/core/spinner/spinner.component.html b/public/docs/_examples/style-guide/ts/src/04-11/app/core/spinner/spinner.component.html
new file mode 100644
index 0000000000..a07e3378c0
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-11/app/core/spinner/spinner.component.html
@@ -0,0 +1,2 @@
+
+
diff --git a/public/docs/_examples/style-guide/ts/src/04-11/app/core/spinner/spinner.component.ts b/public/docs/_examples/style-guide/ts/src/04-11/app/core/spinner/spinner.component.ts
new file mode 100644
index 0000000000..de24167a2b
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-11/app/core/spinner/spinner.component.ts
@@ -0,0 +1,35 @@
+// #docregion
+import { Component, OnDestroy, OnInit } from '@angular/core';
+import { Subscription } from 'rxjs/Subscription';
+
+import { LoggerService } from '../logger.service';
+import { SpinnerState, SpinnerService } from './spinner.service';
+
+@Component({
+ selector: 'toh-spinner',
+ templateUrl: './spinner.component.html',
+ styleUrls: ['./spinner.component.css']
+})
+export class SpinnerComponent implements OnDestroy, OnInit {
+ visible = false;
+
+ private spinnerStateChanged: Subscription;
+
+ constructor(
+ private loggerService: LoggerService,
+ private spinnerService: SpinnerService
+ ) { }
+
+ ngOnInit() {
+ console.log(this.visible);
+ this.spinnerStateChanged = this.spinnerService.spinnerState
+ .subscribe((state: SpinnerState) => {
+ this.visible = state.show;
+ this.loggerService.log(`visible=${this.visible}`);
+ });
+ }
+
+ ngOnDestroy() {
+ this.spinnerStateChanged.unsubscribe();
+ }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/04-11/app/core/spinner/spinner.service.ts b/public/docs/_examples/style-guide/ts/src/04-11/app/core/spinner/spinner.service.ts
new file mode 100644
index 0000000000..85e366c43e
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-11/app/core/spinner/spinner.service.ts
@@ -0,0 +1,24 @@
+// #docregion
+import { Injectable } from '@angular/core';
+import { Subject } from 'rxjs/Subject';
+
+export interface SpinnerState {
+ show: boolean;
+}
+
+@Injectable()
+export class SpinnerService {
+ private spinnerSubject = new Subject();
+
+ spinnerState = this.spinnerSubject.asObservable();
+
+ constructor() { }
+
+ show() {
+ this.spinnerSubject.next({ show: true });
+ }
+
+ hide() {
+ this.spinnerSubject.next({ show: false });
+ }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/04-11/app/heroes/heroes.component.html b/public/docs/_examples/style-guide/ts/src/04-11/app/heroes/heroes.component.html
new file mode 100644
index 0000000000..9035a4b8ff
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-11/app/heroes/heroes.component.html
@@ -0,0 +1,12 @@
+
+
diff --git a/public/docs/_examples/style-guide/ts/src/04-11/app/heroes/heroes.component.ts b/public/docs/_examples/style-guide/ts/src/04-11/app/heroes/heroes.component.ts
new file mode 100644
index 0000000000..856baadd74
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-11/app/heroes/heroes.component.ts
@@ -0,0 +1,32 @@
+import { Component } from '@angular/core';
+
+import { LoggerService } from '../core/logger.service';
+import { SpinnerService } from '../core/spinner/spinner.service';
+
+@Component({
+ selector: 'toh-heroes',
+ templateUrl: './heroes.component.html'
+})
+export class HeroesComponent {
+ heroes: any[];
+
+ constructor(
+ private loggerService: LoggerService,
+ private spinnerService: SpinnerService
+ ) { }
+
+ getHeroes() {
+ this.loggerService.log(`Getting heroes`);
+ this.spinnerService.show();
+ setTimeout(() => {
+ this.heroes = [
+ { id: 1, name: 'Windstorm' },
+ { id: 2, name: 'Bombasto' },
+ { id: 3, name: 'Magneta' },
+ { id: 4, name: 'Tornado' }
+ ];
+ this.loggerService.log(`We have ${HeroesComponent.length} heroes`);
+ this.spinnerService.hide();
+ }, 2000);
+ }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/04-12/app/app.component.ts b/public/docs/_examples/style-guide/ts/src/04-12/app/app.component.ts
new file mode 100644
index 0000000000..dc85b06e9f
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-12/app/app.component.ts
@@ -0,0 +1,11 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'toh-app',
+ template: `
+
+
+ `
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/style-guide/ts/src/04-12/app/app.module.ts b/public/docs/_examples/style-guide/ts/src/04-12/app/app.module.ts
new file mode 100644
index 0000000000..7c9fb44182
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-12/app/app.module.ts
@@ -0,0 +1,30 @@
+// #docplaster
+// #docregion
+// #docregion example
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+// #enddocregion example
+import { RouterModule } from '@angular/router';
+// #docregion example
+
+import { AppComponent } from './app.component';
+import { HeroesComponent } from './heroes/heroes.component';
+import { CoreModule } from './core/core.module';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ CoreModule,
+// #enddocregion example
+ RouterModule.forChild([{ path: '04-12', component: AppComponent }])
+// #docregion example
+ ],
+ declarations: [
+ AppComponent,
+ HeroesComponent
+ ],
+ exports: [ AppComponent ],
+ entryComponents: [ AppComponent ]
+})
+export class AppModule {}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/04-12/app/core/core.module.ts b/public/docs/_examples/style-guide/ts/src/04-12/app/core/core.module.ts
new file mode 100644
index 0000000000..069141bf2a
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-12/app/core/core.module.ts
@@ -0,0 +1,21 @@
+// #docregion
+import { NgModule, Optional, SkipSelf } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { LoggerService } from './logger.service';
+import { NavComponent } from './nav/nav.component';
+import { throwIfAlreadyLoaded } from './module-import-guard';
+
+@NgModule({
+ imports: [
+ CommonModule // we use ngFor
+ ],
+ exports: [NavComponent],
+ declarations: [NavComponent],
+ providers: [LoggerService]
+})
+export class CoreModule {
+ constructor( @Optional() @SkipSelf() parentModule: CoreModule) {
+ throwIfAlreadyLoaded(parentModule, 'CoreModule');
+ }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/04-12/app/core/index.ts b/public/docs/_examples/style-guide/ts/src/04-12/app/core/index.ts
new file mode 100644
index 0000000000..8768b77f41
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-12/app/core/index.ts
@@ -0,0 +1,3 @@
+// #docregion
+export * from './logger.service';
+export * from './nav/nav.component';
diff --git a/public/docs/_examples/style-guide/ts/src/04-12/app/core/logger.service.ts b/public/docs/_examples/style-guide/ts/src/04-12/app/core/logger.service.ts
new file mode 100644
index 0000000000..9c7080f07a
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-12/app/core/logger.service.ts
@@ -0,0 +1,13 @@
+// #docregion
+import { Injectable } from '@angular/core';
+
+@Injectable()
+export class LoggerService {
+ log(msg: string) {
+ console.log(msg);
+ }
+
+ error(msg: string) {
+ console.error(msg);
+ }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/04-12/app/core/module-import-guard.ts b/public/docs/_examples/style-guide/ts/src/04-12/app/core/module-import-guard.ts
new file mode 100644
index 0000000000..5248b15b2e
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-12/app/core/module-import-guard.ts
@@ -0,0 +1,6 @@
+// #docregion
+export function throwIfAlreadyLoaded(parentModule: any, moduleName: string) {
+ if (parentModule) {
+ throw new Error(`${moduleName} has already been loaded. Import Core modules in the AppModule only.`);
+ }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/04-12/app/core/nav/nav.component.css b/public/docs/_examples/style-guide/ts/src/04-12/app/core/nav/nav.component.css
new file mode 100644
index 0000000000..c7903fd25c
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-12/app/core/nav/nav.component.css
@@ -0,0 +1,63 @@
+/*#docregion*/
+.mdl-layout__header {
+ display: flex;
+ position: fixed;
+ background-color: #222;
+}
+
+.nav-link {
+ padding: 0 1em;
+ width: 100px;
+ color: rgba(255,255,255,.6);
+ text-align: center;
+ text-decoration: none;
+}
+
+.nav-link.router-link-active {
+ color: rgba(255,255,255, 1);
+}
+
+.nav-link.router-link-active::after {
+ height: 3px;
+ width: 100%;
+ display: block;
+ content: " ";
+ bottom: 0;
+ left: 0;
+ position: inherit;
+ background: rgb(83,109,254);
+}
+
+.md-title-icon > i {
+ background-image: url("assets/ng.png");
+ background-repeat: no-repeat;
+ background-position: center center;
+ padding: 1em 2em;
+}
+
+.mdl-layout__header-row {
+ height: 56px;
+ padding: 0 16px 0 72px;
+ padding-left: 8px;
+ background-color: #673AB7;
+ background: #0033FF;
+ background-color: #222;
+}
+
+#reset-button {
+ position: fixed;
+ right: 2em;
+ top: 1em;
+}
+
+@media (max-width: 480px) {
+ #reset-button {
+ display: none
+ }
+}
+
+@media (max-width: 320px) {
+ a.nav-link {
+ font-size: 12px;
+ }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/04-12/app/core/nav/nav.component.html b/public/docs/_examples/style-guide/ts/src/04-12/app/core/nav/nav.component.html
new file mode 100644
index 0000000000..b3c7e441e0
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-12/app/core/nav/nav.component.html
@@ -0,0 +1,14 @@
+
+
+
+
Tour of Heroes
+
+
+
+
+
+
diff --git a/public/docs/_examples/style-guide/ts/src/04-12/app/core/nav/nav.component.ts b/public/docs/_examples/style-guide/ts/src/04-12/app/core/nav/nav.component.ts
new file mode 100644
index 0000000000..7e21016e2b
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-12/app/core/nav/nav.component.ts
@@ -0,0 +1,19 @@
+// #docregion
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'toh-nav',
+ templateUrl: './nav.component.html',
+ styleUrls: ['./nav.component.css'],
+})
+export class NavComponent implements OnInit {
+ menuItems = [
+ 'Heroes',
+ 'Villains',
+ 'Other'
+ ];
+
+ ngOnInit() { }
+
+ constructor() { }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/04-12/app/heroes/heroes.component.html b/public/docs/_examples/style-guide/ts/src/04-12/app/heroes/heroes.component.html
new file mode 100644
index 0000000000..9035a4b8ff
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-12/app/heroes/heroes.component.html
@@ -0,0 +1,12 @@
+
+
diff --git a/public/docs/_examples/style-guide/ts/src/04-12/app/heroes/heroes.component.ts b/public/docs/_examples/style-guide/ts/src/04-12/app/heroes/heroes.component.ts
new file mode 100644
index 0000000000..f84b16c140
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/04-12/app/heroes/heroes.component.ts
@@ -0,0 +1,24 @@
+import { Component } from '@angular/core';
+
+import { LoggerService } from '../core/logger.service';
+
+@Component({
+ selector: 'toh-heroes',
+ templateUrl: './heroes.component.html'
+})
+export class HeroesComponent {
+ heroes: any[];
+
+ constructor(private loggerService: LoggerService) { }
+
+ getHeroes() {
+ this.loggerService.log(`Getting heroes`);
+ this.heroes = [
+ { id: 1, name: 'Windstorm' },
+ { id: 2, name: 'Bombasto' },
+ { id: 3, name: 'Magneta' },
+ { id: 4, name: 'Tornado' }
+ ];
+ this.loggerService.log(`We have ${HeroesComponent.length} heroes`);
+ }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/05-02/app/app.component.html b/public/docs/_examples/style-guide/ts/src/05-02/app/app.component.html
new file mode 100644
index 0000000000..607d068557
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-02/app/app.component.html
@@ -0,0 +1,2 @@
+
+
diff --git a/public/docs/_examples/style-guide/ts/src/05-02/app/app.component.ts b/public/docs/_examples/style-guide/ts/src/05-02/app/app.component.ts
new file mode 100644
index 0000000000..7c9f37919f
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-02/app/app.component.ts
@@ -0,0 +1,7 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'sg-app',
+ templateUrl: './app.component.html'
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/style-guide/ts/src/05-02/app/app.module.ts b/public/docs/_examples/style-guide/ts/src/05-02/app/app.module.ts
new file mode 100644
index 0000000000..1c458e2ca1
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-02/app/app.module.ts
@@ -0,0 +1,17 @@
+import { NgModule } from '@angular/core';
+import { RouterModule } from '@angular/router';
+
+import { AppComponent } from './app.component';
+import { HeroButtonComponent } from './heroes';
+
+@NgModule({
+ imports: [
+ RouterModule.forChild([{ path: '05-02', component: AppComponent }])
+ ],
+ declarations: [
+ AppComponent,
+ HeroButtonComponent
+ ],
+ exports: [ AppComponent ]
+})
+export class AppModule {}
diff --git a/public/docs/_examples/style-guide/ts/src/05-02/app/heroes/index.ts b/public/docs/_examples/style-guide/ts/src/05-02/app/heroes/index.ts
new file mode 100644
index 0000000000..c3da79f741
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-02/app/heroes/index.ts
@@ -0,0 +1 @@
+export * from './shared';
diff --git a/public/docs/_examples/style-guide/ts/src/05-02/app/heroes/shared/hero-button/hero-button.component.avoid.ts b/public/docs/_examples/style-guide/ts/src/05-02/app/heroes/shared/hero-button/hero-button.component.avoid.ts
new file mode 100644
index 0000000000..e48d41f721
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-02/app/heroes/shared/hero-button/hero-button.component.avoid.ts
@@ -0,0 +1,11 @@
+// #docplaster
+import { Component } from '@angular/core';
+// #docregion example
+/* avoid */
+
+@Component({
+ selector: 'tohHeroButton',
+ templateUrl: './hero-button.component.html'
+})
+export class HeroButtonComponent {}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/05-02/app/heroes/shared/hero-button/hero-button.component.html b/public/docs/_examples/style-guide/ts/src/05-02/app/heroes/shared/hero-button/hero-button.component.html
new file mode 100644
index 0000000000..9ad67e50ac
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-02/app/heroes/shared/hero-button/hero-button.component.html
@@ -0,0 +1 @@
+Hero button
diff --git a/public/docs/_examples/style-guide/ts/src/05-02/app/heroes/shared/hero-button/hero-button.component.ts b/public/docs/_examples/style-guide/ts/src/05-02/app/heroes/shared/hero-button/hero-button.component.ts
new file mode 100644
index 0000000000..c90c966f1a
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-02/app/heroes/shared/hero-button/hero-button.component.ts
@@ -0,0 +1,9 @@
+import { Component } from '@angular/core';
+
+// #docregion example
+@Component({
+ selector: 'toh-hero-button',
+ templateUrl: './hero-button.component.html'
+})
+export class HeroButtonComponent {}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/05-02/app/heroes/shared/hero-button/index.ts b/public/docs/_examples/style-guide/ts/src/05-02/app/heroes/shared/hero-button/index.ts
new file mode 100644
index 0000000000..6bb67c5670
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-02/app/heroes/shared/hero-button/index.ts
@@ -0,0 +1 @@
+export * from './hero-button.component';
diff --git a/public/docs/_examples/style-guide/ts/src/05-02/app/heroes/shared/index.ts b/public/docs/_examples/style-guide/ts/src/05-02/app/heroes/shared/index.ts
new file mode 100644
index 0000000000..2334d49c9a
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-02/app/heroes/shared/index.ts
@@ -0,0 +1 @@
+export * from './hero-button';
diff --git a/public/docs/_examples/style-guide/ts/src/05-02/app/index.ts b/public/docs/_examples/style-guide/ts/src/05-02/app/index.ts
new file mode 100644
index 0000000000..fe8300f1dd
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-02/app/index.ts
@@ -0,0 +1,2 @@
+export * from './heroes';
+export * from './app.component';
diff --git a/public/docs/_examples/style-guide/ts/src/05-03/app/app.component.avoid.html b/public/docs/_examples/style-guide/ts/src/05-03/app/app.component.avoid.html
new file mode 100644
index 0000000000..91bdbe403c
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-03/app/app.component.avoid.html
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/public/docs/_examples/style-guide/ts/src/05-03/app/app.component.html b/public/docs/_examples/style-guide/ts/src/05-03/app/app.component.html
new file mode 100644
index 0000000000..607d068557
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-03/app/app.component.html
@@ -0,0 +1,2 @@
+
+
diff --git a/public/docs/_examples/style-guide/ts/src/05-03/app/app.component.ts b/public/docs/_examples/style-guide/ts/src/05-03/app/app.component.ts
new file mode 100644
index 0000000000..7c9f37919f
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-03/app/app.component.ts
@@ -0,0 +1,7 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'sg-app',
+ templateUrl: './app.component.html'
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/style-guide/ts/src/05-03/app/app.module.ts b/public/docs/_examples/style-guide/ts/src/05-03/app/app.module.ts
new file mode 100644
index 0000000000..1b754e3ee5
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-03/app/app.module.ts
@@ -0,0 +1,17 @@
+import { NgModule } from '@angular/core';
+import { RouterModule } from '@angular/router';
+
+import { AppComponent } from './app.component';
+import { HeroButtonComponent } from './heroes';
+
+@NgModule({
+ imports: [
+ RouterModule.forChild([{ path: '05-03', component: AppComponent }])
+ ],
+ declarations: [
+ AppComponent,
+ HeroButtonComponent
+ ],
+ exports: [ AppComponent ]
+})
+export class AppModule {}
diff --git a/public/docs/_examples/style-guide/ts/src/05-03/app/heroes/index.ts b/public/docs/_examples/style-guide/ts/src/05-03/app/heroes/index.ts
new file mode 100644
index 0000000000..c3da79f741
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-03/app/heroes/index.ts
@@ -0,0 +1 @@
+export * from './shared';
diff --git a/public/docs/_examples/style-guide/ts/src/05-03/app/heroes/shared/hero-button/hero-button.component.avoid.ts b/public/docs/_examples/style-guide/ts/src/05-03/app/heroes/shared/hero-button/hero-button.component.avoid.ts
new file mode 100644
index 0000000000..74f5c36339
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-03/app/heroes/shared/hero-button/hero-button.component.avoid.ts
@@ -0,0 +1,10 @@
+import { Component } from '@angular/core';
+// #docregion example
+/* avoid */
+
+@Component({
+ selector: '[tohHeroButton]',
+ templateUrl: './hero-button.component.html'
+})
+export class HeroButtonComponent {}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/05-03/app/heroes/shared/hero-button/hero-button.component.html b/public/docs/_examples/style-guide/ts/src/05-03/app/heroes/shared/hero-button/hero-button.component.html
new file mode 100644
index 0000000000..9ad67e50ac
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-03/app/heroes/shared/hero-button/hero-button.component.html
@@ -0,0 +1 @@
+Hero button
diff --git a/public/docs/_examples/style-guide/ts/src/05-03/app/heroes/shared/hero-button/hero-button.component.ts b/public/docs/_examples/style-guide/ts/src/05-03/app/heroes/shared/hero-button/hero-button.component.ts
new file mode 100644
index 0000000000..c90c966f1a
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-03/app/heroes/shared/hero-button/hero-button.component.ts
@@ -0,0 +1,9 @@
+import { Component } from '@angular/core';
+
+// #docregion example
+@Component({
+ selector: 'toh-hero-button',
+ templateUrl: './hero-button.component.html'
+})
+export class HeroButtonComponent {}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/05-03/app/heroes/shared/hero-button/index.ts b/public/docs/_examples/style-guide/ts/src/05-03/app/heroes/shared/hero-button/index.ts
new file mode 100644
index 0000000000..6bb67c5670
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-03/app/heroes/shared/hero-button/index.ts
@@ -0,0 +1 @@
+export * from './hero-button.component';
diff --git a/public/docs/_examples/style-guide/ts/src/05-03/app/heroes/shared/index.ts b/public/docs/_examples/style-guide/ts/src/05-03/app/heroes/shared/index.ts
new file mode 100644
index 0000000000..2334d49c9a
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-03/app/heroes/shared/index.ts
@@ -0,0 +1 @@
+export * from './hero-button';
diff --git a/public/docs/_examples/style-guide/ts/src/05-03/app/index.ts b/public/docs/_examples/style-guide/ts/src/05-03/app/index.ts
new file mode 100644
index 0000000000..fe8300f1dd
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-03/app/index.ts
@@ -0,0 +1,2 @@
+export * from './heroes';
+export * from './app.component';
diff --git a/public/docs/_examples/style-guide/ts/src/05-04/app/app.component.ts b/public/docs/_examples/style-guide/ts/src/05-04/app/app.component.ts
new file mode 100644
index 0000000000..0e43893f7f
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-04/app/app.component.ts
@@ -0,0 +1,7 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'sg-app',
+ template: ' '
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/style-guide/ts/src/05-04/app/app.module.ts b/public/docs/_examples/style-guide/ts/src/05-04/app/app.module.ts
new file mode 100644
index 0000000000..07f97cc6e4
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-04/app/app.module.ts
@@ -0,0 +1,21 @@
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { RouterModule } from '@angular/router';
+
+import { AppComponent } from './app.component';
+import { HeroesComponent } from './heroes';
+import { HeroService } from './heroes/shared';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ RouterModule.forChild([{ path: '05-04', component: AppComponent }])
+ ],
+ declarations: [
+ AppComponent,
+ HeroesComponent
+ ],
+ exports: [ AppComponent ],
+ providers: [ HeroService ]
+})
+export class AppModule {}
diff --git a/public/docs/_examples/style-guide/ts/src/05-04/app/heroes/heroes.component.avoid.ts b/public/docs/_examples/style-guide/ts/src/05-04/app/heroes/heroes.component.avoid.ts
new file mode 100644
index 0000000000..0ceb37032d
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-04/app/heroes/heroes.component.avoid.ts
@@ -0,0 +1,64 @@
+import { Component, OnInit } from '@angular/core';
+import { Observable } from 'rxjs/Observable';
+
+import { Hero, HeroService } from './shared';
+
+// #docregion example
+/* avoid */
+
+@Component({
+ selector: 'toh-heroes',
+ template: `
+
+
My Heroes
+
+
+ {{hero.id}} {{hero.name}}
+
+
+
+
{{selectedHero.name | uppercase}} is my hero
+
+
+ `,
+ styles: [`
+ .heroes {
+ margin: 0 0 2em 0; list-style-type: none; padding: 0; width: 15em;
+ }
+ .heroes li {
+ cursor: pointer;
+ position: relative;
+ left: 0;
+ background-color: #EEE;
+ margin: .5em;
+ padding: .3em 0;
+ height: 1.6em;
+ border-radius: 4px;
+ }
+ .heroes .badge {
+ display: inline-block;
+ font-size: small;
+ color: white;
+ padding: 0.8em 0.7em 0 0.7em;
+ background-color: #607D8B;
+ line-height: 1em;
+ position: relative;
+ left: -1px;
+ top: -4px;
+ height: 1.8em;
+ margin-right: .8em;
+ border-radius: 4px 0 0 4px;
+ }
+ `]
+})
+export class HeroesComponent implements OnInit {
+ heroes: Observable;
+ selectedHero: Hero;
+
+ constructor(private heroService: HeroService) { }
+
+ ngOnInit() {
+ this.heroes = this.heroService.getHeroes();
+ }
+}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/05-04/app/heroes/heroes.component.css b/public/docs/_examples/style-guide/ts/src/05-04/app/heroes/heroes.component.css
new file mode 100644
index 0000000000..82f0c1d0ab
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-04/app/heroes/heroes.component.css
@@ -0,0 +1,28 @@
+/* #docregion */
+.heroes {
+ margin: 0 0 2em 0; list-style-type: none; padding: 0; width: 15em;
+}
+.heroes li {
+ cursor: pointer;
+ position: relative;
+ left: 0;
+ background-color: #EEE;
+ margin: .5em;
+ padding: .3em 0;
+ height: 1.6em;
+ border-radius: 4px;
+}
+.heroes .badge {
+ display: inline-block;
+ font-size: small;
+ color: white;
+ padding: 0.8em 0.7em 0 0.7em;
+ background-color: #607D8B;
+ line-height: 1em;
+ position: relative;
+ left: -1px;
+ top: -4px;
+ height: 1.8em;
+ margin-right: .8em;
+ border-radius: 4px 0 0 4px;
+}
diff --git a/public/docs/_examples/style-guide/ts/src/05-04/app/heroes/heroes.component.html b/public/docs/_examples/style-guide/ts/src/05-04/app/heroes/heroes.component.html
new file mode 100644
index 0000000000..bab05ceb2b
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-04/app/heroes/heroes.component.html
@@ -0,0 +1,12 @@
+
+
+
My Heroes
+
+
+ {{hero.id}} {{hero.name}}
+
+
+
+
{{selectedHero.name | uppercase}} is my hero
+
+
diff --git a/public/docs/_examples/style-guide/ts/src/05-04/app/heroes/heroes.component.ts b/public/docs/_examples/style-guide/ts/src/05-04/app/heroes/heroes.component.ts
new file mode 100644
index 0000000000..c19bc997ae
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-04/app/heroes/heroes.component.ts
@@ -0,0 +1,22 @@
+import { Component, OnInit } from '@angular/core';
+import { Observable } from 'rxjs/Observable';
+
+import { Hero, HeroService } from './shared';
+
+// #docregion example
+@Component({
+ selector: 'toh-heroes',
+ templateUrl: './heroes.component.html',
+ styleUrls: ['./heroes.component.css']
+})
+export class HeroesComponent implements OnInit {
+ heroes: Observable;
+ selectedHero: Hero;
+
+ constructor(private heroService: HeroService) { }
+
+ ngOnInit() {
+ this.heroes = this.heroService.getHeroes();
+ }
+}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/05-04/app/heroes/index.ts b/public/docs/_examples/style-guide/ts/src/05-04/app/heroes/index.ts
new file mode 100644
index 0000000000..a8d7f1d422
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-04/app/heroes/index.ts
@@ -0,0 +1,2 @@
+export * from './shared';
+export * from './heroes.component';
diff --git a/public/docs/_examples/style-guide/ts/src/05-04/app/heroes/shared/hero.model.ts b/public/docs/_examples/style-guide/ts/src/05-04/app/heroes/shared/hero.model.ts
new file mode 100644
index 0000000000..8f7cc205c8
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-04/app/heroes/shared/hero.model.ts
@@ -0,0 +1,5 @@
+// #docregion
+export class Hero {
+ id: number;
+ name: string;
+}
diff --git a/public/docs/_examples/style-guide/ts/src/05-04/app/heroes/shared/hero.service.ts b/public/docs/_examples/style-guide/ts/src/05-04/app/heroes/shared/hero.service.ts
new file mode 100644
index 0000000000..9d388780a6
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-04/app/heroes/shared/hero.service.ts
@@ -0,0 +1,18 @@
+import { Injectable } from '@angular/core';
+import { Http } from '@angular/http';
+
+import { Observable } from 'rxjs/Observable';
+import 'rxjs/add/operator/map';
+
+import { Hero } from './hero.model';
+
+@Injectable()
+export class HeroService {
+
+ constructor(private http: Http) {}
+
+ getHeroes(): Observable {
+ return this.http.get('api/heroes')
+ .map(resp => resp.json().data as Hero[]);
+ }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/05-04/app/heroes/shared/index.ts b/public/docs/_examples/style-guide/ts/src/05-04/app/heroes/shared/index.ts
new file mode 100644
index 0000000000..dbb150d3f8
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-04/app/heroes/shared/index.ts
@@ -0,0 +1,2 @@
+export * from './hero.model';
+export * from './hero.service';
diff --git a/public/docs/_examples/style-guide/ts/src/05-04/app/index.ts b/public/docs/_examples/style-guide/ts/src/05-04/app/index.ts
new file mode 100644
index 0000000000..fe8300f1dd
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-04/app/index.ts
@@ -0,0 +1,2 @@
+export * from './heroes';
+export * from './app.component';
diff --git a/public/docs/_examples/style-guide/ts/src/05-12/app/app.component.ts b/public/docs/_examples/style-guide/ts/src/05-12/app/app.component.ts
new file mode 100644
index 0000000000..dac40205c9
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-12/app/app.component.ts
@@ -0,0 +1,7 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'sg-app',
+ template: ' '
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/style-guide/ts/src/05-12/app/app.module.ts b/public/docs/_examples/style-guide/ts/src/05-12/app/app.module.ts
new file mode 100644
index 0000000000..5177b2cc64
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-12/app/app.module.ts
@@ -0,0 +1,17 @@
+import { NgModule } from '@angular/core';
+import { RouterModule } from '@angular/router';
+
+import { AppComponent } from './app.component';
+import { HeroButtonComponent } from './heroes';
+
+@NgModule({
+ imports: [
+ RouterModule.forChild([{ path: '05-12', component: AppComponent }])
+ ],
+ declarations: [
+ AppComponent,
+ HeroButtonComponent
+ ],
+ exports: [ AppComponent ]
+})
+export class AppModule {}
diff --git a/public/docs/_examples/style-guide/ts/src/05-12/app/heroes/index.ts b/public/docs/_examples/style-guide/ts/src/05-12/app/heroes/index.ts
new file mode 100644
index 0000000000..c3da79f741
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-12/app/heroes/index.ts
@@ -0,0 +1 @@
+export * from './shared';
diff --git a/public/docs/_examples/style-guide/ts/src/05-12/app/heroes/shared/hero-button/hero-button.component.avoid.ts b/public/docs/_examples/style-guide/ts/src/05-12/app/heroes/shared/hero-button/hero-button.component.avoid.ts
new file mode 100644
index 0000000000..8f393ddd32
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-12/app/heroes/shared/hero-button/hero-button.component.avoid.ts
@@ -0,0 +1,20 @@
+// #docregion
+import { Component, EventEmitter } from '@angular/core';
+// #docregion example
+/* avoid */
+
+@Component({
+ selector: 'toh-hero-button',
+ template: ` `,
+ inputs: [
+ 'label'
+ ],
+ outputs: [
+ 'change'
+ ]
+})
+export class HeroButtonComponent {
+ change = new EventEmitter();
+ label: string;
+}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/05-12/app/heroes/shared/hero-button/hero-button.component.ts b/public/docs/_examples/style-guide/ts/src/05-12/app/heroes/shared/hero-button/hero-button.component.ts
new file mode 100644
index 0000000000..b299740765
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-12/app/heroes/shared/hero-button/hero-button.component.ts
@@ -0,0 +1,13 @@
+// #docregion
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+
+// #docregion example
+@Component({
+ selector: 'toh-hero-button',
+ template: `{{label}} `
+})
+export class HeroButtonComponent {
+ @Output() change = new EventEmitter();
+ @Input() label: string;
+}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/05-12/app/heroes/shared/hero-button/index.ts b/public/docs/_examples/style-guide/ts/src/05-12/app/heroes/shared/hero-button/index.ts
new file mode 100644
index 0000000000..6bb67c5670
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-12/app/heroes/shared/hero-button/index.ts
@@ -0,0 +1 @@
+export * from './hero-button.component';
diff --git a/public/docs/_examples/style-guide/ts/src/05-12/app/heroes/shared/index.ts b/public/docs/_examples/style-guide/ts/src/05-12/app/heroes/shared/index.ts
new file mode 100644
index 0000000000..2334d49c9a
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-12/app/heroes/shared/index.ts
@@ -0,0 +1 @@
+export * from './hero-button';
diff --git a/public/docs/_examples/style-guide/ts/src/05-12/app/index.ts b/public/docs/_examples/style-guide/ts/src/05-12/app/index.ts
new file mode 100644
index 0000000000..fe8300f1dd
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-12/app/index.ts
@@ -0,0 +1,2 @@
+export * from './heroes';
+export * from './app.component';
diff --git a/public/docs/_examples/style-guide/ts/src/05-13/app/app.component.avoid.html b/public/docs/_examples/style-guide/ts/src/05-13/app/app.component.avoid.html
new file mode 100644
index 0000000000..0a263a6a95
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-13/app/app.component.avoid.html
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/public/docs/_examples/style-guide/ts/src/05-13/app/app.component.html b/public/docs/_examples/style-guide/ts/src/05-13/app/app.component.html
new file mode 100644
index 0000000000..3cd94ca772
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-13/app/app.component.html
@@ -0,0 +1,6 @@
+
+
+
+
+
+The Great Bombasto
diff --git a/public/docs/_examples/style-guide/ts/src/05-13/app/app.component.ts b/public/docs/_examples/style-guide/ts/src/05-13/app/app.component.ts
new file mode 100644
index 0000000000..7c9f37919f
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-13/app/app.component.ts
@@ -0,0 +1,7 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'sg-app',
+ templateUrl: './app.component.html'
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/style-guide/ts/src/05-13/app/app.module.ts b/public/docs/_examples/style-guide/ts/src/05-13/app/app.module.ts
new file mode 100644
index 0000000000..7ebe91dbbc
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-13/app/app.module.ts
@@ -0,0 +1,17 @@
+import { NgModule } from '@angular/core';
+import { RouterModule } from '@angular/router';
+
+import { AppComponent } from './app.component';
+import { HeroButtonComponent, HeroHighlightDirective } from './heroes';
+
+@NgModule({
+ imports: [
+ RouterModule.forChild([{ path: '05-13', component: AppComponent }])
+ ],
+ declarations: [
+ AppComponent,
+ HeroButtonComponent, HeroHighlightDirective
+ ],
+ exports: [ AppComponent ]
+})
+export class AppModule {}
diff --git a/public/docs/_examples/style-guide/ts/src/05-13/app/heroes/index.ts b/public/docs/_examples/style-guide/ts/src/05-13/app/heroes/index.ts
new file mode 100644
index 0000000000..c3da79f741
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-13/app/heroes/index.ts
@@ -0,0 +1 @@
+export * from './shared';
diff --git a/public/docs/_examples/style-guide/ts/src/05-13/app/heroes/shared/hero-button/hero-button.component.avoid.ts b/public/docs/_examples/style-guide/ts/src/05-13/app/heroes/shared/hero-button/hero-button.component.avoid.ts
new file mode 100644
index 0000000000..4e67a14113
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-13/app/heroes/shared/hero-button/hero-button.component.avoid.ts
@@ -0,0 +1,14 @@
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+// #docregion example
+/* avoid pointless aliasing */
+
+@Component({
+ selector: 'toh-hero-button',
+ template: `{{label}} `
+})
+export class HeroButtonComponent {
+ // Pointless aliases
+ @Output('changeEvent') change = new EventEmitter();
+ @Input('labelAttribute') label: string;
+}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/05-13/app/heroes/shared/hero-button/hero-button.component.ts b/public/docs/_examples/style-guide/ts/src/05-13/app/heroes/shared/hero-button/hero-button.component.ts
new file mode 100644
index 0000000000..af6e7d46b7
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-13/app/heroes/shared/hero-button/hero-button.component.ts
@@ -0,0 +1,14 @@
+// #docregion
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+
+// #docregion example
+@Component({
+ selector: 'toh-hero-button',
+ template: `{{label}} `
+})
+export class HeroButtonComponent {
+ // No aliases
+ @Output() change = new EventEmitter();
+ @Input() label: string;
+}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/05-13/app/heroes/shared/hero-button/index.ts b/public/docs/_examples/style-guide/ts/src/05-13/app/heroes/shared/hero-button/index.ts
new file mode 100644
index 0000000000..6bb67c5670
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-13/app/heroes/shared/hero-button/index.ts
@@ -0,0 +1 @@
+export * from './hero-button.component';
diff --git a/public/docs/_examples/style-guide/ts/src/05-13/app/heroes/shared/hero-highlight.directive.ts b/public/docs/_examples/style-guide/ts/src/05-13/app/heroes/shared/hero-highlight.directive.ts
new file mode 100644
index 0000000000..737af31f4f
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-13/app/heroes/shared/hero-highlight.directive.ts
@@ -0,0 +1,15 @@
+// #docregion
+import { Directive, ElementRef, Input, OnChanges } from '@angular/core';
+
+@Directive({ selector: '[heroHighlight]' })
+export class HeroHighlightDirective implements OnChanges {
+
+ // Aliased because `color` is a better property name than `heroHighlight`
+ @Input('heroHighlight') color: string;
+
+ constructor(private el: ElementRef) {}
+
+ ngOnChanges() {
+ this.el.nativeElement.style.backgroundColor = this.color || 'yellow';
+ }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/05-13/app/heroes/shared/index.ts b/public/docs/_examples/style-guide/ts/src/05-13/app/heroes/shared/index.ts
new file mode 100644
index 0000000000..565f46cf4f
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-13/app/heroes/shared/index.ts
@@ -0,0 +1,2 @@
+export * from './hero-button';
+export * from './hero-highlight.directive';
diff --git a/public/docs/_examples/style-guide/ts/src/05-13/app/index.ts b/public/docs/_examples/style-guide/ts/src/05-13/app/index.ts
new file mode 100644
index 0000000000..fe8300f1dd
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-13/app/index.ts
@@ -0,0 +1,2 @@
+export * from './heroes';
+export * from './app.component';
diff --git a/public/docs/_examples/style-guide/ts/src/05-14/app/app.component.ts b/public/docs/_examples/style-guide/ts/src/05-14/app/app.component.ts
new file mode 100644
index 0000000000..8ed6da4c82
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-14/app/app.component.ts
@@ -0,0 +1,7 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'sg-app',
+ template: ` `
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/style-guide/ts/src/05-14/app/app.module.ts b/public/docs/_examples/style-guide/ts/src/05-14/app/app.module.ts
new file mode 100644
index 0000000000..0b294573d2
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-14/app/app.module.ts
@@ -0,0 +1,17 @@
+import { NgModule } from '@angular/core';
+import { RouterModule } from '@angular/router';
+
+import { AppComponent } from './app.component';
+import { ToastComponent } from './shared';
+
+@NgModule({
+ imports: [
+ RouterModule.forChild([{ path: '05-14', component: AppComponent }])
+ ],
+ declarations: [
+ AppComponent,
+ ToastComponent
+ ],
+ exports: [ AppComponent ]
+})
+export class AppModule {}
diff --git a/public/docs/_examples/style-guide/ts/src/05-14/app/index.ts b/public/docs/_examples/style-guide/ts/src/05-14/app/index.ts
new file mode 100644
index 0000000000..ebe5c92f03
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-14/app/index.ts
@@ -0,0 +1,2 @@
+export * from './shared';
+export * from './app.component';
diff --git a/public/docs/_examples/style-guide/ts/src/05-14/app/shared/index.ts b/public/docs/_examples/style-guide/ts/src/05-14/app/shared/index.ts
new file mode 100644
index 0000000000..7ff6d415e7
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-14/app/shared/index.ts
@@ -0,0 +1 @@
+export * from './toast';
diff --git a/public/docs/_examples/style-guide/ts/src/05-14/app/shared/toast/index.ts b/public/docs/_examples/style-guide/ts/src/05-14/app/shared/toast/index.ts
new file mode 100644
index 0000000000..6502de796e
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-14/app/shared/toast/index.ts
@@ -0,0 +1 @@
+export * from './toast.component';
diff --git a/public/docs/_examples/style-guide/ts/src/05-14/app/shared/toast/toast.component.avoid.ts b/public/docs/_examples/style-guide/ts/src/05-14/app/shared/toast/toast.component.avoid.ts
new file mode 100644
index 0000000000..037ff2c8b5
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-14/app/shared/toast/toast.component.avoid.ts
@@ -0,0 +1,40 @@
+// #docregion
+import { OnInit } from '@angular/core';
+// #docregion example
+/* avoid */
+
+export class ToastComponent implements OnInit {
+
+ private defaults = {
+ title: '',
+ message: 'May the Force be with you'
+ };
+ message: string;
+ title: string;
+ private toastElement: any;
+
+ ngOnInit() {
+ this.toastElement = document.getElementById('toh-toast');
+ }
+
+ // private methods
+ private hide() {
+ this.toastElement.style.opacity = 0;
+ window.setTimeout(() => this.toastElement.style.zIndex = 0, 400);
+ }
+
+ activate(message = this.defaults.message, title = this.defaults.title) {
+ this.title = title;
+ this.message = message;
+ this.show();
+ }
+
+ private show() {
+ console.log(this.message);
+ this.toastElement.style.opacity = 1;
+ this.toastElement.style.zIndex = 9999;
+
+ window.setTimeout(() => this.hide(), 2500);
+ }
+}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/05-14/app/shared/toast/toast.component.ts b/public/docs/_examples/style-guide/ts/src/05-14/app/shared/toast/toast.component.ts
new file mode 100644
index 0000000000..d7b8ea4af0
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-14/app/shared/toast/toast.component.ts
@@ -0,0 +1,45 @@
+// #docregion
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'toh-toast',
+ template: `...`
+})
+// #docregion example
+export class ToastComponent implements OnInit {
+ // public properties
+ message: string;
+ title: string;
+
+ // private fields
+ private defaults = {
+ title: '',
+ message: 'May the Force be with you'
+ };
+ private toastElement: any;
+
+ // public methods
+ activate(message = this.defaults.message, title = this.defaults.title) {
+ this.title = title;
+ this.message = message;
+ this.show();
+ }
+
+ ngOnInit() {
+ this.toastElement = document.getElementById('toh-toast');
+ }
+
+ // private methods
+ private hide() {
+ this.toastElement.style.opacity = 0;
+ window.setTimeout(() => this.toastElement.style.zIndex = 0, 400);
+ }
+
+ private show() {
+ console.log(this.message);
+ this.toastElement.style.opacity = 1;
+ this.toastElement.style.zIndex = 9999;
+ window.setTimeout(() => this.hide(), 2500);
+ }
+}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/05-15/app/app.component.ts b/public/docs/_examples/style-guide/ts/src/05-15/app/app.component.ts
new file mode 100644
index 0000000000..91b569b1e7
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-15/app/app.component.ts
@@ -0,0 +1,10 @@
+import { Component } from '@angular/core';
+
+import { HeroService } from './heroes';
+
+@Component({
+ selector: 'sg-app',
+ template: ' ',
+ providers: [HeroService]
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/style-guide/ts/src/05-15/app/app.module.ts b/public/docs/_examples/style-guide/ts/src/05-15/app/app.module.ts
new file mode 100644
index 0000000000..9bd4b8c9a2
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-15/app/app.module.ts
@@ -0,0 +1,19 @@
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { RouterModule } from '@angular/router';
+
+import { AppComponent } from './app.component';
+import { HeroListComponent } from './heroes';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ RouterModule.forChild([{ path: '05-15', component: AppComponent }])
+ ],
+ declarations: [
+ AppComponent,
+ HeroListComponent
+ ],
+ exports: [ AppComponent ]
+})
+export class AppModule {}
diff --git a/public/docs/_examples/style-guide/ts/src/05-15/app/heroes/hero-list/hero-list.component.avoid.ts b/public/docs/_examples/style-guide/ts/src/05-15/app/heroes/hero-list/hero-list.component.avoid.ts
new file mode 100644
index 0000000000..c323ba2b1c
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-15/app/heroes/hero-list/hero-list.component.avoid.ts
@@ -0,0 +1,39 @@
+// #docregion
+/* avoid */
+
+import { OnInit } from '@angular/core';
+import { Http, Response } from '@angular/http';
+
+import { Observable } from 'rxjs/Observable';
+import 'rxjs/add/operator/catch';
+import 'rxjs/add/operator/finally';
+import 'rxjs/add/operator/map';
+
+import { Hero } from '../shared/hero.model';
+
+const heroesUrl = 'http://angular.io';
+
+export class HeroListComponent implements OnInit {
+ heroes: Hero[];
+ constructor(private http: Http) {}
+ getHeroes() {
+ this.heroes = [];
+ this.http.get(heroesUrl)
+ .map((response: Response) => response.json().data)
+ .catch(this.catchBadResponse)
+ .finally(() => this.hideSpinner())
+ .subscribe((heroes: Hero[]) => this.heroes = heroes);
+ }
+ ngOnInit() {
+ this.getHeroes();
+ }
+
+ private catchBadResponse(err: any, source: Observable) {
+ // log and handle the exception
+ return new Observable();
+ }
+
+ private hideSpinner() {
+ // hide the spinner
+ }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/05-15/app/heroes/hero-list/hero-list.component.ts b/public/docs/_examples/style-guide/ts/src/05-15/app/heroes/hero-list/hero-list.component.ts
new file mode 100644
index 0000000000..1fdb893c13
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-15/app/heroes/hero-list/hero-list.component.ts
@@ -0,0 +1,23 @@
+// #docregion example
+import { Component, OnInit } from '@angular/core';
+
+import { Hero, HeroService } from '../shared';
+
+@Component({
+ selector: 'toh-hero-list',
+ template: `...`
+})
+export class HeroListComponent implements OnInit {
+ heroes: Hero[];
+ constructor(private heroService: HeroService) {}
+ getHeroes() {
+ this.heroes = [];
+ this.heroService.getHeroes()
+ .subscribe(heroes => this.heroes = heroes);
+ }
+ ngOnInit() {
+ this.getHeroes();
+ }
+}
+// #enddocregion example
+
diff --git a/public/docs/_examples/style-guide/ts/src/05-15/app/heroes/hero-list/index.ts b/public/docs/_examples/style-guide/ts/src/05-15/app/heroes/hero-list/index.ts
new file mode 100644
index 0000000000..c4bcb3278e
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-15/app/heroes/hero-list/index.ts
@@ -0,0 +1 @@
+export * from './hero-list.component';
diff --git a/public/docs/_examples/style-guide/ts/src/05-15/app/heroes/index.ts b/public/docs/_examples/style-guide/ts/src/05-15/app/heroes/index.ts
new file mode 100644
index 0000000000..f1112f1c7c
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-15/app/heroes/index.ts
@@ -0,0 +1,2 @@
+export * from './hero-list';
+export * from './shared';
diff --git a/public/docs/_examples/style-guide/ts/src/05-15/app/heroes/shared/hero.model.ts b/public/docs/_examples/style-guide/ts/src/05-15/app/heroes/shared/hero.model.ts
new file mode 100644
index 0000000000..8f7cc205c8
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-15/app/heroes/shared/hero.model.ts
@@ -0,0 +1,5 @@
+// #docregion
+export class Hero {
+ id: number;
+ name: string;
+}
diff --git a/public/docs/_examples/style-guide/ts/src/05-15/app/heroes/shared/hero.service.ts b/public/docs/_examples/style-guide/ts/src/05-15/app/heroes/shared/hero.service.ts
new file mode 100644
index 0000000000..72d07bbed4
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-15/app/heroes/shared/hero.service.ts
@@ -0,0 +1,15 @@
+// #docregion
+import { Injectable } from '@angular/core';
+
+import { Observable } from 'rxjs/Observable';
+import 'rxjs/add/observable/of';
+
+import { Hero } from './hero.model';
+
+@Injectable()
+export class HeroService {
+ getHeroes() {
+ let heroes: Hero[] = [];
+ return Observable.of(heroes);
+ }
+}
diff --git a/public/docs/_examples/style-guide/ts/src/05-15/app/heroes/shared/index.ts b/public/docs/_examples/style-guide/ts/src/05-15/app/heroes/shared/index.ts
new file mode 100644
index 0000000000..27516fdedd
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-15/app/heroes/shared/index.ts
@@ -0,0 +1,3 @@
+// #docregion
+export * from './hero.model';
+export * from './hero.service';
diff --git a/public/docs/_examples/style-guide/ts/src/05-15/app/index.ts b/public/docs/_examples/style-guide/ts/src/05-15/app/index.ts
new file mode 100644
index 0000000000..fe8300f1dd
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-15/app/index.ts
@@ -0,0 +1,2 @@
+export * from './heroes';
+export * from './app.component';
diff --git a/public/docs/_examples/style-guide/ts/src/05-16/app/app.component.avoid.html b/public/docs/_examples/style-guide/ts/src/05-16/app/app.component.avoid.html
new file mode 100644
index 0000000000..2c0cea58e2
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-16/app/app.component.avoid.html
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/public/docs/_examples/style-guide/ts/src/05-16/app/app.component.html b/public/docs/_examples/style-guide/ts/src/05-16/app/app.component.html
new file mode 100644
index 0000000000..4883a6940a
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-16/app/app.component.html
@@ -0,0 +1,2 @@
+
+
diff --git a/public/docs/_examples/style-guide/ts/src/05-16/app/app.component.ts b/public/docs/_examples/style-guide/ts/src/05-16/app/app.component.ts
new file mode 100644
index 0000000000..7c9f37919f
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-16/app/app.component.ts
@@ -0,0 +1,7 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'sg-app',
+ templateUrl: './app.component.html'
+})
+export class AppComponent { }
diff --git a/public/docs/_examples/style-guide/ts/src/05-16/app/app.module.ts b/public/docs/_examples/style-guide/ts/src/05-16/app/app.module.ts
new file mode 100644
index 0000000000..c3fb36f8ac
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-16/app/app.module.ts
@@ -0,0 +1,19 @@
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { RouterModule } from '@angular/router';
+
+import { AppComponent } from './app.component';
+import { HeroComponent } from './heroes';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ RouterModule.forChild([{ path: '05-16', component: AppComponent }])
+ ],
+ declarations: [
+ AppComponent,
+ HeroComponent
+ ],
+ exports: [ AppComponent ]
+})
+export class AppModule {}
diff --git a/public/docs/_examples/style-guide/ts/src/05-16/app/heroes/hero.component.avoid.ts b/public/docs/_examples/style-guide/ts/src/05-16/app/heroes/hero.component.avoid.ts
new file mode 100644
index 0000000000..823aa2e1c7
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-16/app/heroes/hero.component.avoid.ts
@@ -0,0 +1,13 @@
+// #docregion
+import { Component, EventEmitter, Output } from '@angular/core';
+// #docregion example
+/* avoid */
+
+@Component({
+ selector: 'toh-hero',
+ template: `...`
+})
+export class HeroComponent {
+ @Output() onSavedTheDay = new EventEmitter();
+}
+// #enddocregion example
diff --git a/public/docs/_examples/style-guide/ts/src/05-16/app/heroes/hero.component.ts b/public/docs/_examples/style-guide/ts/src/05-16/app/heroes/hero.component.ts
new file mode 100644
index 0000000000..bbd4a4b5f3
--- /dev/null
+++ b/public/docs/_examples/style-guide/ts/src/05-16/app/heroes/hero.component.ts
@@ -0,0 +1,14 @@
+// #docregion
+import { Component, EventEmitter, Output } from '@angular/core';
+
+@Component({
+ selector: 'toh-hero',
+ template: `...`
+})
+// #docregion example
+export class HeroComponent {
+ @Output() savedTheDay = new EventEmitter