feat(cb-ts-to-js): add es6 examples

update docshredder to shred .es6
optimized focus gulp task
convert imports and metadate sections
add DI section
add host and query metadata section
add intro
fix capitalization and grammar
This commit is contained in:
Filipe Silva 2016-10-13 17:59:00 +01:00 committed by Ward Bell
parent 64a8754386
commit 12eb19fa3c
48 changed files with 1440 additions and 416 deletions

View File

@ -247,15 +247,16 @@ function findAndRunE2eTests(filter, outputFile) {
e2eSpecPaths.forEach(function(specPath) { e2eSpecPaths.forEach(function(specPath) {
// get all of the examples under each dir where a pcFilename is found // get all of the examples under each dir where a pcFilename is found
localExamplePaths = getExamplePaths(specPath, true); localExamplePaths = getExamplePaths(specPath, true);
// Filter by language // Filter by example name
localExamplePaths = localExamplePaths.filter(function (fn) {
return fn.match('/'+lang+'$') != null;
});
if (filter) { if (filter) {
localExamplePaths = localExamplePaths.filter(function (fn) { localExamplePaths = localExamplePaths.filter(function (fn) {
return fn.match(filter) != null; return fn.match(filter) != null;
}) })
} }
// Filter by language, also supports variations like js-es6
localExamplePaths = localExamplePaths.filter(function (fn) {
return fn.match('/'+lang+'(?:-[^/]*)?$') != null;
});
localExamplePaths.forEach(function(examplePath) { localExamplePaths.forEach(function(examplePath) {
examplePaths.push(examplePath); examplePaths.push(examplePath);
}) })
@ -1270,7 +1271,7 @@ function apiExamplesWatch(postShredAction) {
} }
function devGuideExamplesWatch(shredOptions, postShredAction, focus) { function devGuideExamplesWatch(shredOptions, postShredAction, focus) {
var watchPattern = focus ? '**/{' + focus + ',cb-' + focus+ '}/**/*.*' : '**/*.*'; var watchPattern = focus ? '{' + focus + ',cb-' + focus+ '}/**/*.*' : '**/*.*';
var includePattern = path.join(shredOptions.examplesDir, watchPattern); var includePattern = path.join(shredOptions.examplesDir, watchPattern);
// removed this version because gulp.watch has the same glob issue that dgeni has. // removed this version because gulp.watch has the same glob issue that dgeni has.
// var excludePattern = '!' + path.join(shredOptions.examplesDir, '**/node_modules/**/*.*'); // var excludePattern = '!' + path.join(shredOptions.examplesDir, '**/node_modules/**/*.*');

View File

@ -11,6 +11,7 @@ wallaby.js
_test-output _test-output
**/ts/**/*.js **/ts/**/*.js
**/js-es6*/**/*.js
**/ts-snippets/**/*.js **/ts-snippets/**/*.js
*.d.ts *.d.ts

View File

@ -18,6 +18,7 @@
"build:webpack": "rimraf dist && webpack --config config/webpack.prod.js --bail", "build:webpack": "rimraf dist && webpack --config config/webpack.prod.js --bail",
"build:cli": "ng build", "build:cli": "ng build",
"build:aot": "ngc -p tsconfig-aot.json && rollup -c rollup-config.js", "build:aot": "ngc -p tsconfig-aot.json && rollup -c rollup-config.js",
"build:babel": "babel app -d app --extensions \".es6\" --source-maps",
"copy-dist-files": "node ./copy-dist-files.js", "copy-dist-files": "node ./copy-dist-files.js",
"i18n": "ng-xi18n" "i18n": "ng-xi18n"
}, },

View File

@ -0,0 +1,6 @@
{
"presets": [
"es2015",
"angular2"
]
}

View File

@ -0,0 +1,10 @@
import { Injectable } from '@angular/core';
@Injectable()
export class DataService {
constructor() {
}
getHeroName() {
return 'Windstorm';
}
}

View File

@ -0,0 +1,50 @@
import {
Attribute,
Component,
Inject,
Optional,
NgModule
} from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
// #docregion
@Component({
selector: 'hero-title',
template: `
<h1>{{titlePrefix}} {{title}}</h1>
<button (click)="ok()">OK</button>
<p>{{ msg }}</p>
`
})
class TitleComponent {
msg = '';
constructor(
@Inject('titlePrefix') @Optional() titlePrefix,
@Attribute('title') title
) {
this.titlePrefix = titlePrefix;
this.title = title;
}
ok() {
this.msg = 'OK!';
}
}
// #enddocregion
@Component({
selector: 'hero-di-inject-additional',
template: `<hero-title title="Tour of Heroes">
</hero-title>`
})
class AppComponent { }
@NgModule({
imports: [ BrowserModule ],
declarations: [
AppComponent,
TitleComponent
],
bootstrap: [ AppComponent ]
})
export class HeroesDIInjectAdditionalModule { }

View File

@ -0,0 +1,22 @@
import { Component, Inject, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
// #docregion
@Component({
selector: 'hero-di-inject',
template: `<h1>Hero: {{name}}</h1>`
})
class HeroComponent {
constructor(@Inject('heroName') name) {
this.name = name;
}
}
// #enddocregion
@NgModule({
imports: [ BrowserModule ],
providers: [ { provide: 'heroName', useValue: 'Windstorm' } ],
declarations: [ HeroComponent ],
bootstrap: [ HeroComponent ]
})
export class HeroesDIInjectModule { }

View File

@ -0,0 +1,26 @@
import { Component, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { DataService } from './data.service';
// #docregion
@Component({
selector: 'hero-di',
template: `<h1>Hero: {{name}}</h1>`
})
class HeroComponent {
name;
constructor(dataService: DataService) {
this.name = dataService.getHeroName();
}
}
// #enddocregion
@NgModule({
imports: [ BrowserModule ],
providers: [ DataService ],
declarations: [ HeroComponent ],
bootstrap: [ HeroComponent ]
})
export class HeroesDIModule { }

View File

@ -0,0 +1,73 @@
import {
Component,
EventEmitter,
Input,
Output,
NgModule
} from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
// #docregion
@Component({
selector: 'my-confirm',
template: `
<button (click)="onOkClick()">
{{okMsg}}
</button>
<button (click)="onNotOkClick()">
{{notOkMsg}}
</button>
`
})
class ConfirmComponent {
@Input() okMsg;
@Input('cancelMsg') notOkMsg;
@Output() ok =
new EventEmitter();
@Output('cancel') notOk =
new EventEmitter();
onOkClick() {
this.ok.next(true);
}
onNotOkClick() {
this.notOk.next(true);
}
}
// #enddocregion
@Component({
selector: 'hero-io',
template: `
<my-confirm [okMsg]="'OK'"
[cancelMsg]="'Cancel'"
(ok)="onOk()"
(cancel)="onCancel()">
</my-confirm>
<span *ngIf="okClicked">OK clicked</span>
<span *ngIf="cancelClicked">Cancel clicked</span>
`
})
class AppComponent {
okClicked;
cancelClicked;
onOk() {
this.okClicked = true;
}
onCancel() {
this.cancelClicked = true;
}
}
@NgModule({
imports: [ BrowserModule ],
declarations: [
AppComponent,
ConfirmComponent
],
bootstrap: [ AppComponent ]
})
export class HeroesIOModule { }

View File

@ -0,0 +1,27 @@
// #docplaster
// #docregion
import { Component, OnInit } from '@angular/core';
// #enddocregion
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@Component({
selector: 'hero-lifecycle',
template: `<h1>Hero: {{name}}</h1>`
})
// #docregion
class HeroComponent{
name;
ngOnInit() {
this.name = 'Windstorm';
}
}
// #enddocregion
@NgModule({
imports: [ BrowserModule ],
declarations: [ HeroComponent ],
bootstrap: [ HeroComponent ]
})
export class HeroesLifecycleModule { }

View File

@ -0,0 +1,30 @@
// #docplaster
// #docregion metadata
import { Component } from '@angular/core';
@Component({
selector: 'hero-view',
template:
'<h1>Hero: {{getName()}}</h1>'
})
// #docregion appexport
// #docregion class
export class HeroComponent {
title = 'Hero Detail';
getName() {return 'Windstorm'; }
}
// #enddocregion class
// #enddocregion appexport
// #enddocregion metadata
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
imports: [ BrowserModule ],
declarations: [ HeroComponent ],
bootstrap: [ HeroComponent ]
})
export class HeroesModule { }

View File

@ -0,0 +1,42 @@
import {
Component,
HostBinding,
HostListener,
NgModule
} from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
// #docregion
@Component({
selector: 'heroes-bindings',
template: `
<h1 [class.active]="active">
Tour of Heroes
</h1>
`
})
class HeroesComponent {
@HostBinding() title = 'Tooltip content';
@HostBinding('class.heading') hClass = true;
active;
constructor() {}
@HostListener('click')
clicked() {
this.active = !this.active;
}
@HostListener('dblclick', ['$event'])
doubleClicked(evt) {
this.active = true;
}
}
// #enddocregion
@NgModule({
imports: [ BrowserModule ],
declarations: [ HeroesComponent ],
bootstrap: [ HeroesComponent ]
})
export class HeroesHostBindingsModule { }

View File

@ -0,0 +1,88 @@
import {
Component,
ViewChildren,
ContentChild,
QueryList,
Input,
NgModule
} from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@Component({
selector: 'active-label',
template: `<span class="active-label"
*ngIf="active">
Active
</span>`
})
class ActiveLabelComponent {
active;
activate() {
this.active = true;
}
}
// #docregion content
@Component({
selector: 'a-hero',
template: `<h2 [class.active]=active>
{{hero.name}}
<ng-content></ng-content>
</h2>`
})
class HeroComponent {
@Input() hero;
active;
@ContentChild(ActiveLabelComponent)
label;
activate() {
this.active = true;
this.label.activate();
}
}
// #enddocregion content
// #docregion view
@Component({
selector: 'heroes-queries',
template: `
<a-hero *ngFor="let hero of heroData"
[hero]="hero">
<active-label></active-label>
</a-hero>
<button (click)="activate()">
Activate
</button>
`
})
class HeroesQueriesComponent {
heroData = [
{id: 1, name: 'Windstorm'},
{id: 2, name: 'Superman'}
];
@ViewChildren(HeroComponent)
heroCmps;
activate() {
this.heroCmps.forEach(
(cmp) => cmp.activate()
);
}
}
// #enddocregion view
@NgModule({
imports: [ BrowserModule ],
declarations: [
HeroesQueriesComponent,
HeroComponent,
ActiveLabelComponent
],
bootstrap: [ HeroesQueriesComponent ]
})
export class HeroesQueriesModule { }

View File

@ -0,0 +1,30 @@
/* tslint:disable no-unused-variable */
// #docregion ng2import
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import {
LocationStrategy,
HashLocationStrategy
} from '@angular/common';
// #enddocregion ng2import
// #docregion appimport
import { HeroComponent } from './hero.component';
// #enddocregion appimport
import { HeroesModule } from './hero.component';
import { HeroesLifecycleModule } from './hero-lifecycle.component';
import { HeroesDIModule } from './hero-di.component';
import { HeroesDIInjectModule } from './hero-di-inject.component';
import { HeroesDIInjectAdditionalModule } from './hero-di-inject-additional.component';
import { HeroesIOModule } from './hero-io.component';
import { HeroesHostBindingsModule } from './heroes-bindings.component';
import { HeroesQueriesModule } from './heroes-queries.component';
platformBrowserDynamic().bootstrapModule(HeroesModule);
platformBrowserDynamic().bootstrapModule(HeroesLifecycleModule);
platformBrowserDynamic().bootstrapModule(HeroesDIModule);
platformBrowserDynamic().bootstrapModule(HeroesDIInjectModule);
platformBrowserDynamic().bootstrapModule(HeroesDIInjectAdditionalModule);
platformBrowserDynamic().bootstrapModule(HeroesIOModule);
platformBrowserDynamic().bootstrapModule(HeroesHostBindingsModule);
platformBrowserDynamic().bootstrapModule(HeroesQueriesModule);

View File

@ -0,0 +1,4 @@
{
"build": "build:babel",
"run": "http-server:e2e"
}

View File

@ -0,0 +1,51 @@
<!DOCTYPE html>
<html>
<head>
<base href="/">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
<!-- Polyfill(s) for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
</head>
<body>
<a id="toc"></a>
<h1>TypeScript to JavaScript</h1>
<a href="#class-metadata">Classes and Class Metadata</a><br>
<a href="#property-metadata">Input and Output Metadata</a><br>
<a href="#dependency-injection">Dependency Injection</a><br>
<a href="#other-property-metadata">Host and Query Metadata</a><br>
<hr>
<h4 id="class-metadata">Classes and Class Metadata</h4>
<hero-view id="class-metadata">Loading hero-view...</hero-view>
<hero-lifecycle>Loading hero-lifecycle...</hero-lifecycle>
<hr>
<h4 id="property-metadata">Input and Output Metadata</h4>
<hero-io>Loading hero-io...</hero-io>
<hr>
<h4 id="dependency-injection">Dependency Injection</h4>
<hero-di>Loading hero-di...</hero-di>
<hero-di-inject>Loading hero-di-inject...</hero-di-inject>
<hero-di-inject-additional>Loading hero-di-inject-additional...</hero-di-inject-additional>
<hr>
<h4 id="other-property-metadata">Host and Query Metadata</h4>
<heroes-bindings>Loading heroes-bindings...</heroes-bindings>
<heroes-queries id="other-property-metadata">Loading heroes-queries...</heroes-queries>
</body>
</html>

View File

@ -0,0 +1,8 @@
{
"description": "TypeScript to JavaScript",
"files":[
"!**/*.d.ts",
"!**/*.js"
],
"tags":["cookbook"]
}

View File

@ -0,0 +1,5 @@
{
"presets": [
"es2015"
]
}

View File

@ -0,0 +1,13 @@
import { Injectable } from '@angular/core';
export class DataService {
constructor() {
}
getHeroName() {
return 'Windstorm';
}
}
DataService.annotations = [
new Injectable()
];

View File

@ -0,0 +1,61 @@
import {
Attribute,
Component,
Inject,
Optional,
NgModule
} from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
// #docregion
class TitleComponent {
constructor(titlePrefix, title) {
this.titlePrefix = titlePrefix;
this.title = title;
this.msg = '';
}
ok() {
this.msg = 'OK!';
}
}
TitleComponent.annotations = [
new Component({
selector: 'hero-title',
template: `
<h1>{{titlePrefix}} {{title}}</h1>
<button (click)="ok()">OK</button>
<p>{{ msg }}</p>
`
})
];
TitleComponent.parameters = [
[new Optional(), new Inject('titlePrefix')],
[new Attribute('title')]
];
// #enddocregion
class AppComponent {
}
AppComponent.annotations = [
new Component({
selector: 'hero-di-inject-additional',
template: `<hero-title title="Tour of Heroes">
</hero-title>`
})
];
export class HeroesDIInjectAdditionalModule { }
HeroesDIInjectAdditionalModule.annotations = [
new NgModule({
imports: [ BrowserModule ],
declarations: [
AppComponent,
TitleComponent
],
bootstrap: [ AppComponent ]
})
];

View File

@ -0,0 +1,32 @@
import { Component, Inject, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
// #docregion
class HeroComponent {
constructor(name) {
this.name = name;
}
}
HeroComponent.annotations = [
new Component({
selector: 'hero-di-inject',
template: `<h1>Hero: {{name}}</h1>`
})
];
HeroComponent.parameters = [
[new Inject('heroName')]
];
// #enddocregion
export class HeroesDIInjectModule { }
HeroesDIInjectModule.annotations = [
new NgModule({
imports: [ BrowserModule ],
providers: [ { provide: 'heroName', useValue: 'Windstorm' } ],
declarations: [ HeroComponent ],
bootstrap: [ HeroComponent ]
})
];

View File

@ -0,0 +1,35 @@
import { Component, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { DataService } from './data.service';
// #docregion
class HeroComponent {
constructor(dataService) {
this.name = dataService.getHeroName();
}
}
HeroComponent.annotations = [
new Component({
selector: 'hero-di',
template: `<h1>Hero: {{name}}</h1>`
})
];
HeroComponent.parameters = [
[DataService]
];
// #enddocregion
export class HeroesDIModule { }
HeroesDIModule.annotations = [
new NgModule({
imports: [ BrowserModule ],
providers: [ DataService ],
declarations: [ HeroComponent ],
bootstrap: [ HeroComponent ]
})
];

View File

@ -0,0 +1,85 @@
import {
Component,
EventEmitter,
Input,
Output,
NgModule
} from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
// #docregion
class ConfirmComponent {
constructor(){
this.ok = new EventEmitter();
this.notOk = new EventEmitter();
}
onOkClick() {
this.ok.next(true);
}
onNotOkClick() {
this.notOk.next(true);
}
}
ConfirmComponent.annotations = [
new Component({
selector: 'my-confirm',
template: `
<button (click)="onOkClick()">
{{okMsg}}
</button>
<button (click)="onNotOkClick()">
{{notOkMsg}}
</button>
`,
inputs: [
'okMsg',
'notOkMsg: cancelMsg'
],
outputs: [
'ok',
'notOk: cancel'
]
})
];
// #enddocregion
class AppComponent {
constructor(){
}
onOk() {
this.okClicked = true;
}
onCancel() {
this.cancelClicked = true;
}
}
AppComponent.annotations = [
new Component({
selector: 'hero-io',
template: `
<my-confirm [okMsg]="'OK'"
[cancelMsg]="'Cancel'"
(ok)="onOk()"
(cancel)="onCancel()">
</my-confirm>
<span *ngIf="okClicked">OK clicked</span>
<span *ngIf="cancelClicked">Cancel clicked</span>
`
})
];
export class HeroesIOModule { }
HeroesIOModule.annotations = [
new NgModule({
imports: [ BrowserModule ],
declarations: [
AppComponent,
ConfirmComponent
],
bootstrap: [ AppComponent ]
})
];

View File

@ -0,0 +1,31 @@
// #docplaster
// #docregion
import { Component } from '@angular/core';
// #enddocregion
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
// #docregion
class HeroComponent {
ngOnInit() {
this.name = 'Windstorm';
}
}
// #enddocregion
HeroComponent.annotations = [
new Component({
selector: 'hero-lifecycle',
template: `<h1>Hero: {{name}}</h1>`
})
];
export class HeroesLifecycleModule { }
HeroesLifecycleModule.annotations = [
new NgModule({
imports: [ BrowserModule ],
declarations: [ HeroComponent ],
bootstrap: [ HeroComponent ]
})
];

View File

@ -0,0 +1,37 @@
// #docplaster
// #docregion metadata
import { Component } from '@angular/core';
// #docregion class
// #docregion appexport
export class HeroComponent {
construct() {
this.title = 'Hero Detail';
}
getName() {return 'Windstorm'; }
}
// #enddocregion appexport
// #enddocregion class
HeroComponent.annotations = [
new Component({
selector: 'hero-view',
template: '<h1>Hero: {{getName()}}</h1>'
})
];
// #enddocregion metadata
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
export class HeroesModule { }
HeroesModule.annotations = [
new NgModule({
imports: [ BrowserModule ],
declarations: [ HeroComponent ],
bootstrap: [ HeroComponent ]
})
];

View File

@ -0,0 +1,48 @@
import {
Component,
HostBinding,
HostListener,
NgModule
} from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
// #docregion
class HeroesComponent {
constructor() {
this.title = 'Tooltip content';
this.hClass = true;
}
clicked() {
this.active = !this.active;
}
doubleClicked(evt) {
this.active = true;
}
}
HeroesComponent.annotations = [
new Component({
selector: 'heroes-bindings',
template: `<h1 [class.active]="active">
Tour of Heroes
</h1>`,
host: {
'[title]': 'title',
'[class.heading]': 'hClass',
'(click)': 'clicked()',
'(dblclick)': 'doubleClicked($event)'
}
})
];
// #enddocregion
export class HeroesHostBindingsModule { }
HeroesHostBindingsModule.annotations = [
new NgModule({
imports: [ BrowserModule ],
declarations: [ HeroesComponent ],
bootstrap: [ HeroesComponent ]
})
];

View File

@ -0,0 +1,98 @@
import {
Component,
ViewChildren,
ContentChild,
QueryList,
Input,
NgModule
} from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
class ActiveLabelComponent {
activate() {
this.active = true;
}
}
ActiveLabelComponent.annotations = [
new Component({
selector: 'active-label',
template: `
<span class="active-label" *ngIf="active">
Active
</span>`
})
];
// #docregion content
class HeroComponent {
activate() {
this.active = true;
this.label.activate();
}
}
HeroComponent.annotations = [
new Component({
selector: 'a-hero',
template: `<h2 [class.active]=active>
{{hero.name}}
<ng-content></ng-content>
</h2>`,
inputs: ['hero'],
queries: {
label: new ContentChild(ActiveLabelComponent)
}
})
];
// #enddocregion content
// #docregion view
class HeroesQueriesComponent {
constructor(){
this.heroData = [
{id: 1, name: 'Windstorm'},
{id: 2, name: 'Superman'}
];
}
activate() {
this.heroCmps.forEach(
(cmp) => cmp.activate()
);
}
}
HeroesQueriesComponent.annotations = [
new Component({
selector: 'heroes-queries',
template: `
<a-hero *ngFor="let hero of heroData"
[hero]="hero">
<active-label></active-label>
</a-hero>
<button (click)="activate()">
Activate
</button>
`,
queries: {
heroCmps: new ViewChildren(HeroComponent)
}
})
];
// #enddocregion view
export class HeroesQueriesModule { }
HeroesQueriesModule.annotations = [
new NgModule({
imports: [ BrowserModule ],
declarations: [
HeroesQueriesComponent,
HeroComponent,
ActiveLabelComponent
],
bootstrap: [ HeroesQueriesComponent ]
})
];

View File

@ -0,0 +1,30 @@
/* tslint:disable no-unused-variable */
// #docregion ng2import
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import {
LocationStrategy,
HashLocationStrategy
} from '@angular/common';
// #enddocregion ng2import
// #docregion appimport
import { HeroComponent } from './hero.component';
// #enddocregion appimport
import { HeroesModule } from './hero.component';
import { HeroesLifecycleModule } from './hero-lifecycle.component';
import { HeroesDIModule } from './hero-di.component';
import { HeroesDIInjectModule } from './hero-di-inject.component';
import { HeroesDIInjectAdditionalModule } from './hero-di-inject-additional.component';
import { HeroesIOModule } from './hero-io.component';
import { HeroesHostBindingsModule } from './heroes-bindings.component';
import { HeroesQueriesModule } from './heroes-queries.component';
platformBrowserDynamic().bootstrapModule(HeroesModule);
platformBrowserDynamic().bootstrapModule(HeroesLifecycleModule);
platformBrowserDynamic().bootstrapModule(HeroesDIModule);
platformBrowserDynamic().bootstrapModule(HeroesDIInjectModule);
platformBrowserDynamic().bootstrapModule(HeroesDIInjectAdditionalModule);
platformBrowserDynamic().bootstrapModule(HeroesIOModule);
platformBrowserDynamic().bootstrapModule(HeroesHostBindingsModule);
platformBrowserDynamic().bootstrapModule(HeroesQueriesModule);

View File

@ -0,0 +1,4 @@
{
"build": "build:babel",
"run": "http-server:e2e"
}

View File

@ -0,0 +1,52 @@
<!DOCTYPE html>
<html>
<head>
<base href="/">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
<!-- Polyfill(s) for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
</head>
<body>
<a id="toc"></a>
<h1>TypeScript to JavaScript</h1>
<a href="#class-metadata">Classes and Class Metadata</a><br>
<a href="#property-metadata">Input and Output Metadata</a><br>
<a href="#dependency-injection">Dependency Injection</a><br>
<a href="#other-property-metadata">Host and Query Metadata</a><br>
<my-app></my-app>
<hr>
<h4 id="class-metadata">Classes and Class Metadata</h4>
<hero-view id="class-metadata">Loading hero-view...</hero-view>
<hero-lifecycle>Loading hero-lifecycle...</hero-lifecycle>
<hr>
<h4 id="property-metadata">Input and Output Metadata</h4>
<hero-io>Loading hero-io...</hero-io>
<hr>
<h4 id="dependency-injection">Dependency Injection</h4>
<hero-di>Loading hero-di...</hero-di>
<hero-di-inject>Loading hero-di-inject...</hero-di-inject>
<hero-di-inject-additional>Loading hero-di-inject-additional...</hero-di-inject-additional>
<hr>
<h4 id="other-property-metadata">Host and Query Metadata</h4>
<heroes-bindings>Loading heroes-bindings...</heroes-bindings>
<heroes-queries id="other-property-metadata">Loading heroes-queries...</heroes-queries>
</body>
</html>

View File

@ -0,0 +1,8 @@
{
"description": "TypeScript to JavaScript",
"files":[
"!**/*.d.ts",
"!**/*.js"
],
"tags":["cookbook"]
}

View File

@ -9,10 +9,7 @@
'<p>{{ msg }}</p>' '<p>{{ msg }}</p>'
}).Class({ }).Class({
constructor: [ constructor: [
[ [ new ng.core.Optional(), new ng.core.Inject('titlePrefix') ],
new ng.core.Optional(),
new ng.core.Inject('titlePrefix')
],
new ng.core.Attribute('title'), new ng.core.Attribute('title'),
function(titlePrefix, title) { function(titlePrefix, title) {
this.titlePrefix = titlePrefix; this.titlePrefix = titlePrefix;

View File

@ -35,11 +35,12 @@
template: '<h1>Hero: {{name}}</h1>' template: '<h1>Hero: {{name}}</h1>'
}) })
.Class({ .Class({
constructor: constructor: [
[new ng.core.Inject('heroName'), new ng.core.Inject('heroName'),
function(name) { function(name) {
this.name = name; this.name = name;
}] }
]
}); });
// #enddocregion ctor // #enddocregion ctor

View File

@ -5,11 +5,12 @@
template: '<h1>Hero: {{name}}</h1>' template: '<h1>Hero: {{name}}</h1>'
}) })
.Class({ .Class({
constructor: constructor: [
[app.DataService, app.DataService,
function(service) { function(service) {
this.name = service.getHeroName(); this.name = service.getHeroName();
}] }
]
}); });
// #enddocregion // #enddocregion

View File

@ -6,9 +6,11 @@
function HeroComponent(dataService) { function HeroComponent(dataService) {
this.name = dataService.getHeroName(); this.name = dataService.getHeroName();
} }
HeroComponent.parameters = [ HeroComponent.parameters = [
app.DataService app.DataService
]; ];
HeroComponent.annotations = [ HeroComponent.annotations = [
new ng.core.Component({ new ng.core.Component({
selector: 'hero-di', selector: 'hero-di',

View File

@ -5,8 +5,7 @@
// #docregion component // #docregion component
var HeroComponent = ng.core.Component({ var HeroComponent = ng.core.Component({
selector: 'hero-view-2', selector: 'hero-view-2',
template: template: '<h1>Name: {{getName()}}</h1>',
'<h1>Name: {{getName()}}</h1>',
}) })
.Class({ .Class({
constructor: function() { constructor: function() {

View File

@ -10,10 +10,9 @@
}) })
]; ];
// #docregion // #docregion
HeroComponent.prototype.ngOnInit = HeroComponent.prototype.ngOnInit = function() {
function() { this.name = 'Windstorm';
this.name = 'Windstorm'; };
};
// #enddocregion // #enddocregion
app.HeroesLifecycleModule = app.HeroesLifecycleModule =

View File

@ -15,13 +15,12 @@
HeroComponent.annotations = [ HeroComponent.annotations = [
new ng.core.Component({ new ng.core.Component({
selector: 'hero-view', selector: 'hero-view',
template: template: '<h1>Hero: {{getName()}}</h1>'
'<h1>Hero: {{getName()}}</h1>'
}) })
]; ];
// #docregion constructorproto // #docregion constructorproto
HeroComponent.prototype.getName =
function() {return 'Windstorm';}; HeroComponent.prototype.getName = function() {return 'Windstorm';};
// #enddocregion constructorproto // #enddocregion constructorproto
// #enddocregion metadata // #enddocregion metadata

View File

@ -4,12 +4,9 @@
// #enddocregion appimport // #enddocregion appimport
// #docregion ng2import // #docregion ng2import
var platformBrowserDynamic = var platformBrowserDynamic = ng.platformBrowserDynamic.platformBrowserDynamic;
ng.platformBrowserDynamic.platformBrowserDynamic; var LocationStrategy = ng.common.LocationStrategy;
var LocationStrategy = var HashLocationStrategy = ng.common.HashLocationStrategy;
ng.common.LocationStrategy;
var HashLocationStrategy =
ng.common.HashLocationStrategy;
// #enddocregion ng2import // #enddocregion ng2import
// #docregion appimport // #docregion appimport

View File

@ -19,12 +19,9 @@ import { BrowserModule } from '@angular/platform-browser';
class TitleComponent { class TitleComponent {
private msg: string = ''; private msg: string = '';
constructor( constructor(
@Inject('titlePrefix') @Inject('titlePrefix') @Optional() private titlePrefix: string,
@Optional() @Attribute('title') private title: string
private titlePrefix: string, ) { }
@Attribute('title')
private title: string) {
}
ok() { ok() {
this.msg = 'OK!'; this.msg = 'OK!';

View File

@ -7,10 +7,7 @@ import { BrowserModule } from '@angular/platform-browser';
template: `<h1>Hero: {{name}}</h1>` template: `<h1>Hero: {{name}}</h1>`
}) })
class HeroComponent { class HeroComponent {
constructor( constructor(@Inject('heroName') private name: string) { }
@Inject('heroName')
private name: string) {
}
} }
// #enddocregion // #enddocregion

View File

@ -8,6 +8,7 @@ import { DataService } from './data.service';
selector: 'hero-di', selector: 'hero-di',
template: `<h1>Hero: {{name}}</h1>` template: `<h1>Hero: {{name}}</h1>`
}) })
class HeroComponent { class HeroComponent {
name: string; name: string;
constructor(dataService: DataService) { constructor(dataService: DataService) {

View File

@ -10,8 +10,7 @@ import { BrowserModule } from '@angular/platform-browser';
template: `<h1>Hero: {{name}}</h1>` template: `<h1>Hero: {{name}}</h1>`
}) })
// #docregion // #docregion
class HeroComponent class HeroComponent implements OnInit {
implements OnInit {
name: string; name: string;
ngOnInit() { ngOnInit() {
this.name = 'Windstorm'; this.name = 'Windstorm';

View File

@ -9,14 +9,15 @@ import { BrowserModule } from '@angular/platform-browser';
// #docregion // #docregion
@Component({ @Component({
selector: 'heroes-bindings', selector: 'heroes-bindings',
template: `<h1 [class.active]="active"> template: `
Tour of Heroes <h1 [class.active]="active">
</h1>` Tour of Heroes
</h1>
`
}) })
class HeroesComponent { class HeroesComponent {
@HostBinding() title = 'Tooltip content'; @HostBinding() title = 'Tooltip content';
@HostBinding('class.heading') @HostBinding('class.heading') hClass = true;
hClass = true;
active: boolean; active: boolean;
constructor() {} constructor() {}

View File

@ -27,7 +27,7 @@
"@angular/router": "~3.1.1", "@angular/router": "~3.1.1",
"@angular/upgrade": "~2.1.1", "@angular/upgrade": "~2.1.1",
"angular-in-memory-web-api": "~0.1.13", "angular-in-memory-web-api": "~0.1.14",
"core-js": "^2.4.1", "core-js": "^2.4.1",
"reflect-metadata": "^0.1.8", "reflect-metadata": "^0.1.8",
"rollup": "^0.36.0", "rollup": "^0.36.0",
@ -51,6 +51,9 @@
"@types/selenium-webdriver": "^2.53.32", "@types/selenium-webdriver": "^2.53.32",
"angular2-template-loader": "^0.4.0", "angular2-template-loader": "^0.4.0",
"awesome-typescript-loader": "^2.2.4", "awesome-typescript-loader": "^2.2.4",
"babel-cli": "^6.16.0",
"babel-preset-angular2": "^0.0.2",
"babel-preset-es2015": "^6.16.0",
"canonical-path": "0.0.2", "canonical-path": "0.0.2",
"concurrently": "^3.0.0", "concurrently": "^3.0.0",
"css-loader": "^0.25.0", "css-loader": "^0.25.0",

View File

@ -16,6 +16,8 @@ include ../../../../_includes/_util-fns
:marked :marked
## Table of contents ## Table of contents
[From TS to ES6 to ES5](#from-ts)
[Modularity: imports and exports](#modularity) [Modularity: imports and exports](#modularity)
[Classes and Class Metadata](#class-metadata) [Classes and Class Metadata](#class-metadata)
@ -24,90 +26,127 @@ include ../../../../_includes/_util-fns
[Dependency Injection](#dependency-injection) [Dependency Injection](#dependency-injection)
[Host and Query Metadata](#other-property-metadata) [Host and Query Metadata](#host-query-metadata)
**Run and compare the live <live-example name="cb-ts-to-js">TypeScript</live-example> and <live-example name="cb-ts-to-js" lang="js">JavaScript</live-example> **Run and compare the live <live-example name="cb-ts-to-js">TypeScript</live-example> and <live-example name="cb-ts-to-js" lang="js">JavaScript</live-example>
code shown in this cookbook.** code shown in this cookbook.**
a(id="from-ts")
.l-main-section
:marked
## From TS to ES6 to ES5
Since TypeScript is a superset of ES6 JavaScript, and ES6 itself is a superset of ES5, the
transformation of Typescript code all the way to ES5 javascript can be seen as "shedding"
features.
When going from TypeScript to ES6 with decorators, we mostly remove
[type annotations](https://www.typescriptlang.org/docs/handbook/basic-types.html)
, such as `string` or `boolean`, and
[class property modifiers](http://www.typescriptlang.org/docs/handbook/classes.html#public-private-and-protected-modifiers)
such as `public` and `private`.
The exception is type annotations used for dependency injection, which can be kept.
Going from ES6 with decorators to plain ES6 JavaScript we lose all
[decorators](https://www.typescriptlang.org/docs/handbook/decorators.html)
and the remaining type annotations.
We also lose class properties, which now have to be declared in the class constructor.
Finally, in the transition from ES6 to ES5 JavaScript the main missing features are `import`
statements and `class` declarations.
For ES6 transpilation we recommend using a similar setup as our TypeScript quickstart,
replacing TypeScript with [Babel](https://babeljs.io/) using the `es2015` preset.
To use decorators and annotations with Babel, install the
[`angular2`](https://github.com/shuhei/babel-plugin-angular2-annotations) preset as well.
a(id="modularity") a(id="modularity")
.l-main-section .l-main-section
:marked :marked
## Importing and Exporting ## Importing and Exporting
- var top="vertical-align:top" ### Importing Angular Code
table(width="100%")
col(width="50%")
col(width="50%")
tr
th TypeScript
th ES5 JavaScript
tr(style=top)
td
:marked
### Importing Angular Code
In TypeScript code, Angular classes, functions, and other members In TypeScript and ES6 JavaScript, Angular classes, functions, and other members are imported
are imported with TypeScript `import` statements: with ES6 `import` statements.
+makeExample('cb-ts-to-js/ts/app/main.ts', 'ng2import')(format="." ) In ES5 JavaScript code, when using [the Angular packages](../glossary.html#!#scoped-package),
we can access Angular code through the global `ng` object. In the nested members of this
object we'll find everything we would import from `@angular` in TypeScript:
td +makeTabs(`
:marked cb-ts-to-js/ts/app/main.ts,
### Accessing Angular Code through the ng global cb-ts-to-js/js-es6-decorators/app/main.es6,
cb-ts-to-js/js-es6/app/main.es6,
cb-ts-to-js/js/app/main.js
`,`
ng2import,
ng2import,
ng2import,
ng2import
`,`
Typescript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
In JavaScript code, when using :marked
[the Angular packages](../glossary.html#!#scoped-package), ### Importing and Exporting Application Code
we can access Angular code through the global `ng` object. In the
nested members of this object we'll find everything we would import
from `@angular` in TypeScript:
+makeExample('cb-ts-to-js/js/app/main.js', 'ng2import')(format="." ) Each file in an Angular TypeScript or ES6 JavaScript application constitutes a ES6 module.
When we want to make something from a module available to other modules, we `export` it.
tr(style=top) In an Angular ES5 JavaScript application, we load each file to the page using a `<script>` tag.
td Each file can make things available to other files via the shared global `window` scope.
:marked
### Importing and Exporting Application Code
Each file in an Angular TypeScript application constitutes a We often introduce an application namespace object (such as `app`) onto `window` and attach
TypeScript module. When we want to make something from a module available everything we need to share to that namespace object.
to other modules, we `export` it. We also wrap our code in an
[Immediately Invoked Function Expression (IIFE)](https://en.wikipedia.org/wiki/Immediately-invoked_function_expression).
These practices together prevent our code from polluting the global scope.
+makeExample('cb-ts-to-js/ts/app/hero.component.ts', 'appexport')(format="." ) +makeTabs(`
cb-ts-to-js/ts/app/hero.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero.component.es6,
cb-ts-to-js/js-es6/app/hero.component.es6,
cb-ts-to-js/js/app/hero.component.js
`,`
appexport,
appexport,
appexport,
appexport
`,`
Typescript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
:marked :marked
In other modules we can then `import` things that have been exported Using Typescript or ES6 JavaScript, in other modules we can then `import` things that have been exported
elsewhere. elsewhere.
+makeExample('cb-ts-to-js/ts/app/main.ts', 'appimport')(format="." ) In ES5 JavaScript we can access anything using the shared namespace in other files.
Note that the order of `<script>` tags on the page is significant.
We must load a file that defines a shared member before a file that uses that member.
td +makeTabs(`
:marked cb-ts-to-js/ts/app/main.ts,
### Sharing Application Code cb-ts-to-js/js-es6-decorators/app/main.es6,
cb-ts-to-js/js-es6/app/main.es6,
In an Angular JavaScript application, we load each file to the page cb-ts-to-js/js/app/main.js
using a `<script>` tag. Each file can make things available to other `,`
files via the shared global `window` scope. appimport,
appimport,
We often introduce an application namespace appimport,
object (such as `"app"`) onto `window` and attach everything we need appimport
to share to that namespace object. `,`
We also wrap our code in an Typescript,
[Immediately Invoked Function Expression (IIFE)](https://en.wikipedia.org/wiki/Immediately-invoked_function_expression). ES6 JavaScript with decorators,
These practices together prevent our code from ES6 JavaScript,
polluting the global scope. ES5 JavaScript
`)
+makeExample('cb-ts-to-js/js/app/hero.component.js', 'appexport')(format="." )
:marked
We can then access anything from this shared namespace in
other files.
+makeExample('cb-ts-to-js/js/app/main.js', 'appimport')(format="." )
:marked
Note that the order of `<script>` tags on the page is significant.
We must load a file that defines a shared member before
a file that uses that member.
.alert.is-helpful .alert.is-helpful
:marked :marked
@ -123,347 +162,329 @@ a(id="class-metadata")
:marked :marked
## Classes and Class Metadata ## Classes and Class Metadata
- var top="vertical-align:top" ### Classes
table(width="100%")
col(width="50%")
col(width="50%")
tr
th TypeScript
th ES5 JavaScript
tr(style=top)
td
:marked
### Classes
We put most of our Angular TypeScript code into TypeScript classes. We put most of our Angular TypeScript or ES6 JavaScript code into classes. ES6 without decorators
also does not have support for class properties, so they must be assigned inside the constructor.
+makeExample('cb-ts-to-js/ts/app/hero.component.ts', 'class')(format="." ) ES5 JavaScript has no classes. We use the constructor pattern instead which works with
Angular as well as classes do.
td +makeTabs(`
:marked cb-ts-to-js/ts/app/hero.component.ts,
### Constructors and Prototypes cb-ts-to-js/js-es6-decorators/app/hero.component.es6,
cb-ts-to-js/js-es6/app/hero.component.es6,
cb-ts-to-js/js/app/hero.component.js
`,`
class,
class,
class,
constructorproto
`,`
Typescript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
ES5 JavaScript has no classes. We use the constructor :marked
pattern instead which works with Angular as well as classes do. ### Metadata
+makeExample('cb-ts-to-js/js/app/hero.component.js', 'constructorproto')(format="." ) Using Typescript or ES6 with decorators, we have access to *decorators*.
Most Angular classes have one or more *decorators* attached to provide configuration
and metadata.
For example, a component must have a
[`@Component`](../api/core/index/Component-decorator.html) decorator.
tr(style=top) In ES5/6 JavaScript we can instead attach an `annotations` array to a class/constructor
td to provide metadata.
:marked Each item in the array corresponds to a decorator.
### Metadata with Decorators
Most Angular classes have one or more TypeScript *decorators* The pattern of creating a constructor and decorating it with metadata is so common that Angular
attached to provide configuration and metadata. For example, provides an alternative ES5 convenience class API for it for ES5 JavaScript.
a component must have a [`@Component`](../api/core/index/Component-decorator.html) decorator. This API lets us define everything in a single expression.
+makeExample('cb-ts-to-js/ts/app/hero.component.ts', 'metadata')(format="." ) With this API we first call the `ng.core.Component` function, followed by a chained `Class`
method call.
The argument to `Class` is an object that defines the constructor and the instance methods
of the component.
Similar APIs are also available for other decorators. You can define a directive with
`ng.core.Directive` or a pipe with `ng.core.Pipe`.
td +makeTabs(`
:marked cb-ts-to-js/ts/app/hero.component.ts,
### Metadata with the Annotations Array cb-ts-to-js/js-es6-decorators/app/hero.component.es6,
cb-ts-to-js/js-es6/app/hero.component.es6,
cb-ts-to-js/js/app/hero.component.js,
cb-ts-to-js/js/app/hero-dsl.component.js
`,`
metadata,
metadata,
metadata,
metadata,
component
`,`
Typescript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript,
ES5 JavaScript with Class API
`)
In JavaScript, we can attach an `annotations` array to a constructor :marked
to provide metadata. ### Interfaces
Each item in the array corresponds to a TypeScript decorator.
In the following example, we create a new instance of `Component` that corresponds When defining classes that need to implement a certain method, it is common to use TypeScript
to the [`@Component`](../api/core/index/Component-decorator.html) TypeScript decorator. interfaces that enforce that the method signature is correct.
Component lifecycle methods like `ngOnInit` are one example of this pattern.
`ngOnInit` is defined in the `OnInit` interface.
+makeExample('cb-ts-to-js/js/app/hero.component.js', 'metadata')(format="." ) TypeScript interfaces are purely for developer convenience and are not used by Angular at runtime.
This means that in ES5/6 JavaScript code we don't need to substitute anything for interfaces.
We can just implement the methods.
:marked +makeTabs(`
### Metadata with The Class Convenience API cb-ts-to-js/ts/app/hero-lifecycle.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero-lifecycle.component.es6,
The pattern of creating a constructor and decorating it with metadata cb-ts-to-js/js-es6/app/hero-lifecycle.component.es6,
is so common that Angular provides an alternative convenience API for it. cb-ts-to-js/js/app/hero-lifecycle.component.js
This API lets us define everything in a single expression. `,`
`,`
With this API we first call the `ng.core.Component` function, Typescript,
followed by a chained `Class` method call. The argument to `Class` ES6 JavaScript with decorators,
is an object that defines the constructor and the instance methods ES6 JavaScript,
of the component: ES5 JavaScript
`)
+makeExample('cb-ts-to-js/js/app/hero-dsl.component.js', 'component')(format="." )
:marked
Similar APIs are also available for other decorators. You can define a
directive:
code-example.
var MyDirective = ng.core.Directive({
...
}).Class({
...
});
:marked
Or a pipe:
code-example.
var MyPipe = ng.core.Pipe({
name: 'myPipe'
}).Class({
...
});
tr(style=top)
td
:marked
### Interfaces
When defining classes that need to implement a certain method, it
is common to use TypeScript interfaces that enforce that the
method signature is correct. Component lifecycle methods like `ngOnInit`
are one example of this pattern. `ngOnInit` is defined in the `OnInit`
interface.
+makeExample('cb-ts-to-js/ts/app/hero-lifecycle.component.ts')(format="." )
td
:marked
### Implementing Methods without Interfaces
TypeScript interfaces are purely for developer convenience
and are not used by Angular at runtime. This means that in JavaScript
code we don't need to substitute anything for interfaces. We can just
implement the methods.
+makeExample('cb-ts-to-js/js/app/hero-lifecycle.component.js')(format="." )
a(id="property-metadata") a(id="property-metadata")
.l-main-section .l-main-section
:marked :marked
## Input and Output Metadata ## Input and Output Metadata
- var top="vertical-align:top" ### Input and Output Decorators
table(width="100%")
col(width="50%")
col(width="50%")
tr
th TypeScript
th ES5 JavaScript
tr(style=top)
td
:marked
### Input and Output Decorators
In TypeScript, property decorators are often used to provide additional metadata In TypeScript and ES6 with decorators, property decorators are often used to provide additional
for components and directives. metadata for components and directives.
For [inputs and outputs](../guide/template-syntax.html#inputs-outputs), we use `@Input` and
`@Output` property decorators.
They may optionally specify input and output binding names if we want them to be different
from the class property names.
For [inputs and outputs](../guide/template-syntax.html#inputs-outputs), There is no equivalent of a property decorator in ES5/6 JavaScript.
we use `@Input` and `@Output` property decorators. Instead, we add comparable information to the `Component` (or `Directive`) metadata.
They may optionally specify input and output binding names if we want them to be
different from the class property names.
+makeExample('cb-ts-to-js/ts/app/hero-io.component.ts')(format="." ) In this example, we add `inputs` and `outputs` array attributes containing the input and
output property names.
.alert.is-helpful If we need a binding name that is different from the property itself, we use the
:marked `propertyName: bindingName` syntax.
In TypeScript we can also use the `inputs` and `outputs` array metadata
instead of the `@Input` and `@Output` property decorators.
td
:marked
### Inputs and Outputs in Component Metadata
There is no equivalent of a property decorator in ES5 JavaScript. Instead,
we add comparable information to the `Component` (or `Directive`) metadata.
In this example, we add `inputs` and `outputs` array attributes
containing the input and output property names.
If we need a binding name that is different from the
property itself, we use the `propertyName: bindingName` syntax.
+makeExample('cb-ts-to-js/js/app/hero-io.component.js')(format="." )
+makeTabs(`
cb-ts-to-js/ts/app/hero-io.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero-io.component.es6,
cb-ts-to-js/js-es6/app/hero-io.component.es6,
cb-ts-to-js/js/app/hero-io.component.js
`,`
`,`
Typescript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
.l-main-section .l-main-section
:marked :marked
## Dependency Injection ## Dependency Injection
- var top="vertical-align:top" ### Injection by Type
table(width="100%")
col(width="50%")
col(width="50%")
tr
th TypeScript
th ES5 JavaScript
tr(style=top)
td
:marked
### Injection by Type
Angular can often use TypeScript type information to Angular can often use TypeScript type information to determine what needs to be injected.
determine what needs to be injected. ES6 with decorators can also make use of type information.
+makeExample('cb-ts-to-js/ts/app/hero-di.component.ts')(format="." ) Since no type information is available in ES5/6 JavaScript, we must identify "injectables" in
some other way.
td We attach a `parameters` array to the constructor function.
:marked Each array item is the dependency injection token that identifies the thing to be injected.
### Injection with Parameter Tokens Often the token is the constructor function for the class-like dependency.
Since no type information is available in ES5 JavaScript, In ES6 the decorators need to be inside a nested array.
we must identify "injectables" in some other way. When using the ES5 class convenience API, we can also supply the parameter tokens by wrapping
the constructor in an array.
We attach a `parameters` array to the constructor function. +makeTabs(`
Each array item is the dependency injection token that identifies the thing to be injected. cb-ts-to-js/ts/app/hero-di.component.ts,
Often the token is the constructor function for the class-like dependency. cb-ts-to-js/js-es6-decorators/app/hero-di.component.es6,
cb-ts-to-js/js-es6/app/hero-di.component.es6,
cb-ts-to-js/js/app/hero-di.component.js,
cb-ts-to-js/js/app/hero-di-inline.component.js
`,`
`,`
Typescript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript,
ES5 JavaScript with Class API
`)
+makeExample('cb-ts-to-js/js/app/hero-di.component.js')(format="." ) :marked
### Injection with the @Inject decorator
:marked When the thing being injected doesn't correspond directly to a type, we use the
When using the class convenience API, we can also supply the parameter `@Inject()` decorator to supply the injection token.
tokens by wrapping the constructor in an array. In this example, we're injecting a string identified by the "heroName" token.
+makeExample('cb-ts-to-js/js/app/hero-di-inline.component.js')(format="." ) In ES5/6 JavaScript we add the token string to the injection parameters array.
Alternatively, when using the ES5 convenience class API we can create a token with the
`Inject` method and add that to the constructor array in the annotations.
tr(style=top) +makeTabs(`
td cb-ts-to-js/ts/app/hero-di-inject.component.ts,
:marked cb-ts-to-js/js-es6-decorators/app/hero-di-inject.component.es6,
### Injection with the @Inject decorator cb-ts-to-js/js-es6/app/hero-di-inject.component.es6,
cb-ts-to-js/js/app/hero-di-inject.component.js,
cb-ts-to-js/js/app/hero-di-inject.component.js
`,`
,
,
,
parameters,
ctor
`,`
Typescript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript,
ES5 JavaScript with Class API
`)
When the thing being injected doesn't correspond directly to a type, :marked
we use the `@Inject()` decorator to supply the injection token. ### Additional Injection Decorators
In this example, we're injecting a string identified by the "heroName" token. We can attach additional decorators to constructor parameters to qualify the injection behavior.
We can mark optional dependencies with the [`@Optional`](../api/core/index/Optional-decorator.html),
inject host element attributes with [`@Attribute`](../api/core/index/Attribute-interface.html),
inject content child queries with [`@ContentChild`](../api/core/index/ContentChild-decorator.html)
and inject view child queries with [`@ViewChild`](../api/core/index/ViewChild-decorator.html)).
+makeExample('cb-ts-to-js/ts/app/hero-di-inject.component.ts')(format="." ) In ES6 JavaScript we just add the extra decorators to the nested injection parameters array.
td To achieve the same effect in ES5 JavaScript, use a nested array with the constructor
:marked array notation in which the injection information precedes the constructor function itself.
### Injection with plain string tokens
In JavaScript we add the token string to the injection parameters array. We can apply other additional parameter decorators such as
[`@Host`](../api/core/index/Host-decorator.html) and
[`@SkipSelf`](../api/core/index/SkipSelf-decorator.html) in the same way -
by adding `new ng.core.Host()` or `ng.core.SkipSelf()` in the
parameters array.
+makeTabs(`
cb-ts-to-js/ts/app/hero-di-inject-additional.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero-di-inject-additional.component.es6,
cb-ts-to-js/js-es6/app/hero-di-inject-additional.component.es6,
cb-ts-to-js/js/app/hero-di-inject-additional.component.js
`,`
`,`
Typescript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
+makeExample('cb-ts-to-js/js/app/hero-di-inject.component.js','parameters')(format="." ) a(id="host-query-metadata")
:marked
Alternatively, we can create a token with the `Inject` method and
add that to the constructor array in the annotations like this:
+makeExample('cb-ts-to-js/js/app/hero-di-inject.component.js','ctor')(format="." )
tr(style=top)
td
:marked
### Additional Injection Decorators
We can attach additional decorators to constructor parameters
to qualify the injection behavior. We can mark
optional dependencies with the [`@Optional`](../api/core/index/Optional-decorator.html),
inject host element attributes with [`@Attribute`](../api/core/index/Attribute-interface.html),
inject content child queries with [`@ContentChild`](../api/core/index/ContentChild-decorator.html)
and inject view child queries with [`@ViewChild`](../api/core/index/ViewChild-decorator.html)).
+makeExample('cb-ts-to-js/ts/app/hero-di-inject-additional.component.ts')(format="." )
td
:marked
### Additional Injection Metadata with Nested Arrays
To achieve the same effect in JavaScript, use the constructor array notation
in which the injection information precedes the constructor function itself.
Use the injection support functions `Attribute`, `Host`, `Optional`, `Self`, `SkipSelf` to qualify dependency injection behavior.
Use a nested array to combine injection functions.
+makeExample('cb-ts-to-js/js/app/hero-di-inject-additional.component.js')(format="." )
:marked
We can apply other additional parameter decorators such as
[`@Host`](../api/core/index/Host-decorator.html) and
[`@SkipSelf`](../api/core/index/SkipSelf-decorator.html) in the same way -
by adding `new ng.core.Host()` or `ng.core.SkipSelf()` in the
parameters array.
a(id="other-property-metadata")
.l-main-section .l-main-section
:marked :marked
## Host and Query Metadata ## Host and Query Metadata
- var top="vertical-align:top" ### Host Decorators
table(width="100%")
col(width="50%")
col(width="50%")
tr
th TypeScript
th ES5 JavaScript
tr(style=top)
td In Typescript and ES6 with decorators we can use host property decorators to bind a host
:marked element to a component or directive.
### Host Decorators The [`@HostBinding`](../api/core/index/HostBinding-interface.html) decorator
binds host element properties to component data properties.
The [`@HostListener`](../api/core/index/HostListener-interface.html) decorator binds
host element events to component event handlers.
We can use host property decorators to bind a host element to a component or directive. When using ES5/6 we add a `host` attribute to the component metadata to achieve the
The [`@HostBinding`](../api/core/index/HostBinding-interface.html) decorator same effect as `@HostBinding` and `@HostListener`.
binds host element properties to component data properties.
The [`@HostListener`](../api/core/index/HostListener-interface.html) decorator bimds
host element events to component event handlers.
+makeExample('cb-ts-to-js/ts/app/heroes-bindings.component.ts')(format="." ) The `host` value is an object whose properties are host property and listener bindings:
.alert.is-helpful * Each key follows regular Angular binding syntax: `[property]` for host bindings
:marked or `(event)` for host listeners.
In TypeScript we can also use `host` metadata * Each value identifies the corresponding component property or method.
instead of the `@HostBinding` and `@HostListener` property decorators.
td
:marked
### Host Metadata
We add a `host` attribute to the component metadata to achieve the +makeTabs(`
same effect as `@HostBinding` and `@HostListener`. cb-ts-to-js/ts/app/heroes-bindings.component.ts,
cb-ts-to-js/js-es6-decorators/app/heroes-bindings.component.es6,
cb-ts-to-js/js-es6/app/heroes-bindings.component.es6,
cb-ts-to-js/js/app/heroes-bindings.component.js
`,`
`,`
Typescript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
.alert.is-helpful
:marked
In TypeScript and ES6 with decorators we can also use the `queries` metadata
instead of the `@ViewChild` and `@ContentChild` property decorators.
The `host` value is an object whose properties are host property and listener bindings: :marked
### Query Decorators
* Each key follows regular Angular binding syntax: `[property]` for host bindings There are several property decorators for querying the descendants of
or `(event)` for host listeners. a component or directive.
* Each value identifies the corresponding component property or method.
+makeExample('cb-ts-to-js/js/app/heroes-bindings.component.js')(format="." ) The [`@ViewChild`](../api/core/index/ViewChild-decorator.html) and
[`@ViewChildren`](../api/core/index/ViewChildren-decorator.html) property decorators
allow a component to query instances of other components that are used in
its view.
tr(style=top) In ES5/6 JavaScript we access a component's view children by adding a `queries` attribute to
td the component metadata. It should be an object where:
:marked
### Query Decorators
There are several property decorators for querying the descendants of * Each key is the name of a component property that will hold the view children
a component or directive. * Each value is an instance of either `ViewChild` or `ViewChildren`.
The [`@ViewChild`](../api/core/index/ViewChild-decorator.html) and +makeTabs(`
[`@ViewChildren`](../api/core/index/ViewChildren-decorator.html) property decorators cb-ts-to-js/ts/app/heroes-queries.component.ts,
allow a component to query instances of other components that are used in cb-ts-to-js/js-es6-decorators/app/heroes-queries.component.es6,
its view. cb-ts-to-js/js-es6/app/heroes-queries.component.es6,
cb-ts-to-js/js/app/heroes-queries.component.js
`,`
view,
view,
view,
view
`,`
Typescript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
+makeExample('cb-ts-to-js/ts/app/heroes-queries.component.ts', 'view')(format="." ) :marked
The [`@ContentChild`](../api/core/index/ContentChild-decorator.html) and
[`@ContentChildren`](../api/core/index/ContentChildren-decorator.html) property decorators
allow a component to query instances of other components that have been projected
into its view from elsewhere.
:marked They can be added in the same way as [`@ViewChild`](../api/core/index/ViewChild-decorator.html) and
The [`@ContentChild`](../api/core/index/ContentChild-decorator.html) and [`@ViewChildren`](../api/core/index/ViewChildren-decorator.html).
[`@ContentChildren`](../api/core/index/ContentChildren-decorator.html) property decorators
allow a component to query instances of other components that have been projected
into its view from elsewhere.
+makeExample('cb-ts-to-js/ts/app/heroes-queries.component.ts', 'content')(format="." ) +makeTabs(`
cb-ts-to-js/ts/app/heroes-queries.component.ts,
.alert.is-helpful cb-ts-to-js/js-es6-decorators/app/heroes-queries.component.es6,
:marked cb-ts-to-js/js-es6/app/heroes-queries.component.es6,
In TypeScript we can also use the `queries` metadata cb-ts-to-js/js/app/heroes-queries.component.js
instead of the `@ViewChild` and `@ContentChild` property decorators. `,`
td content,
:marked content,
### Query Metadata content,
content
We access a component's view children by adding a `queries` attribute to `,`
the component metadata. It should be an object where: Typescript,
ES6 JavaScript with decorators,
* Each key is the name of a component property that will hold the view children ES6 JavaScript,
* Each value is an instance of either `ViewChild` or `ViewChildren`. ES5 JavaScript
`)
+makeExample('cb-ts-to-js/js/app/heroes-queries.component.js', 'view')(format="." )
:marked
We add *content* child queries to the same `queries` attribute
in the same manner, using instances of `ContentChild` or `ContentChildren`:
+makeExample('cb-ts-to-js/js/app/heroes-queries.component.js', 'content')(format="." )

View File

@ -120,7 +120,7 @@ function createShredExamplePackage(shredOptions) {
readFilesProcessor.basePath = "/"; readFilesProcessor.basePath = "/";
// Specify collections of source files that should contain the documentation to extract // Specify collections of source files that should contain the documentation to extract
var extns = ['*.ts', '*.html', '*.js', '*.css', '*.json', '*.dart', '*.yaml' ]; var extns = ['*.ts', '*.html', '*.js', '*.css', '*.json', '*.dart', '*.yaml', '*.es6' ];
var includeFiles = extns.map(function(extn) { var includeFiles = extns.map(function(extn) {
if (options.includeSubdirs) { if (options.includeSubdirs) {
return path.join(options.examplesDir, '**', extn); return path.join(options.examplesDir, '**', extn);

View File

@ -154,6 +154,7 @@ function getCommentInfo(extension) {
switch (extension) { switch (extension) {
case 'ts': case 'ts':
case 'js': case 'js':
case 'es6':
case 'dart': case 'dart':
commentInfo = { commentInfo = {
prefix: '//', prefix: '//',