diff --git a/.gitignore b/.gitignore
index 4f8d611769..b6d52bd9b9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,4 +29,4 @@ plnkr.html
public/docs/*/latest/guide/cheatsheet.json
protractor-results.txt
link-checker-results.txt
-.history/
+*a2docs.css
diff --git a/gulpfile.js b/gulpfile.js
index b2e93be14e..c6e15ae13f 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -22,7 +22,7 @@ var globby = require("globby");
// - because childProcess.kill does not work properly on windows
var treeKill = require("tree-kill");
var blc = require("broken-link-checker");
-
+var less = require('gulp-less');
var tslint = require('gulp-tslint');
// TODO:
@@ -41,6 +41,7 @@ var EXAMPLES_PROTRACTOR_PATH = path.join(EXAMPLES_PATH, '_protractor');
var NOT_API_DOCS_GLOB = path.join(PUBLIC_PATH, './{docs/*/latest/!(api),!(docs)}/**/*.*');
var RESOURCES_PATH = path.join(PUBLIC_PATH, 'resources');
var LIVE_EXAMPLES_PATH = path.join(RESOURCES_PATH, 'live-examples');
+var STYLES_SOURCE_PATH = path.join(TOOLS_PATH, 'styles-builder/less');
var docShredder = require(path.resolve(TOOLS_PATH, 'doc-shredder/doc-shredder'));
var exampleZipper = require(path.resolve(TOOLS_PATH, '_example-zipper/exampleZipper'));
@@ -87,6 +88,7 @@ var _excludeMatchers = _excludePatterns.map(function(excludePattern){
var _exampleBoilerplateFiles = [
'.editorconfig',
+ 'a2docs.css',
'karma.conf.js',
'karma-test-shim.js',
'package.json',
@@ -98,7 +100,7 @@ var _exampleBoilerplateFiles = [
'wallaby.js'
];
-var _exampleDartWebBoilerPlateFiles = ['styles.css'];
+var _exampleDartWebBoilerPlateFiles = ['a2docs.css', 'styles.css'];
var _exampleProtractorBoilerplateFiles = [
'tsconfig.json'
@@ -106,6 +108,8 @@ var _exampleProtractorBoilerplateFiles = [
var _exampleConfigFilename = 'example-config.json';
+var _styleLessName = 'a2docs.less';
+
// Gulp flags:
//
// --lang=[all | ts | js | dart | 'ts|js' | 'ts|js|dart' | ...]
@@ -118,7 +122,7 @@ var _exampleConfigFilename = 'example-config.json';
var lang, langs, buildDartApiDocs = false;
function configLangs(langOption) {
const fullSiteBuildTasks = ['build-compile', 'check-serve', 'check-deploy'];
- const buildAllDocs = argv['_'] &&
+ const buildAllDocs = argv['_'] &&
fullSiteBuildTasks.some((task) => argv['_'].indexOf(task) >= 0);
const langDefault = buildAllDocs ? 'all' : 'ts|js';
lang = (langOption || langDefault).toLowerCase();
@@ -190,7 +194,7 @@ function runE2e() {
return spawnInfo.promise;
})
.then(function() {
- copyExampleBoilerplate();
+ buildStyles(copyExampleBoilerplate, _.noop);
gutil.log('runE2e: update webdriver');
spawnInfo = spawnExt('npm', ['run', 'webdriver:update'], {cwd: EXAMPLES_PROTRACTOR_PATH});
return spawnInfo.promise;
@@ -414,7 +418,7 @@ gulp.task('help', taskListing.withFilters(function(taskName) {
}));
// requires admin access because it adds symlinks
-gulp.task('add-example-boilerplate', function() {
+gulp.task('add-example-boilerplate', function(done) {
var realPath = path.join(EXAMPLES_PATH, '/node_modules');
var nodeModulesPaths = excludeDartPaths(getNodeModulesPaths(EXAMPLES_PATH));
@@ -430,16 +434,26 @@ gulp.task('add-example-boilerplate', function() {
fsUtils.addSymlink(realPath, linkPath);
});
- return copyExampleBoilerplate();
+ return buildStyles(copyExampleBoilerplate, done);
});
// copies boilerplate files to locations
// where an example app is found
-gulp.task('_copy-example-boilerplate', function () {
- if (!argv.fast) copyExampleBoilerplate();
+gulp.task('_copy-example-boilerplate', function (done) {
+ if (!argv.fast) buildStyles(copyExampleBoilerplate, done);
});
+//Builds Angular 2 Docs CSS file from Bootstrap npm LESS source
+//and copies the result to the _examples folder to be included as
+//part of the example boilerplate.
+function buildStyles(cb, done){
+ gulp.src(path.join(STYLES_SOURCE_PATH, _styleLessName))
+ .pipe(less())
+ .pipe(gulp.dest(EXAMPLES_PATH)).on('end', function(){
+ cb().then(function() { done(); });
+ });
+}
// copies boilerplate files to locations
// where an example app is found
@@ -581,7 +595,7 @@ gulp.task('build-dart-api-docs', ['_shred-api-examples', 'dartdoc'], function()
});
gulp.task('build-plunkers', ['_copy-example-boilerplate'], function() {
- return plunkerBuilder.buildPlunkers(EXAMPLES_PATH, LIVE_EXAMPLES_PATH, { errFn: gutil.log });
+ return plunkerBuilder.buildPlunkers(EXAMPLES_PATH, LIVE_EXAMPLES_PATH, { errFn: gutil.log, build: argv.build });
});
gulp.task('build-dart-cheatsheet', [], function() {
@@ -1251,7 +1265,7 @@ function buildApiDocsForDart() {
dab.createApiDataAndJadeFiles(apiEntries);
}).catch((err) => {
- console.log(err);
+ console.error(err);
});
} catch(err) {
diff --git a/package.json b/package.json
index e6d82ff58e..2e848d239c 100644
--- a/package.json
+++ b/package.json
@@ -27,11 +27,12 @@
"devDependencies": {
"archiver": "^1.0.0",
"assert-plus": "^1.0.0",
+ "bootstrap": "3.3.6",
"broken-link-checker": "0.7.1",
"browser-sync": "^2.9.3",
"canonical-path": "0.0.2",
"cheerio": "^0.20.0",
- "codelyzer": "0.0.22",
+ "codelyzer": "0.0.26",
"cross-spawn": "^4.0.0",
"del": "^2.2.0",
"dgeni": "^0.4.0",
@@ -43,6 +44,7 @@
"gulp": "^3.5.6",
"gulp-env": "0.4.0",
"gulp-sass": "^2.3.2",
+ "gulp-less": "^3.1.0",
"gulp-task-listing": "^1.0.1",
"gulp-tslint": "^5.0.0",
"gulp-util": "^3.0.6",
diff --git a/public/docs/_examples/animations/ts/app/app.module.ts b/public/docs/_examples/animations/ts/app/app.module.ts
new file mode 100644
index 0000000000..1550034236
--- /dev/null
+++ b/public/docs/_examples/animations/ts/app/app.module.ts
@@ -0,0 +1,33 @@
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+import { HeroTeamBuilderComponent } from './hero-team-builder.component';
+import { HeroListBasicComponent } from './hero-list-basic.component';
+import { HeroListInlineStylesComponent } from './hero-list-inline-styles.component';
+import { HeroListEnterLeaveComponent } from './hero-list-enter-leave.component';
+import { HeroListEnterLeaveStatesComponent } from './hero-list-enter-leave-states.component';
+import { HeroListCombinedTransitionsComponent } from './hero-list-combined-transitions.component';
+import { HeroListTwowayComponent } from './hero-list-twoway.component';
+import { HeroListAutoComponent } from './hero-list-auto.component';
+import { HeroListGroupsComponent } from './hero-list-groups.component';
+import { HeroListMultistepComponent } from './hero-list-multistep.component';
+import { HeroListTimingsComponent } from './hero-list-timings.component';
+
+@NgModule({
+ imports: [ BrowserModule ],
+ declarations: [
+ HeroTeamBuilderComponent,
+ HeroListBasicComponent,
+ HeroListInlineStylesComponent,
+ HeroListCombinedTransitionsComponent,
+ HeroListTwowayComponent,
+ HeroListEnterLeaveComponent,
+ HeroListEnterLeaveStatesComponent,
+ HeroListAutoComponent,
+ HeroListTimingsComponent,
+ HeroListMultistepComponent,
+ HeroListGroupsComponent
+ ],
+ bootstrap: [ HeroTeamBuilderComponent ]
+})
+export class AppModule { }
diff --git a/public/docs/_examples/animations/ts/app/hero-team-builder.component.ts b/public/docs/_examples/animations/ts/app/hero-team-builder.component.ts
index 0ae7ec519e..e5413be50e 100644
--- a/public/docs/_examples/animations/ts/app/hero-team-builder.component.ts
+++ b/public/docs/_examples/animations/ts/app/hero-team-builder.component.ts
@@ -1,16 +1,6 @@
import { Component } from '@angular/core';
import { Heroes } from './hero.service';
-import { HeroListBasicComponent } from './hero-list-basic.component';
-import { HeroListInlineStylesComponent } from './hero-list-inline-styles.component';
-import { HeroListEnterLeaveComponent } from './hero-list-enter-leave.component';
-import { HeroListEnterLeaveStatesComponent } from './hero-list-enter-leave-states.component';
-import { HeroListCombinedTransitionsComponent } from './hero-list-combined-transitions.component';
-import { HeroListTwowayComponent } from './hero-list-twoway.component';
-import { HeroListAutoComponent } from './hero-list-auto.component';
-import { HeroListGroupsComponent } from './hero-list-groups.component';
-import { HeroListMultistepComponent } from './hero-list-multistep.component';
-import { HeroListTimingsComponent } from './hero-list-timings.component';
@Component({
selector: 'hero-team-builder',
@@ -97,18 +87,6 @@ import { HeroListTimingsComponent } from './hero-list-timings.component';
min-height: 6em;
}
`],
- directives: [
- HeroListBasicComponent,
- HeroListInlineStylesComponent,
- HeroListCombinedTransitionsComponent,
- HeroListTwowayComponent,
- HeroListEnterLeaveComponent,
- HeroListEnterLeaveStatesComponent,
- HeroListAutoComponent,
- HeroListTimingsComponent,
- HeroListMultistepComponent,
- HeroListGroupsComponent
- ],
providers: [Heroes]
})
export class HeroTeamBuilderComponent {
diff --git a/public/docs/_examples/animations/ts/app/main.ts b/public/docs/_examples/animations/ts/app/main.ts
index 3c8422e790..2470c9595e 100644
--- a/public/docs/_examples/animations/ts/app/main.ts
+++ b/public/docs/_examples/animations/ts/app/main.ts
@@ -1,5 +1,4 @@
-import { bootstrap } from '@angular/platform-browser-dynamic';
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app.module';
-import { HeroTeamBuilderComponent } from './hero-team-builder.component';
-
-bootstrap(HeroTeamBuilderComponent);
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/public/docs/_examples/architecture/ts/app/app.component.ts b/public/docs/_examples/architecture/ts/app/app.component.ts
index 930cf5f045..b987f17e44 100644
--- a/public/docs/_examples/architecture/ts/app/app.component.ts
+++ b/public/docs/_examples/architecture/ts/app/app.component.ts
@@ -1,16 +1,13 @@
// #docregion import
import { Component } from '@angular/core';
// #enddocregion import
-import { HeroListComponent } from './hero-list.component';
-import { SalesTaxComponent } from './sales-tax.component';
@Component({
selector: 'my-app',
template: `
-
{{comment}}
- `, - directives: [ChildViewComponent] + ` }) // #docregion hooks export class AfterViewComponent implements AfterViewChecked, AfterViewInit { @@ -100,8 +99,7 @@ export class AfterViewComponent implements AfterViewChecked, AfterViewInit {Power: | |
Hero.name: |
+ Welcome, {{user}} +
+ diff --git a/public/docs/_examples/ngmodule/ts/app/shared/title.component.ts b/public/docs/_examples/ngmodule/ts/app/shared/title.component.ts new file mode 100644 index 0000000000..c3f35b5d32 --- /dev/null +++ b/public/docs/_examples/ngmodule/ts/app/shared/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 './user.service'; + +@Component({ + selector: 'app-title', + templateUrl: 'app/shared/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/app/shared/user.service.ts b/public/docs/_examples/ngmodule/ts/app/shared/user.service.ts new file mode 100644 index 0000000000..d32b20b043 --- /dev/null +++ b/public/docs/_examples/ngmodule/ts/app/shared/user.service.ts @@ -0,0 +1,20 @@ +// 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 } from '@angular/core'; + +@Injectable() +export class UserService { + + static userName = ''; + + constructor() { + UserService.userName += UserService.userName || 'Sam Spade'; + } + + get userName() { return UserService.userName; } +} diff --git a/public/docs/_examples/ngmodule/ts/app/title.component.html b/public/docs/_examples/ngmodule/ts/app/title.component.html new file mode 100644 index 0000000000..3db364cd4b --- /dev/null +++ b/public/docs/_examples/ngmodule/ts/app/title.component.html @@ -0,0 +1,10 @@ + + +
+ Welcome, {{user}} +
+ + diff --git a/public/docs/_examples/ngmodule/ts/app/title.component.ts b/public/docs/_examples/ngmodule/ts/app/title.component.ts new file mode 100644 index 0000000000..0edfd4b468 --- /dev/null +++ b/public/docs/_examples/ngmodule/ts/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: 'app/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/app/user.service.ts b/public/docs/_examples/ngmodule/ts/app/user.service.ts new file mode 100644 index 0000000000..cf31db5da5 --- /dev/null +++ b/public/docs/_examples/ngmodule/ts/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 = 'Sam Spade'; +} 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..77804a3be1 --- /dev/null +++ b/public/docs/_examples/ngmodule/ts/contact.1b.plnkr.json @@ -0,0 +1,23 @@ +{ + "description": "Contact NgModule v.1", + "files": [ + "app/app.component.1b.ts", + "app/app.module.1b.ts", + "app/main.1b.ts", + "app/highlight.directive.ts", + "app/title.component.html", + "app/title.component.ts", + "app/user.service.ts", + + "app/contact/*.css", + "app/contact/*.html", + "app/contact/*.ts", + "!app/contact/contact.component.ts", + "!app/contact/contact.module.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..b7da9b879f --- /dev/null +++ b/public/docs/_examples/ngmodule/ts/contact.2.plnkr.json @@ -0,0 +1,24 @@ +{ + "description": "Contact NgModule v.2", + "files": [ + "app/app.component.2.ts", + "app/app.module.2.ts", + "app/main.2.ts", + "app/highlight.directive.ts", + "app/title.component.html", + "app/title.component.ts", + "app/user.service.ts", + + "app/contact/*.css", + "app/contact/*.html", + "app/contact/*.ts", + "!app/contact/contact.component.ts", + "!app/contact/contact.module.ts", + "!app/contact/contact.module.3.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/index.0.html b/public/docs/_examples/ngmodule/ts/index.0.html new file mode 100644 index 0000000000..7deb1e2a5f --- /dev/null +++ b/public/docs/_examples/ngmodule/ts/index.0.html @@ -0,0 +1,26 @@ + + +
++ +New hero: + + + can fly +
++ Mutate array + + + +
+ +Heroes as JSON: {{'heroes.json' | fetch | json}}
- `, + ` // #enddocregion template - pipes: [FetchJsonPipe] }) export class HeroListComponent { } diff --git a/public/docs/_examples/pipes/ts/app/main.ts b/public/docs/_examples/pipes/ts/app/main.ts index dd9994d2b6..3001ee1461 100644 --- a/public/docs/_examples/pipes/ts/app/main.ts +++ b/public/docs/_examples/pipes/ts/app/main.ts @@ -1,6 +1,6 @@ -import { bootstrap } from '@angular/platform-browser-dynamic'; +// #docregion +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import 'rxjs/Rx'; +import { AppModule } from './app.module'; -import { AppComponent } from './app.component'; - -bootstrap(AppComponent); +platformBrowserDynamic().bootstrapModule(AppModule); 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 index 2c97e4a8f6..e65e29ad4c 100644 --- a/public/docs/_examples/pipes/ts/app/power-boost-calculator.component.ts +++ b/public/docs/_examples/pipes/ts/app/power-boost-calculator.component.ts @@ -1,8 +1,6 @@ // #docregion import { Component } from '@angular/core'; -import { ExponentialStrengthPipe } from './exponential-strength.pipe'; - @Component({ selector: 'power-boost-calculator', template: ` @@ -12,8 +10,7 @@ import { ExponentialStrengthPipe } from './exponential-strength.pipe';Super Hero Power: {{power | exponentialStrength: factor}}
- `, - pipes: [ExponentialStrengthPipe] + ` }) export class PowerBoostCalculatorComponent { power = 5; diff --git a/public/docs/_examples/pipes/ts/app/power-booster.component.ts b/public/docs/_examples/pipes/ts/app/power-booster.component.ts index b62e678e90..08e3e24c7b 100644 --- a/public/docs/_examples/pipes/ts/app/power-booster.component.ts +++ b/public/docs/_examples/pipes/ts/app/power-booster.component.ts @@ -1,14 +1,11 @@ // #docregion import { Component } from '@angular/core'; -import { ExponentialStrengthPipe } from './exponential-strength.pipe'; - @Component({ selector: 'power-booster', template: `Super power boost: {{2 | exponentialStrength: 10}}
- `, - pipes: [ExponentialStrengthPipe] + ` }) export class PowerBoosterComponent { } diff --git a/public/docs/_examples/quickstart/js/app/app.module.js b/public/docs/_examples/quickstart/js/app/app.module.js new file mode 100644 index 0000000000..0f3d5f82cf --- /dev/null +++ b/public/docs/_examples/quickstart/js/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/app/main.js b/public/docs/_examples/quickstart/js/app/main.js index 55a77b9ddd..785823fa84 100644 --- a/public/docs/_examples/quickstart/js/app/main.js +++ b/public/docs/_examples/quickstart/js/app/main.js @@ -1,8 +1,8 @@ // #docregion (function(app) { document.addEventListener('DOMContentLoaded', function() { - // #docregion import - ng.platformBrowserDynamic.bootstrap(app.AppComponent); - // #enddocregion import + ng.platformBrowserDynamic + .platformBrowserDynamic() + .bootstrapModule(app.AppModule); }); })(window.app || (window.app = {})); diff --git a/public/docs/_examples/quickstart/js/index.html b/public/docs/_examples/quickstart/js/index.html index a1e88e0461..b127bdce13 100644 --- a/public/docs/_examples/quickstart/js/index.html +++ b/public/docs/_examples/quickstart/js/index.html @@ -27,6 +27,7 @@ + diff --git a/public/docs/_examples/quickstart/js/package.1.json b/public/docs/_examples/quickstart/js/package.1.json index 358034f15e..5b3ecbc847 100644 --- a/public/docs/_examples/quickstart/js/package.1.json +++ b/public/docs/_examples/quickstart/js/package.1.json @@ -7,23 +7,23 @@ }, "license": "ISC", "dependencies": { - "@angular/common": "2.0.0-rc.4", - "@angular/compiler": "2.0.0-rc.4", - "@angular/core": "2.0.0-rc.4", - "@angular/forms": "0.2.0", - "@angular/http": "2.0.0-rc.4", - "@angular/platform-browser": "2.0.0-rc.4", - "@angular/platform-browser-dynamic": "2.0.0-rc.4", - "@angular/router": "3.0.0-beta.1", + "@angular/common": "2.0.0-rc.5", + "@angular/compiler": "2.0.0-rc.5", + "@angular/core": "2.0.0-rc.5", + "@angular/forms": "0.3.0", + "@angular/http": "2.0.0-rc.5", + "@angular/platform-browser": "2.0.0-rc.5", + "@angular/platform-browser-dynamic": "2.0.0-rc.5", + "@angular/router": "3.0.0-rc.1", "@angular/router-deprecated": "2.0.0-rc.2", - "@angular/upgrade": "2.0.0-rc.4", + "@angular/upgrade": "2.0.0-rc.5", "core-js": "^2.4.0", "reflect-metadata": "0.1.3", "rxjs": "5.0.0-beta.6", "zone.js": "0.6.12", - "angular2-in-memory-web-api": "0.0.14", + "angular2-in-memory-web-api": "0.0.15", "bootstrap": "^3.3.6" }, "devDependencies": { diff --git a/public/docs/_examples/quickstart/ts/app/app.module.ts b/public/docs/_examples/quickstart/ts/app/app.module.ts new file mode 100644 index 0000000000..b4fc185c24 --- /dev/null +++ b/public/docs/_examples/quickstart/ts/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/quickstart/ts/app/main.ts b/public/docs/_examples/quickstart/ts/app/main.ts index 2aede345e9..4ad787ebfd 100644 --- a/public/docs/_examples/quickstart/ts/app/main.ts +++ b/public/docs/_examples/quickstart/ts/app/main.ts @@ -1,8 +1,8 @@ // #docregion -import { bootstrap } from '@angular/platform-browser-dynamic'; - // #docregion import -import { AppComponent } from './app.component'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app.module'; // #enddocregion import -bootstrap(AppComponent); +platformBrowserDynamic().bootstrapModule(AppModule); diff --git a/public/docs/_examples/quickstart/ts/package.1.json b/public/docs/_examples/quickstart/ts/package.1.json index ef5d180619..4f0bc098fd 100644 --- a/public/docs/_examples/quickstart/ts/package.1.json +++ b/public/docs/_examples/quickstart/ts/package.1.json @@ -11,16 +11,16 @@ }, "license": "ISC", "dependencies": { - "@angular/common": "2.0.0-rc.4", - "@angular/compiler": "2.0.0-rc.4", - "@angular/core": "2.0.0-rc.4", - "@angular/forms": "0.2.0", - "@angular/http": "2.0.0-rc.4", - "@angular/platform-browser": "2.0.0-rc.4", - "@angular/platform-browser-dynamic": "2.0.0-rc.4", - "@angular/router": "3.0.0-beta.1", + "@angular/common": "2.0.0-rc.5", + "@angular/compiler": "2.0.0-rc.5", + "@angular/core": "2.0.0-rc.5", + "@angular/forms": "0.3.0", + "@angular/http": "2.0.0-rc.5", + "@angular/platform-browser": "2.0.0-rc.5", + "@angular/platform-browser-dynamic": "2.0.0-rc.5", + "@angular/router": "3.0.0-rc.1", "@angular/router-deprecated": "2.0.0-rc.2", - "@angular/upgrade": "2.0.0-rc.4", + "@angular/upgrade": "2.0.0-rc.5", "systemjs": "0.19.27", "core-js": "^2.4.0", @@ -28,7 +28,7 @@ "rxjs": "5.0.0-beta.6", "zone.js": "^0.6.12", - "angular2-in-memory-web-api": "0.0.14", + "angular2-in-memory-web-api": "0.0.15", "bootstrap": "^3.3.6" }, "devDependencies": { diff --git a/public/docs/_examples/quickstart/ts/typings.1.json b/public/docs/_examples/quickstart/ts/typings.1.json index 3385926d1f..3d826df25a 100644 --- a/public/docs/_examples/quickstart/ts/typings.1.json +++ b/public/docs/_examples/quickstart/ts/typings.1.json @@ -2,6 +2,6 @@ "globalDependencies": { "core-js": "registry:dt/core-js#0.0.0+20160602141332", "jasmine": "registry:dt/jasmine#2.2.0+20160621224255", - "node": "registry:dt/node#6.0.0+20160621231320" + "node": "registry:dt/node#6.0.0+20160807145350" } } diff --git a/public/docs/_examples/router-deprecated/e2e-spec.ts b/public/docs/_examples/router-deprecated/e2e-spec.ts.disabled similarity index 100% rename from public/docs/_examples/router-deprecated/e2e-spec.ts rename to public/docs/_examples/router-deprecated/e2e-spec.ts.disabled diff --git a/public/docs/_examples/router/e2e-spec.ts b/public/docs/_examples/router/e2e-spec.ts index ac3e36f4ea..bf672c3f01 100644 --- a/public/docs/_examples/router/e2e-spec.ts +++ b/public/docs/_examples/router/e2e-spec.ts @@ -11,18 +11,18 @@ describe('Router', function () { return { hrefs: hrefEles, - routerParent: element(by.css('my-app > undefined')), - routerTitle: element(by.css('my-app > undefined > h2')), + routerParent: element(by.css('my-app > ng-component')), + routerTitle: element(by.css('my-app > ng-component > 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')), + crisisList: element.all(by.css('my-app > ng-component > ng-component li')), + crisisDetail: element(by.css('my-app > ng-component > ng-component > div')), + crisisDetailTitle: element(by.css('my-app > ng-component > ng-component > 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')), + heroesList: element.all(by.css('my-app > ng-component li')), + heroDetail: element(by.css('my-app > ng-component > div')), + heroDetailTitle: element(by.css('my-app > ng-component > div > h3')), adminHref: hrefEles.get(2), loginHref: hrefEles.get(3) @@ -31,7 +31,7 @@ describe('Router', function () { it('should be able to see the start screen', function () { let page = getPageStruct(); - expect(page.hrefs.count()).toEqual(4, 'should be two dashboard choices'); + expect(page.hrefs.count()).toEqual(4, 'should be 4 dashboard choices'); expect(page.crisisHref.getText()).toEqual('Crisis Center'); expect(page.heroesHref.getText()).toEqual('Heroes'); expect(page.adminHref.getText()).toEqual('Crisis Admin'); @@ -40,7 +40,9 @@ describe('Router', function () { it('should be able to see crises center items', function () { let page = getPageStruct(); - expect(page.crisisList.count()).toBe(4, 'should be 4 crisis center entries at start'); + page.crisisHref.click().then(function() { + expect(page.crisisList.count()).toBe(4, 'should be 4 crisis center entries at start'); + }); }); it('should be able to see hero items', function () { @@ -62,11 +64,17 @@ describe('Router', function () { }); it('should be able to edit and save details from the crisis center view', function () { - crisisCenterEdit(2, true); + let page = getPageStruct(); + page.crisisHref.click().then(function() { + crisisCenterEdit(2, true); + }); }); xit('should be able to edit and cancel details from the crisis center view', function () { - crisisCenterEdit(3, false); + let page = getPageStruct(); + page.crisisHref.click().then(function() { + crisisCenterEdit(3, false); + }); }); it('should be able to edit and save details from the heroes view', function () { diff --git a/public/docs/_examples/router/ts/app/app.component.1.ts b/public/docs/_examples/router/ts/app/app.component.1.ts index e124b6771a..1b0aba0044 100644 --- a/public/docs/_examples/router/ts/app/app.component.1.ts +++ b/public/docs/_examples/router/ts/app/app.component.1.ts @@ -1,10 +1,6 @@ /* First version */ -// #docplaster // #docregion import { Component } from '@angular/core'; -// #docregion import-router -import { ROUTER_DIRECTIVES } from '@angular/router'; -// #enddocregion import-router @Component({ selector: 'my-app', @@ -16,11 +12,7 @@ import { ROUTER_DIRECTIVES } from '@angular/router'; HeroesManage your crises here
- `, - directives: [] + ` }) export class CrisisAdminComponent { } diff --git a/public/docs/_examples/router/ts/app/crisis-center/crisis-admin.component.ts b/public/docs/_examples/router/ts/app/crisis-center/crisis-admin.component.ts index 9783466d4c..38fe14a38e 100755 --- a/public/docs/_examples/router/ts/app/crisis-center/crisis-admin.component.ts +++ b/public/docs/_examples/router/ts/app/crisis-center/crisis-admin.component.ts @@ -1,7 +1,7 @@ // #docregion -import { Component, OnInit } from '@angular/core'; -import { Router } from '@angular/router'; -import { Observable } from 'rxjs/Observable'; +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { Observable } from 'rxjs/Observable'; import 'rxjs/add/operator/map'; @Component({ @@ -12,25 +12,22 @@ import 'rxjs/add/operator/map';Session ID: {{ sessionId | async }}
Token: {{ token | async }}
- `, - directives: [] + ` }) export class CrisisAdminComponent implements OnInit { sessionId: Observable{{message}}
++ + +
` +}) +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/app/login.component.ts b/public/docs/_examples/router/ts/app/login.component.ts index ddee339011..6dd5605fb1 100755 --- a/public/docs/_examples/router/ts/app/login.component.ts +++ b/public/docs/_examples/router/ts/app/login.component.ts @@ -1,7 +1,8 @@ // #docregion -import { Component } from '@angular/core'; -import { Router } from '@angular/router'; -import { AuthService } from './auth.service'; +import { Component } from '@angular/core'; +import { Router, + NavigationExtras } from '@angular/router'; +import { AuthService } from './auth.service'; @Component({ template: ` @@ -33,8 +34,17 @@ export class LoginComponent { // If no redirect has been set, use the default let redirect = this.authService.redirectUrl ? this.authService.redirectUrl : '/crisis-center/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]); + this.router.navigate([redirect], navigationExtras); + // #enddocregion preserve } }); } diff --git a/public/docs/_examples/router/ts/app/login.routes.ts b/public/docs/_examples/router/ts/app/login.routes.ts deleted file mode 100644 index 8bfc1ff10d..0000000000 --- a/public/docs/_examples/router/ts/app/login.routes.ts +++ /dev/null @@ -1,11 +0,0 @@ -// #docregion -import { RouterConfig } from '@angular/router'; -import { AuthGuard } from './auth-guard.service'; -import { AuthService } from './auth.service'; -import { LoginComponent } from './login.component'; - -export const loginRoutes: RouterConfig = [ - { path: 'login', component: LoginComponent } -]; - -export const authProviders = [AuthGuard, AuthService]; diff --git a/public/docs/_examples/router/ts/app/login.routing.ts b/public/docs/_examples/router/ts/app/login.routing.ts new file mode 100644 index 0000000000..9e3eaf2350 --- /dev/null +++ b/public/docs/_examples/router/ts/app/login.routing.ts @@ -0,0 +1,14 @@ +// #docregion +import { Routes } from '@angular/router'; +import { AuthGuard } from './auth-guard.service'; +import { AuthService } from './auth.service'; +import { LoginComponent } from './login.component'; + +export const loginRoutes: Routes = [ + { path: 'login', component: LoginComponent } +]; + +export const authProviders = [ + AuthGuard, + AuthService +]; 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 deff5b9ac5..0000000000 --- a/public/docs/_examples/router/ts/app/main.1.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* First version */ -// #docplaster -// #docregion all -// main entry point -import { bootstrap } from '@angular/platform-browser-dynamic'; -import { AppComponent } from './app.component'; -import { appRouterProviders } from './app.routes'; - -// #enddocregion - -/* 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.ts'; // './app.component.1'; - -bootstrap(ac, [ -// #docregion all - appRouterProviders -]) -.catch(err => console.error(err)); -// #enddocregion all 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 10e4e4b18a..0000000000 --- a/public/docs/_examples/router/ts/app/main.2.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* Second version */ -// For Milestone #2 -// Also includes digression on HashPathStrategy (not used in the final app) -// #docplaster -// #docregion -// main entry point -import { bootstrap } from '@angular/platform-browser-dynamic'; - -// Add these symbols to override the `LocationStrategy` -import { LocationStrategy, - HashLocationStrategy } from '@angular/common'; - -import { AppComponent } from './app.component'; -import { appRouterProviders } from './app.routes'; - -// #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.ts'; // './app.component.2'; - -bootstrap(ac, [ -// #docregion - appRouterProviders, - { provide: LocationStrategy, useClass: HashLocationStrategy } // .../#/crisis-center/ - -]) -.catch(err => console.error(err)); -// #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 e1be742421..0000000000 --- a/public/docs/_examples/router/ts/app/main.3.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* third version */ -// #docregion -// main entry point -import { bootstrap } from '@angular/platform-browser-dynamic'; -import { AppComponent } from './app.component.3'; -import { appRouterProviders } from './app.routes'; - -bootstrap(AppComponent, [ - appRouterProviders -]) -.catch(err => console.error(err)); diff --git a/public/docs/_examples/router/ts/app/main.ts b/public/docs/_examples/router/ts/app/main.ts index 6142cad5ee..ba9421d573 100644 --- a/public/docs/_examples/router/ts/app/main.ts +++ b/public/docs/_examples/router/ts/app/main.ts @@ -1,10 +1,6 @@ // #docregion -// main entry point -import { bootstrap } from '@angular/platform-browser-dynamic'; -import { AppComponent } from './app.component'; -import { appRouterProviders } from './app.routes'; +import { browserDynamicPlatform } from '@angular/platform-browser-dynamic'; -bootstrap(AppComponent, [ - appRouterProviders -]) -.catch(err => console.error(err)); +import { AppModule } from './app.module'; + +browserDynamicPlatform().bootstrapModule(AppModule); diff --git a/public/docs/_examples/router/ts/plnkr.json b/public/docs/_examples/router/ts/plnkr.json index 73d83adaf6..83b1913f0e 100644 --- a/public/docs/_examples/router/ts/plnkr.json +++ b/public/docs/_examples/router/ts/plnkr.json @@ -3,10 +3,11 @@ "files":[ "!**/*.d.ts", "!**/*.js", - "!**/*.[1,2,3,4,5].*", + "!**/*.[1,2,3,4,5,6].*", "!app/crisis-list.component.ts", "!app/hero-list.component.ts", - "!app/crisis-center/add-crisis.component.ts" + "!app/crisis-center/add-crisis.component.ts", + "!app/not-found.component.ts" ], "tags": ["router"] } diff --git a/public/docs/_examples/security/ts/app/app.component.ts b/public/docs/_examples/security/ts/app/app.component.ts index a2fc7e7320..c30235e8e7 100644 --- a/public/docs/_examples/security/ts/app/app.component.ts +++ b/public/docs/_examples/security/ts/app/app.component.ts @@ -1,20 +1,13 @@ // #docregion import { Component } from '@angular/core'; -import { BypassSecurityComponent } from './bypass-security.component'; -import { InnerHtmlBindingComponent } from './inner-html-binding.component'; - @Component({ selector: 'my-app', template: ``.
+ But what are `*ngFor`, `{{hero.name}}`, `(click)`, `[hero]`, and ` Metadata tells Angular how to process a class. ` element will be the attribute **host**.
+p
+ | We'll put the template in its own
+ code #[+adjExPath('app.component.html')]
+ | file that looks like this:
++makeExample('attribute-directives/ts/app/app.component.1.html',null,'app/app.component.html')(format=".")
+:marked
+ A separate template file is clearly overkill for a 2-line template.
+ Hang in there; we're going to expand it later.
+ Meanwhile, we'll revise the `AppComponent` to reference this template.
++makeExample('attribute-directives/ts/app/app.component.ts',null,'app/app.component.ts')
+:marked
+ We've added an `import` statement to fetch the 'Highlight' directive and,
+ added that class to a `directives` component metadata so that Angular
+ will recognize our directive when it encounters `myHighlight` in the template.
+
+ We run the app and see that our directive highlights the paragraph text.
+
+figure.image-display
+ img(src="/resources/images/devguide/attribute-directives/first-highlight.png" alt="First Highlight")
+.l-sub-section
+ :marked
+ ### Your directive isn't working?
+
+ Did you remember to set the `directives` attribute of `@Component`? It is easy to forget!
+
+ Open the console in the browser tools and look for an error like this:
+ code-example(format="nocode").
+ EXCEPTION: Template parse errors:
+ Can't bind to 'myHighlight' since it isn't a known native property
+ :marked
+ Angular detects that we're trying to bind to *something* but it doesn't know what.
+ We have to tell it by listing `HighlightDirective` in the `directives` metadata array.
+:marked
+ Let's recap what happened.
+
+ Angular found the `myHighlight` attribute on the ` ` element. It created
+ an instance of the `HighlightDirective` class,
+ injecting a reference to the element into the constructor
+ where we set the ` ` element's background style to yellow.
+
+.l-main-section
+a#respond-to-user
+:marked
+ ## Respond to user action
+
+ We are not satisfied to simply set an element color.
+ Our directive should set the color in response to a user action.
+ Specifically, we want to set the color when the user hovers over an element.
+
+ We'll need to
+ 1. detect when the user hovers into and out of the element,
+ 2. respond to those actions by setting and clearing the highlight color, respectively.
+
+ We apply the `@HostListener` !{_decorator} to methods which are called when an event is raised.
+
++makeExample('attribute-directives/ts/app/highlight.directive.2.ts','host')(format=".")
+
+.l-sub-section
+ :marked
+ The `@HostListener` !{_decorator} refers to the DOM element that hosts our attribute directive, the ` ` in our case.
+
+ We could have attached event listeners by manipulating the host DOM element directly, but
+ there are at least three problems with such an approach:
+
+ 1. We have to write the listeners correctly.
+ 1. We must *detach* our listener when the directive is destroyed to avoid memory leaks.
+ 1. We'd be talking to DOM API directly which, we learned, is something to avoid.
+
+ Let's roll with the `@HostListener` !{_decorator}.
+:marked
+ Now we implement the two mouse event handlers:
++makeExample('attribute-directives/ts/app/highlight.directive.2.ts','mouse-methods')(format=".")
+:marked
+ Notice that they delegate to a helper method that sets the color via a private local variable, `#{_priv}el`.
+ We revise the constructor to capture the `ElementRef.nativeElement` in this variable.
+
++makeExample('attribute-directives/ts/app/highlight.directive.2.ts','ctor')(format=".")
+:marked
+ Here's the updated directive:
++makeExample('app/highlight.directive.2.ts')
+:marked
+ We run the app and confirm that the background color appears as we move the mouse over the `p` and
+ disappears as we move out.
+figure.image-display
+ img(src="/resources/images/devguide/attribute-directives/highlight-directive-anim.gif" alt="Second Highlight")
+.l-main-section
+a#bindings
+:marked
+ ## Configure the directive with binding
+
+ Currently the highlight color is hard-coded within the directive. That's inflexible.
+ We should set the color externally with a binding like this:
++makeExample('attribute-directives/ts/app/app.component.html','pHost')
+:marked
+ We'll extend our directive class with a bindable **input** `highlightColor` property and use it when we highlight text.
+
+ Here is the final version of the class:
++makeExcerpt('app/highlight.directive.ts', 'class')
+a#input
+:marked
+ The new `highlightColor` property is called an *input* property because data flows from the binding expression into our directive.
+ Notice the `@Input()` #{_decorator} applied to the property.
++makeExcerpt('app/highlight.directive.ts', 'color')
+:marked
+ `@Input` adds metadata to the class that makes the `highlightColor` property available for
+ property binding under the `myHighlight` alias.
+ We must add this input metadata or Angular will reject the binding.
+ See the [appendix](#why-input) below to learn why.
+.l-sub-section
+ :marked
+ ### @Input(_alias_)
+ The developer who uses this directive expects to bind to the attribute name, `myHighlight`.
+ The directive property name is `highlightColor`. That's a disconnect.
+
+ We could resolve the discrepancy by renaming the property to `myHighlight` and define it as follows:
+
+ +makeExcerpt('app/highlight.directive.ts', 'highlight', '')
+ :marked
+ Maybe we don't want that property name inside the directive perhaps because it
+ doesn't express our intention well.
+ We can **alias** the `highlightColor` property with the attribute name by
+ passing `myHighlight` into the `@Input` #{_decorator}:
+ +makeExcerpt('app/highlight.directive.ts', 'color', '')
+:marked
+ Now that we're getting the highlight color as an input, we modify the `onMouseEnter()` method to use
+ it instead of the hard-coded color name.
+ We also define red as the default color to fallback on in case
+ the user neglects to bind with a color.
++makeExcerpt('attribute-directives/ts/app/highlight.directive.ts', 'mouse-enter', '')
+:marked
+ Now we'll update our `AppComponent` template to let
+ users pick the highlight color and bind their choice to our directive.
+
+ Here is the updated template:
++makeExcerpt('attribute-directives/ts/app/app.component.html', 'v2', '')
+
+.l-sub-section
+ :marked
+ ### Where is the templated *color* property?
+
+ The eagle-eyed may notice that the radio button click handlers in the template set a `color` property
+ and we are binding that `color` to the directive.
+ We should expect to find a `color` on the host `AppComponent`.
+
+ **We never defined a color property for the host *AppComponent***!
+ And yet this code works. Where is the template `color` value going?
+
+ Browser debugging reveals that Angular dynamically added a `color` property
+ to the runtime instance of the `AppComponent`.
+
+ This is *convenient* behavior but it is also *implicit* behavior that could be confusing.
+ While it's cool that this technique works, we recommend adding the `color` property to the `AppComponent`.
+
+:marked
+ Here is our second version of the directive in action.
+figure.image-display
+ img(src="/resources/images/devguide/attribute-directives/highlight-directive-v2-anim.gif" alt="Highlight v.2")
+
+.l-main-section
+:marked
+ ## Bind to a second property
+ Our directive only has a single, customizable property. What if we had ***two properties***?
+
+ Let's allow the template developer to set the default color, the color that prevails until the user picks a highlight color.
+ We'll add a second **input** property to `HighlightDirective` called `defaultColor`:
++makeExample('attribute-directives/ts/app/highlight.directive.ts', 'defaultColor')(format=".")
+:marked
+ The `defaultColor` property has a setter that overrides the hard-coded default color, "red".
+ We don't need a getter.
+
+ How do we bind to it? We already "burned" the `myHighlight` attribute name as a binding target.
+
+ Remember that a *component is a directive too*.
+ We can add as many component property bindings as we need by stringing them along in the template
+ as in this example that sets the `a`, `b`, `c` properties to the string literals 'a', 'b', and 'c'.
+code-example(format="." ).
+ <my-component [a]="'a'" [b]="'b'" [c]="'c'"><my-component>
+:marked
+ We do the same thing with an attribute directive.
++makeExample('attribute-directives/ts/app/app.component.html', 'defaultColor')(format=".")
+:marked
+ Here we're binding the user's color choice to the `myHighlight` attribute as we did before.
+ We're *also* binding the literal string, 'violet', to the `defaultColor`.
+
+ Here is the final version of the directive in action.
+figure.image-display
+ img(src="/resources/images/devguide/attribute-directives/highlight-directive-final-anim.gif" alt="Final Highlight")
+
+.l-main-section
+:marked
+ ## Summary
+ We now know how to
+ - [build a simple **attribute directive** to attach behavior to an HTML element](#write-directive),
+ - [use that directive in a template](#apply-directive),
+ - [respond to **events** to change behavior based on an event](#respond-to-user),
+ - and [use **binding** to pass values to the attribute directive](#bindings).
+
+ The final source:
+
++makeTabs(
+ `attribute-directives/ts/app/app.component.ts,
+ attribute-directives/ts/app/app.component.html,
+ attribute-directives/ts/app/highlight.directive.ts,
+ attribute-directives/ts/app/main.ts,
+ attribute-directives/ts/index.html
+ `,
+ ',,full',
+ `app.component.ts,
+ app.component.html,
+ highlight.directive.ts,
+ main.ts,
+ index.html
+ `)
+
+
+a#why-input
+.l-main-section
+:marked
+ ### Appendix: Input properties
+
+ Earlier we declared the `highlightColor` property to be an ***input*** property of our
+ `HighlightDirective`
+
+ We've seen properties in bindings before.
+ We never had to declare them as anything. Why now?
+
+ Angular makes a subtle but important distinction between binding **sources** and **targets**.
+
+ In all previous bindings, the directive or component property was a binding ***source***.
+ A property is a *source* if it appears in the template expression to the ***right*** of the equals (=).
+
+ A property is a *target* when it appears in **square brackets** ([ ]) to the **left** of the equals (=) ...
+ as it is does when we bind to the `myHighlight` property of the `HighlightDirective`,
++makeExample('attribute-directives/ts/app/app.component.html','pHost')(format=".")
+:marked
+ The 'color' in `[myHighlight]="color"` is a binding ***source***.
+ A source property doesn't require a declaration.
+
+ The 'myHighlight' in `[myHighlight]="color"` *is* a binding ***target***.
+ We must declare it as an *input* property.
+ Angular rejects the binding with a clear error if we don't.
+
+ Angular treats a *target* property differently for a good reason.
+ A component or directive in target position needs protection.
+
+ Imagine that our `HighlightDirective` did truly wonderous things.
+ We graciously made a gift of it to the world.
+
+ To our surprise, some people — perhaps naively —
+ started binding to *every* property of our directive.
+ Not just the one or two properties we expected them to target. *Every* property.
+ That could really mess up our directive in ways we didn't anticipate and have no desire to support.
+
+ The *input* declaration ensures that consumers of our directive can only bind to
+ the properties of our public API ... nothing else.
diff --git a/public/docs/ts/_cache/guide/component-styles.jade b/public/docs/ts/_cache/guide/component-styles.jade
new file mode 100644
index 0000000000..c87e746a8e
--- /dev/null
+++ b/public/docs/ts/_cache/guide/component-styles.jade
@@ -0,0 +1,319 @@
+block includes
+ include ../_util-fns
+
+:marked
+ Angular 2 applications are styled with regular CSS. That means we can apply
+ everything we know about CSS stylesheets, selectors, rules, and media queries
+ to our Angular applications directly.
+
+ On top of this, Angular has the ability to bundle *component styles*
+ with our components enabling a more modular design than regular stylesheets.
+
+ In this chapter we learn how to load and apply these *component styles*.
+
+ # Table Of Contents
+
+ * [Using Component Styles](#using-component-styles)
+ * [Special selectors](#special-selectors)
+ * [Loading Styles into Components](#loading-styles)
+ * [Controlling View Encapsulation: Emulated, Native, and None](#view-encapsulation)
+ * [Appendix 1: Inspecting the generated runtime component styles](#inspect-generated-css)
+ * [Appendix 2: Loading Styles with Relative URLs](#relative-urls)
+
+ Run the
+
+.l-main-section
+:marked
+ ## Metadata
+figure
+ img(src="/resources/images/devguide/architecture/metadata.png" alt="Metadata" align="left" style="width:150px; margin-left:-40px;margin-right:10px" )
+
+:marked
+
+:marked
+ [Looking back at the code](#component-code) for `HeroListComponent`, we see that it's just a class.
+ There is no evidence of a framework, no "Angular" in it at all.
+
+ In fact, it really is *just a class*. It's not a component until we *tell Angular about it*.
+
+ We tell Angular that `HeroListComponent` is a component by attaching **metadata** to the class.
+
+ In !{_Lang}, we attach metadata by using !{_a} **!{_decorator}**.
+ Here's some metadata for `HeroListComponent`:
+
++makeExcerpt('app/hero-list.component.ts', 'metadata')
+
+:marked
+ Here we see the `@Component` !{_decorator} which (no surprise) identifies the class
+ immediately below it as a component class.
+
+block ts-decorator
+ :marked
+ A decorator is a function. Decorators often have a configuration parameter.
+ The `@Component` decorator takes a required configuration object with the
+ information Angular needs to create and present the component and its view.
+
+ Here are a few of the possible `@Component` configuration options:
+
+:marked
+ - `selector`: CSS selector that tells Angular to create and insert an instance of this component
+ where it finds a `
+:marked
+ The architectural takeaway is that we must add metadata to our code
+ so that Angular knows what to do.
+
+.l-main-section
+:marked
+ ## Data binding
+ Without a framework, we would be responsible for pushing data values into the HTML controls and turning user responses
+ into actions and value updates. Writing such push/pull logic by hand is tedious, error-prone, and a nightmare to
+ read as any experienced jQuery programmer can attest.
+figure
+ img(src="/resources/images/devguide/architecture/databinding.png" alt="Data Binding" style="width:220px; float:left; margin-left:-40px;margin-right:20px" )
+:marked
+ Angular supports **data binding**,
+ a mechanism for coordinating parts of a template with parts of a component.
+ We add binding markup to the template HTML to tell Angular how to connect both sides.
+
+ There are four forms of data binding syntax. Each form has a direction — to the DOM, from the DOM, or in both directions —
+ as indicated by the arrows in the diagram.
+
+:marked
+ We saw three forms of data binding in our [example](#templates) template:
+
++makeExcerpt('app/hero-list.component.1.html', 'binding')
+
+:marked
+ * The `{{hero.name}}` [*interpolation*](displaying-data.html#interpolation)
+ displays the component's `hero.name` property value within the `
+figure
+ img(src="/resources/images/devguide/architecture/parent-child-binding.png" alt="Parent/Child binding" style="float:left; width:300px; margin-left:-40px;margin-right:10px" )
+:marked
+ Data binding is also important for communication between parent and child components.
+
+
+.l-main-section
+:marked
+ ## Directives
+figure
+ img(src="/resources/images/devguide/architecture/directive.png" alt="Parent child" style="float:left; width:150px; margin-left:-40px;margin-right:10px" )
+:marked
+ Angular templates are *dynamic*. When Angular renders them, it transforms the DOM
+ according to the instructions given by **directives**.
+
+ A directive is a class with directive metadata. In !{_Lang} we apply the `@Directive` !{_decorator}
+ to attach metadata to the class.
+
+:marked
+ We already met one form of directive: the component. A component is a *directive-with-a-template*;
+ a `@Component` !{_decorator} is actually a `@Directive` !{_decorator} extended with template-oriented features.
+
+.l-sub-section
+ :marked
+ While **a component is technically a directive**,
+ components are so distinctive and central to Angular applications that we chose
+ to separate components from directives in this architectural overview.
+:marked
+ Two *other* kinds of directives exist: _structural_ and _attribute_ directives.
+
+ They tend to appear within an element tag as attributes do,
+ sometimes by name but more often as the target of an assignment or a binding.
+
+ **Structural** directives alter layout by adding, removing, and replacing elements in DOM.
+
+ Our [example](#templates) template uses two built-in structural directives:
+
++makeExcerpt('app/hero-list.component.1.html', 'structural')
+
+:marked
+ * [`*ngFor`](displaying-data.html#ngFor) tells Angular to stamp out one `
+:marked
+ Examples include:
+ * logging service
+ * data service
+ * message bus
+ * tax calculator
+ * application configuration
+
+ There is nothing specifically _Angular_ about services. Angular itself has no definition of a service.
+ There is no service base class, and no place to register a service.
+
+ Yet services are fundamental to any Angular application. Our components are big consumers of services.
+
+ Here's an example of a service class that logs to the browser console
+
++makeExcerpt('app/logger.service.ts', 'class')
+
+:marked
+ Here's a `HeroService` that fetches heroes and returns them in a resolved !{_PromiseLinked}.
+ The `HeroService` depends on the `Logger` service and another `BackendService` that handles the server communication grunt work.
+
++makeExcerpt('app/hero.service.ts', 'class')
+
+:marked
+ Services are everywhere.
+
+ We prefer our component classes lean. Our components don't fetch data from the server,
+ they don't validate user input, and they don't log directly to the console.
+ They delegate such tasks to services.
+
+ A component's job is to enable the user experience and nothing more. It mediates between the view (rendered by the template)
+ and the application logic (which often includes some notion of a _model_).
+ A good component presents properties and methods for data binding.
+ It delegates everything nontrivial to services.
+
+ Angular doesn't *enforce* these principles.
+ It won't complain if we write a "kitchen sink" component with 3000 lines.
+
+ Angular does help us *follow* these principles by making it easy to factor our
+ application logic into services and make those services available to components through *dependency injection*.
+
+.l-main-section
+:marked
+ ## Dependency injection
+figure
+ img(src="/resources/images/devguide/architecture/dependency-injection.png" alt="Service" style="float:left; width:200px; margin-left:-40px;margin-right:10px" )
+:marked
+ _Dependency injection_ is a way to supply a new instance of a class
+ with the fully-formed dependencies it requires. Most dependencies are services.
+ Angular uses dependency injection to provide new components with the services they need.
+
+:marked
+ Angular can tell which services a component needs by looking at the types of its constructor parameters.
+ For example, the constructor of our `HeroListComponent` needs a `HeroService`:
+
++makeExcerpt('app/hero-list.component.ts (constructor)', 'ctor')
+
+:marked
+ When Angular creates a component, it first asks an **injector** for
+ the services that the component requires.
+
+ An injector maintains a container of service instances that it has previously created.
+ If a requested service instance is not in the container, the injector makes one and adds it to the container
+ before returning the service to Angular.
+ When all requested services have been resolved and returned,
+ Angular can call the component's constructor with those services as arguments.
+ This is what we mean by *dependency injection*.
+
+ The process of `HeroService` injection looks a bit like this:
+figure
+ img(src="/resources/images/devguide/architecture/injector-injects.png" alt="Service" )
+:marked
+ If the injector doesn't have a `HeroService`, how does it know how to make one?
+
+ In brief, we must have previously registered a **provider** of the `HeroService` with the injector.
+ A provider is something that can create or return a service, typically the service class itself.
+
+ We can register providers at any level of the application component tree.
+ We often do so at the root when we bootstrap the application so that
+ the same instance of a service is available everywhere.
+
++makeExcerpt('app/main.ts', 'bootstrap')
+
+:marked
+ Alternatively, we might register at a component level, in the providers property of the `@Component` metadata:
+
++makeExcerpt('app/hero-list.component.ts', 'providers')
+
+:marked
+ Registering at a component level means we get a new instance of the
+ service with each new instance of that component.
+
+
+
+ Points to remember about dependency injection:
+
+ * Dependency injection is wired into the Angular framework and used everywhere.
+
+ * The *injector* is the main mechanism.
+ * An injector maintains a *container* of service instances that it created.
+ * An injector can create a new service instance from a *provider*.
+
+ * A *provider* is a recipe for creating a service.
+
+ * We register *providers* with injectors.
+
+.l-main-section
+:marked
+ ## Wrap up
+
+ We've learned just a bit about the eight main building blocks of an Angular application:
+
+ 1. [Modules](#modules)
+ 1. [Components](#components)
+ 1. [Templates](#templates)
+ 1. [Metadata](#metadata)
+ 1. [Data binding](#data-binding)
+ 1. [Directives](#directives)
+ 1. [Services](#services)
+ 1. [Dependency injection](#dependency-injection)
+
+ That's a foundation for everything else in an Angular application,
+ and it's more than enough to get going.
+ But it doesn't include everything we'll need or want to know.
+
+ Here is a brief, alphabetical list of other important Angular features and services.
+ Most of them are covered in this Developers Guide (or soon will be).
+
+ > [**Animations**](animations.html): The animation library makes it easy for developers to animate component behavior
+ without deep knowledge of animation techniques or CSS.
+
+ > **Bootstrap**: A method to configure and launch the root application component.
+
+ > **Change detection**: Learn how Angular decides that a component property value has changed and
+ when to update the screen.
+ Learn how it uses **zones** to intercept asynchronous activity and run its change detection strategies.
+
+ > **Component router**: With the component Router service, users can navigate a multi-screen application
+ in a familiar web browsing style using URLs.
+
+ > **Events**: The DOM raises events. So can components and services. Angular offers mechanisms for
+ publishing and subscribing to events.
+
+ > [**Forms**](forms.html): Support complex data entry scenarios with HTML-based validation and dirty checking.
+
+ > [**HTTP**](server-communication.html): Communicate with a server to get data, save data, and invoke server-side actions with an HTTP client.
+
+ > [**Lifecycle hooks**](lifecycle-hooks.html): We can tap into key moments in the lifetime of a component, from its creation to its destruction,
+ by implementing the lifecycle hook interfaces.
+
+ > [**Pipes**](pipes.html): Services that transform values for display.
+ We can put pipes in our templates to improve the user experience. Consider
+ this `currency` pipe expression:
+` tag
+ in the template of `HeroAppComponent`. Any `
` elements elsewhere in
+ the application are unaffected.
+
+ This is a big improvement in modularity compared to how CSS traditionally works:
+
+ 1. We can use the CSS class names and selectors that make the most sense in the context of each component.
+
+ 1. Class names and selectors are local to the component and won't collide with
+ classes and selectors used elsewhere in the application.
+
+ 1. Our component's styles *cannot* be changed by changes to styles elsewhere in the application.
+
+ 1. We can co-locate the CSS code of each component with the TypeScript and HTML code of the component,
+ which leads to a neat and tidy project structure.
+
+ 1. We can change or remove component CSS code in the future without trawling through the
+ whole application to see where else it may have been used. We just look at the component we're in.
+
+a(id="special-selectors")
+.l-main-section
+:marked
+ ## Special selectors
+
+ Component styles have a few special *selectors* from the world of
+ [shadow DOM style scoping](https://www.w3.org/TR/css-scoping-1):
+
+ ### :host
+
+ Use the `:host` pseudo-class selector to target styles in the element that *hosts* the component (as opposed to
+ targeting elements *inside* the component's template):
+
++makeExample('component-styles/ts/app/hero-details.component.css', 'host')(format='.')
+
+:marked
+ This is the *only* way we can target the host element. We cannot reach
+ it from inside the component with other selectors, because it is not part of the
+ component's own template. It is in a parent component's template.
+
+ Use the *function form* to apply host styles conditionally by
+ including another selector inside parentheses after `:host`.
+
+ In the next example we target the host element again, but only when it also has the `active` CSS class.
+
++makeExample('component-styles/ts/app/hero-details.component.css', 'hostfunction')(format=".")
+
+:marked
+ ### :host-context
+
+ Sometimes it is useful to apply styles based on some condition *outside* a component's view.
+ For example, there may be a CSS theme class applied to the document `` element, and
+ we want to change how our component looks based on that.
+
+ Use the `:host-context()` pseudo-class selector. It works just like the function
+ form of `:host()`. It looks for a CSS class in *any ancestor* of the component host element, all the way
+ up to the document root. It's useful when combined with another selector.
+
+ In the following example, we apply a `background-color` style to all `
` elements *inside* the component, only
+ if some ancestor element has the CSS class `theme-light`.
+
++makeExample('component-styles/ts/app/hero-details.component.css', 'hostcontext')(format='.')
+
+:marked
+ ### /deep/
+
+ Component styles normally apply only to the HTML in the component's own template.
+
+ We can use the `/deep/` selector to force a style down through the child component tree into all the child component views.
+ The `/deep/` selector works to any depth of nested components, and it applies *both to the view
+ children and the content children* of the component.
+
+ In this example, we target all `
` elements, from the host element down
+ through this component to all of its child elements in the DOM:
++makeExample('component-styles/ts/app/hero-details.component.css', 'deep')(format=".")
+
+:marked
+ The `/deep/` selector also has the alias `>>>`. We can use either of the two interchangeably.
+
+.alert.is-important
+ :marked
+ The `/deep/` and `>>>` selectors should only be used with **emulated** view encapsulation.
+ This is the default and it is what we use most of the time. See the
+ [Controlling View Encapsulation](#view-encapsulation)
+ section for more details.
+
+a(id='loading-styles')
+.l-main-section
+:marked
+ ## Loading Styles into Components
+
+ We have several ways to add styles to a component:
+ * inline in the template HTML
+ * by setting `styles` or `styleUrls` metadata
+ * with CSS imports
+
+ The scoping rules outlined above apply to each of these loading patterns.
+
+ ### Styles in Metadata
+
+ We can add a `styles` #{_array} property to the `@Component` #{_decorator}.
+ Each string in the #{_array} (usually just one string) defines the CSS.
+
++makeExample('component-styles/ts/app/hero-app.component.ts')
+
+:marked
+ ### Template Inline Styles
+
+ We can embed styles directly into the HTML template by putting them
+ inside `