feat(cb-ts-to-js): add es6 examples (#2606)
* 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 * docs(ts-to-js): ward's edits (incomplete) * docs(ts-to-js): add separate template files for some components * docs(cb-ts-to-js): refactor sample code
This commit is contained in:
commit
182493f877
11
gulpfile.js
11
gulpfile.js
|
@ -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/**/*.*');
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
},
|
},
|
||||||
|
|
|
@ -9,7 +9,7 @@ describe('TypeScript to Javascript tests', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display the basic component example', function () {
|
it('should display the basic component example', function () {
|
||||||
testTag('hero-view', 'Hero: Windstorm');
|
testTag('hero-view', 'Hero Detail: Windstorm');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display the component example with lifecycle methods', function () {
|
it('should display the component example with lifecycle methods', function () {
|
||||||
|
@ -36,7 +36,7 @@ describe('TypeScript to Javascript tests', function () {
|
||||||
|
|
||||||
it('should support component with inputs and outputs', function () {
|
it('should support component with inputs and outputs', function () {
|
||||||
let app = element(by.css('hero-io'));
|
let app = element(by.css('hero-io'));
|
||||||
let confirmComponent = app.element(by.css('my-confirm'));
|
let confirmComponent = app.element(by.css('app-confirm'));
|
||||||
|
|
||||||
confirmComponent.element(by.buttonText('OK')).click();
|
confirmComponent.element(by.buttonText('OK')).click();
|
||||||
expect(app.element(by.cssContainingText('span', 'OK clicked')).isPresent()).toBe(true);
|
expect(app.element(by.cssContainingText('span', 'OK clicked')).isPresent()).toBe(true);
|
||||||
|
@ -46,11 +46,11 @@ describe('TypeScript to Javascript tests', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support host bindings and host listeners', function() {
|
it('should support host bindings and host listeners', function() {
|
||||||
let app = element(by.css('heroes-bindings'));
|
let app = element(by.css('hero-host'));
|
||||||
let h1 = app.element(by.css('h1'));
|
let h1 = app.element(by.css('h1'));
|
||||||
|
|
||||||
expect(app.getAttribute('class')).toBe('heading');
|
expect(app.getAttribute('class')).toBe('heading');
|
||||||
expect(app.getAttribute('title')).toBe('Tooltip content');
|
expect(app.getAttribute('title')).toContain('Tooltip');
|
||||||
|
|
||||||
h1.click();
|
h1.click();
|
||||||
expect(h1.getAttribute('class')).toBe('active');
|
expect(h1.getAttribute('class')).toBe('active');
|
||||||
|
@ -61,12 +61,12 @@ describe('TypeScript to Javascript tests', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support content and view queries', function() {
|
it('should support content and view queries', function() {
|
||||||
let app = element(by.css('heroes-queries'));
|
let app = element(by.css('hero-queries'));
|
||||||
let windstorm = app.element(by.css('a-hero:first-child'));
|
let windstorm = app.element(by.css('view-child:first-child'));
|
||||||
|
|
||||||
app.element(by.buttonText('Activate')).click();
|
app.element(by.css('button')).click();
|
||||||
expect(windstorm.element(by.css('h2')).getAttribute('class')).toBe('active');
|
expect(windstorm.element(by.css('h2')).getAttribute('class')).toBe('active');
|
||||||
expect(windstorm.element(by.css('active-label')).getText()).toBe('Active');
|
expect(windstorm.element(by.css('content-child')).getText()).toBe('Active');
|
||||||
});
|
});
|
||||||
|
|
||||||
function testTag(selector: string, expectedText: string) {
|
function testTag(selector: string, expectedText: string) {
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"presets": [
|
||||||
|
"es2015",
|
||||||
|
"angular2"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
moduleId: module.id,
|
||||||
|
selector: 'my-app',
|
||||||
|
templateUrl: 'app.component.html',
|
||||||
|
styles: [
|
||||||
|
// See hero-di-inject-additional.component
|
||||||
|
'hero-host, hero-host-meta { border: 1px dashed black; display: block; padding: 4px;}',
|
||||||
|
'.heading {font-style: italic}'
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
title = 'ES6 JavaScript with Decorators';
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
<a id="toc"></a>
|
||||||
|
<h1>{{title}}</h1>
|
||||||
|
<a href="#class-metadata">Classes and Class Metadata</a><br>
|
||||||
|
<a href="#io-metadata">Input and Output Decorators</a><br>
|
||||||
|
<a href="#dependency-injection">Dependency Injection</a><br>
|
||||||
|
<a href="#host-metadata">Host Metadata</a><br>
|
||||||
|
<a href="#view-child-metadata">View and Child Metadata</a><br>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="class-metadata">Classes and Class Metadata</h4>
|
||||||
|
<hero-view></hero-view>
|
||||||
|
<hero-lifecycle></hero-lifecycle>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="io-metadata">Input and Output Metadata</h4>
|
||||||
|
<hero-io></hero-io>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="dependency-injection">Dependency Injection</h4>
|
||||||
|
<hero-di></hero-di>
|
||||||
|
<hero-di-inject></hero-di-inject>
|
||||||
|
<hero-di-inject-additional></hero-di-inject-additional>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="host-metadata">Host Metadata</h4>
|
||||||
|
<hero-host></hero-host>
|
||||||
|
<hero-host-meta></hero-host-meta>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="view-child-metadata">View and Child Metadata</h4>
|
||||||
|
<hero-queries></hero-queries>
|
|
@ -0,0 +1,55 @@
|
||||||
|
import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
import { ConfirmComponent } from './confirm.component';
|
||||||
|
// #docregion appimport
|
||||||
|
import { HeroComponent } from './hero.component';
|
||||||
|
// #enddocregion appimport
|
||||||
|
import { HeroComponent as HeroDIComponent } from './hero-di.component';
|
||||||
|
import { HeroComponent as HeroDIInjectComponent } from './hero-di-inject.component';
|
||||||
|
import { HeroComponent as HeroDIInjectAdditionalComponent } from './hero-di-inject-additional.component';
|
||||||
|
import { HeroHostComponent } from './hero-host.component';
|
||||||
|
import { HeroHostMetaComponent } from './hero-host-meta.component';
|
||||||
|
import { HeroIOComponent } from './hero-io.component';
|
||||||
|
import { HeroComponent as HeroLifecycleComponent } from './hero-lifecycle.component';
|
||||||
|
import { HeroQueriesComponent, ViewChildComponent, ContentChildComponent } from './hero-queries.component';
|
||||||
|
import { HeroTitleComponent } from './hero-title.component';
|
||||||
|
|
||||||
|
import { DataService } from './data.service';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
BrowserModule
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
AppComponent,
|
||||||
|
ConfirmComponent,
|
||||||
|
HeroComponent,
|
||||||
|
HeroDIComponent,
|
||||||
|
HeroDIInjectComponent,
|
||||||
|
HeroDIInjectAdditionalComponent,
|
||||||
|
HeroHostComponent, HeroHostMetaComponent,
|
||||||
|
HeroIOComponent,
|
||||||
|
HeroLifecycleComponent,
|
||||||
|
HeroQueriesComponent, ViewChildComponent, ContentChildComponent,
|
||||||
|
HeroTitleComponent
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
DataService,
|
||||||
|
{ provide: 'heroName', useValue: 'Windstorm' }
|
||||||
|
],
|
||||||
|
bootstrap: [ AppComponent ],
|
||||||
|
|
||||||
|
// schemas: [ NO_ERRORS_SCHEMA ] // helpful for debugging
|
||||||
|
})
|
||||||
|
export class AppModule { }
|
||||||
|
|
||||||
|
/* tslint:disable no-unused-variable */
|
||||||
|
// #docregion ng2import
|
||||||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
import {
|
||||||
|
LocationStrategy,
|
||||||
|
HashLocationStrategy
|
||||||
|
} from '@angular/common';
|
||||||
|
// #enddocregion ng2import
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
@Component({
|
||||||
|
moduleId: module.id,
|
||||||
|
selector: 'app-confirm',
|
||||||
|
templateUrl: 'confirm.component.html'
|
||||||
|
})
|
||||||
|
export class ConfirmComponent {
|
||||||
|
@Input() okMsg = '';
|
||||||
|
@Input('cancelMsg') notOkMsg = '';
|
||||||
|
@Output() ok = new EventEmitter();
|
||||||
|
@Output('cancel') notOk = new EventEmitter();
|
||||||
|
|
||||||
|
onOkClick() {
|
||||||
|
this.ok.emit(true);
|
||||||
|
}
|
||||||
|
onNotOkClick() {
|
||||||
|
this.notOk.emit(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion
|
|
@ -0,0 +1,6 @@
|
||||||
|
<button (click)="onOkClick()">
|
||||||
|
{{okMsg}}
|
||||||
|
</button>
|
||||||
|
<button (click)="onNotOkClick()">
|
||||||
|
{{notOkMsg}}
|
||||||
|
</button>
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class DataService {
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
getHeroName() {
|
||||||
|
return 'Windstorm';
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'hero-di-inject-additional',
|
||||||
|
template: `<hero-title title="Tour of Heroes"></hero-title>`
|
||||||
|
})
|
||||||
|
export class HeroComponent { }
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { Component, Inject } from '@angular/core';
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
@Component({
|
||||||
|
selector: 'hero-di-inject',
|
||||||
|
template: `<h1>Hero: {{name}}</h1>`
|
||||||
|
})
|
||||||
|
export class HeroComponent {
|
||||||
|
constructor(@Inject('heroName') name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { DataService } from './data.service';
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
@Component({
|
||||||
|
selector: 'hero-di',
|
||||||
|
template: `<h1>Hero: {{name}}</h1>`
|
||||||
|
})
|
||||||
|
export class HeroComponent {
|
||||||
|
name = '';
|
||||||
|
constructor(dataService: DataService) {
|
||||||
|
this.name = dataService.getHeroName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
@Component({
|
||||||
|
selector: 'hero-host-meta',
|
||||||
|
template: `
|
||||||
|
<h1 [class.active]="active">Hero Host in Metadata</h1>
|
||||||
|
<div>Heading clicks: {{clicks}}</div>
|
||||||
|
`,
|
||||||
|
host: {
|
||||||
|
// HostBindings to the <hero-host-meta> element
|
||||||
|
'[title]': 'title',
|
||||||
|
'[class.heading]': 'headingClass',
|
||||||
|
|
||||||
|
// HostListeners on the entire <hero-host-meta> element
|
||||||
|
'(click)': 'clicked()',
|
||||||
|
'(mouseenter)': 'enter($event)',
|
||||||
|
'(mouseleave)': 'leave($event)'
|
||||||
|
},
|
||||||
|
// Styles within (but excluding) the <hero-host-meta> element
|
||||||
|
styles: ['.active {background-color: coral;}']
|
||||||
|
})
|
||||||
|
export class HeroHostMetaComponent {
|
||||||
|
title = 'Hero Host in Metadata Tooltip';
|
||||||
|
headingClass = true;
|
||||||
|
|
||||||
|
active = false;
|
||||||
|
clicks = 0;
|
||||||
|
|
||||||
|
clicked() {
|
||||||
|
this.clicks += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enter(event: Event) {
|
||||||
|
this.active = true;
|
||||||
|
this.headingClass = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
leave(event: Event) {
|
||||||
|
this.active = false;
|
||||||
|
this.headingClass = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion
|
|
@ -0,0 +1,39 @@
|
||||||
|
import { Component, HostBinding, HostListener } from '@angular/core';
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
@Component({
|
||||||
|
selector: 'hero-host',
|
||||||
|
template: `
|
||||||
|
<h1 [class.active]="active">Hero Host in Decorators</h1>
|
||||||
|
<div>Heading clicks: {{clicks}}</div>
|
||||||
|
`,
|
||||||
|
// Styles within (but excluding) the <hero-host> element
|
||||||
|
styles: ['.active {background-color: yellow;}']
|
||||||
|
})
|
||||||
|
export class HeroHostComponent {
|
||||||
|
// HostBindings to the <hero-host> element
|
||||||
|
@HostBinding() title = 'Hero Host in Decorators Tooltip';
|
||||||
|
@HostBinding('class.heading') headingClass = true;
|
||||||
|
|
||||||
|
active = false;
|
||||||
|
clicks = 0;
|
||||||
|
|
||||||
|
// HostListeners on the entire <hero-host> element
|
||||||
|
@HostListener('click')
|
||||||
|
clicked() {
|
||||||
|
this.clicks += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('mouseenter', ['$event'])
|
||||||
|
enter(event: Event) {
|
||||||
|
this.active = true;
|
||||||
|
this.headingClass = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('mouseleave', ['$event'])
|
||||||
|
leave(event: Event) {
|
||||||
|
this.active = false;
|
||||||
|
this.headingClass = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'hero-io',
|
||||||
|
template: `
|
||||||
|
<app-confirm [okMsg]="'OK'"
|
||||||
|
[cancelMsg]="'Cancel'"
|
||||||
|
(ok)="onOk()"
|
||||||
|
(cancel)="onCancel()">
|
||||||
|
</app-confirm>
|
||||||
|
<span *ngIf="okClicked">OK clicked</span>
|
||||||
|
<span *ngIf="cancelClicked">Cancel clicked</span>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
export class HeroIOComponent {
|
||||||
|
okClicked = false;
|
||||||
|
cancelClicked = false;
|
||||||
|
|
||||||
|
onOk() {
|
||||||
|
this.okClicked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
onCancel() {
|
||||||
|
this.cancelClicked = true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
// #docregion
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'hero-lifecycle',
|
||||||
|
template: `<h1>Hero: {{name}}</h1>`
|
||||||
|
})
|
||||||
|
export class HeroComponent {
|
||||||
|
name = '';
|
||||||
|
ngOnInit() {
|
||||||
|
// todo: fetch from server async
|
||||||
|
setTimeout(() => this.name = 'Windstorm', 0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
ContentChild,
|
||||||
|
Input,
|
||||||
|
QueryList,
|
||||||
|
ViewChildren
|
||||||
|
} from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'content-child',
|
||||||
|
template: `
|
||||||
|
<span class="content-child" *ngIf="active">
|
||||||
|
Active
|
||||||
|
</span>`
|
||||||
|
})
|
||||||
|
export class ContentChildComponent {
|
||||||
|
active = false;
|
||||||
|
|
||||||
|
activate() {
|
||||||
|
this.active = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
|
||||||
|
// #docregion content
|
||||||
|
@Component({
|
||||||
|
selector: 'view-child',
|
||||||
|
template: `
|
||||||
|
<h2 [class.active]=active>
|
||||||
|
{{hero.name}}
|
||||||
|
<ng-content></ng-content>
|
||||||
|
</h2>`,
|
||||||
|
styles: ['.active {font-weight: bold; background-color: skyblue;}']
|
||||||
|
})
|
||||||
|
export class ViewChildComponent {
|
||||||
|
@Input() hero;
|
||||||
|
active = false;
|
||||||
|
|
||||||
|
@ContentChild(ContentChildComponent) content;
|
||||||
|
|
||||||
|
activate() {
|
||||||
|
this.active = !this.active;
|
||||||
|
this.content.activate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion content
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
|
||||||
|
// #docregion view
|
||||||
|
@Component({
|
||||||
|
selector: 'hero-queries',
|
||||||
|
template: `
|
||||||
|
<view-child *ngFor="let hero of heroData" [hero]="hero">
|
||||||
|
<content-child></content-child>
|
||||||
|
</view-child>
|
||||||
|
<button (click)="activate()">{{buttonLabel}} All</button>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
export class HeroQueriesComponent {
|
||||||
|
active = false;
|
||||||
|
heroData = [
|
||||||
|
{id: 1, name: 'Windstorm'},
|
||||||
|
{id: 2, name: 'LaughingGas'}
|
||||||
|
];
|
||||||
|
|
||||||
|
@ViewChildren(ViewChildComponent) views;
|
||||||
|
|
||||||
|
activate() {
|
||||||
|
this.active = !this.active;
|
||||||
|
this.views.forEach(
|
||||||
|
view => view.activate()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
get buttonLabel() {
|
||||||
|
return this.active ? 'Deactivate' : 'Activate';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion view
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { Attribute, Component, Inject, Optional } from '@angular/core';
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
// #docregion templateUrl
|
||||||
|
@Component({
|
||||||
|
moduleId: module.id,
|
||||||
|
selector: 'hero-title',
|
||||||
|
templateUrl: 'hero-title.component.html'
|
||||||
|
})
|
||||||
|
// #enddocregion templateUrl
|
||||||
|
export class HeroTitleComponent {
|
||||||
|
msg = '';
|
||||||
|
constructor(
|
||||||
|
@Inject('titlePrefix') @Optional() titlePrefix,
|
||||||
|
@Attribute('title') title
|
||||||
|
) {
|
||||||
|
this.titlePrefix = titlePrefix;
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
ok() {
|
||||||
|
this.msg = 'OK!';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
<!-- #docregion -->
|
||||||
|
<h1>{{titlePrefix}} {{title}}</h1>
|
||||||
|
<button (click)="ok()">OK</button>
|
||||||
|
<p>{{ msg }}</p>
|
|
@ -0,0 +1,14 @@
|
||||||
|
// #docregion metadata
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'hero-view',
|
||||||
|
template: '<h1>{{title}}: {{getName()}}</h1>'
|
||||||
|
})
|
||||||
|
// #docregion appexport, class
|
||||||
|
export class HeroComponent {
|
||||||
|
title = 'Hero Detail';
|
||||||
|
getName() {return 'Windstorm'; }
|
||||||
|
}
|
||||||
|
// #enddocregion appexport, class
|
||||||
|
// #enddocregion metadata
|
|
@ -0,0 +1,4 @@
|
||||||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
import { AppModule } from './app.module';
|
||||||
|
|
||||||
|
platformBrowserDynamic().bootstrapModule(AppModule);
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"build": "build:babel",
|
||||||
|
"run": "http-server:e2e"
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
<!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">
|
||||||
|
<title>TypeScript to JavaScript</title>
|
||||||
|
|
||||||
|
<!-- 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>
|
||||||
|
<my-app>Loading...</my-app>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"description": "TypeScript to JavaScript",
|
||||||
|
"files":[
|
||||||
|
"!**/*.d.ts",
|
||||||
|
"!**/*.js"
|
||||||
|
],
|
||||||
|
"tags":["cookbook"]
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"presets": [
|
||||||
|
"es2015"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
export class AppComponent {
|
||||||
|
constructor() {
|
||||||
|
this.title = 'Plain ES6 JavaScript';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AppComponent.annotations = [
|
||||||
|
new Component({
|
||||||
|
moduleId: module.id,
|
||||||
|
selector: 'my-app',
|
||||||
|
templateUrl: 'app.component.html',
|
||||||
|
styles: [
|
||||||
|
// See hero-di-inject-additional.component
|
||||||
|
'hero-host { border: 1px dashed black; display: block; padding: 4px;}',
|
||||||
|
'.heading {font-style: italic}'
|
||||||
|
]
|
||||||
|
})
|
||||||
|
];
|
|
@ -0,0 +1,30 @@
|
||||||
|
<a id="toc"></a>
|
||||||
|
<h1>{{title}}</h1>
|
||||||
|
<a href="#class-metadata">Classes and Class Metadata</a><br>
|
||||||
|
<a href="#io-metadata">Input and Output Metadata</a><br>
|
||||||
|
<a href="#dependency-injection">Dependency Injection</a><br>
|
||||||
|
<a href="#host-metadata">Host Metadata</a><br>
|
||||||
|
<a href="#view-child-metadata">View and Child Metadata</a><br>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="class-metadata">Classes and Class Metadata</h4>
|
||||||
|
<hero-view></hero-view>
|
||||||
|
<hero-lifecycle></hero-lifecycle>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="io-metadata">Input and Output Metadata</h4>
|
||||||
|
<hero-io></hero-io>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="dependency-injection">Dependency Injection</h4>
|
||||||
|
<hero-di></hero-di>
|
||||||
|
<hero-di-inject></hero-di-inject>
|
||||||
|
<hero-di-inject-additional></hero-di-inject-additional>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="host-metadata">Host Metadata</h4>
|
||||||
|
<hero-host></hero-host>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="view-child-metadata">View and Child Metadata</h4>
|
||||||
|
<hero-queries></hero-queries>
|
|
@ -0,0 +1,56 @@
|
||||||
|
import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
import { ConfirmComponent } from './confirm.component';
|
||||||
|
// #docregion appimport
|
||||||
|
import { HeroComponent } from './hero.component';
|
||||||
|
|
||||||
|
// #enddocregion appimport
|
||||||
|
import { HeroComponent as HeroDIComponent } from './hero-di.component';
|
||||||
|
import { HeroComponent as HeroDIInjectComponent } from './hero-di-inject.component';
|
||||||
|
import { HeroComponent as HeroDIInjectAdditionalComponent } from './hero-di-inject-additional.component';
|
||||||
|
import { HeroHostComponent } from './hero-host.component';
|
||||||
|
import { HeroIOComponent } from './hero-io.component';
|
||||||
|
import { HeroComponent as HeroLifecycleComponent } from './hero-lifecycle.component';
|
||||||
|
import { HeroQueriesComponent, ViewChildComponent, ContentChildComponent } from './hero-queries.component';
|
||||||
|
import { HeroTitleComponent } from './hero-title.component';
|
||||||
|
|
||||||
|
import { DataService } from './data.service';
|
||||||
|
|
||||||
|
export class AppModule { }
|
||||||
|
|
||||||
|
AppModule.annotations = [
|
||||||
|
new NgModule({
|
||||||
|
imports: [ BrowserModule],
|
||||||
|
declarations: [
|
||||||
|
AppComponent,
|
||||||
|
ConfirmComponent,
|
||||||
|
HeroComponent,
|
||||||
|
HeroDIComponent,
|
||||||
|
HeroDIInjectComponent,
|
||||||
|
HeroDIInjectAdditionalComponent,
|
||||||
|
HeroHostComponent,
|
||||||
|
HeroIOComponent,
|
||||||
|
HeroLifecycleComponent,
|
||||||
|
HeroQueriesComponent, ViewChildComponent, ContentChildComponent,
|
||||||
|
HeroTitleComponent
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
DataService,
|
||||||
|
{ provide: 'heroName', useValue: 'Windstorm' }
|
||||||
|
],
|
||||||
|
bootstrap: [ AppComponent ],
|
||||||
|
|
||||||
|
// schemas: [ NO_ERRORS_SCHEMA ] // helpful for debugging
|
||||||
|
})
|
||||||
|
]
|
||||||
|
|
||||||
|
/* tslint:disable no-unused-variable */
|
||||||
|
// #docregion ng2import
|
||||||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
import {
|
||||||
|
LocationStrategy,
|
||||||
|
HashLocationStrategy
|
||||||
|
} from '@angular/common';
|
||||||
|
// #enddocregion ng2import
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { Component, EventEmitter } from '@angular/core';
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
export class ConfirmComponent {
|
||||||
|
constructor(){
|
||||||
|
this.ok = new EventEmitter();
|
||||||
|
this.notOk = new EventEmitter();
|
||||||
|
}
|
||||||
|
onOkClick() {
|
||||||
|
this.ok.emit(true);
|
||||||
|
}
|
||||||
|
onNotOkClick() {
|
||||||
|
this.notOk.emit(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfirmComponent.annotations = [
|
||||||
|
new Component({
|
||||||
|
moduleId: module.id,
|
||||||
|
selector: 'app-confirm',
|
||||||
|
templateUrl: 'confirm.component.html',
|
||||||
|
inputs: [
|
||||||
|
'okMsg',
|
||||||
|
'notOkMsg: cancelMsg'
|
||||||
|
],
|
||||||
|
outputs: [
|
||||||
|
'ok',
|
||||||
|
'notOk: cancel'
|
||||||
|
]
|
||||||
|
})
|
||||||
|
];
|
||||||
|
// #enddocregion
|
|
@ -0,0 +1,6 @@
|
||||||
|
<button (click)="onOkClick()">
|
||||||
|
{{okMsg}}
|
||||||
|
</button>
|
||||||
|
<button (click)="onNotOkClick()">
|
||||||
|
{{notOkMsg}}
|
||||||
|
</button>
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
export class DataService {
|
||||||
|
constructor() {
|
||||||
|
}
|
||||||
|
getHeroName() {
|
||||||
|
return 'Windstorm';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DataService.annotations = [
|
||||||
|
new Injectable()
|
||||||
|
];
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
export class HeroComponent { }
|
||||||
|
|
||||||
|
HeroComponent.annotations = [
|
||||||
|
new Component({
|
||||||
|
selector: 'hero-di-inject-additional',
|
||||||
|
template: `<hero-title title="Tour of Heroes"></hero-title>`
|
||||||
|
})
|
||||||
|
];
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { Component, Inject } from '@angular/core';
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
export class HeroComponent {
|
||||||
|
constructor(name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HeroComponent.annotations = [
|
||||||
|
new Component({
|
||||||
|
selector: 'hero-di-inject',
|
||||||
|
template: `<h1>Hero: {{name}}</h1>`
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
HeroComponent.parameters = [
|
||||||
|
[new Inject('heroName')]
|
||||||
|
];
|
||||||
|
// #enddocregion
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { DataService } from './data.service';
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
export class HeroComponent {
|
||||||
|
constructor(dataService) {
|
||||||
|
this.name = dataService.getHeroName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HeroComponent.annotations = [
|
||||||
|
new Component({
|
||||||
|
selector: 'hero-di',
|
||||||
|
template: `<h1>Hero: {{name}}</h1>`
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
HeroComponent.parameters = [
|
||||||
|
[DataService]
|
||||||
|
];
|
||||||
|
|
||||||
|
// #enddocregion
|
|
@ -0,0 +1,50 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
export class HeroHostComponent {
|
||||||
|
constructor() {
|
||||||
|
this.active = false;
|
||||||
|
this.clicks = 0;
|
||||||
|
this.headingClass = true;
|
||||||
|
this.title = 'Hero Host Tooltip';
|
||||||
|
}
|
||||||
|
|
||||||
|
clicked() {
|
||||||
|
this.clicks += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enter(event) {
|
||||||
|
this.active = true;
|
||||||
|
this.headingClass = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
leave(event) {
|
||||||
|
this.active = false;
|
||||||
|
this.headingClass = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #docregion metadata
|
||||||
|
HeroHostComponent.annotations = [
|
||||||
|
new Component({
|
||||||
|
selector: 'hero-host',
|
||||||
|
template: `
|
||||||
|
<h1 [class.active]="active">Hero Host</h1>
|
||||||
|
<div>Heading clicks: {{clicks}}</div>
|
||||||
|
`,
|
||||||
|
host: {
|
||||||
|
// HostBindings to the <hero-host> element
|
||||||
|
'[title]': 'title',
|
||||||
|
'[class.heading]': 'headingClass',
|
||||||
|
'(click)': 'clicked()',
|
||||||
|
|
||||||
|
// HostListeners on the entire <hero-host> element
|
||||||
|
'(mouseenter)': 'enter($event)',
|
||||||
|
'(mouseleave)': 'leave($event)'
|
||||||
|
},
|
||||||
|
// Styles within (but excluding) the <hero-host> element
|
||||||
|
styles: ['.active {background-color: yellow;}']
|
||||||
|
})
|
||||||
|
];
|
||||||
|
// #docregion metadata
|
||||||
|
// #enddocregion
|
|
@ -0,0 +1,31 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
export class HeroIOComponent {
|
||||||
|
constructor() {
|
||||||
|
this.okClicked = false;
|
||||||
|
this.cancelClicked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
onOk() {
|
||||||
|
this.okClicked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
onCancel() {
|
||||||
|
this.cancelClicked = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HeroIOComponent.annotations = [
|
||||||
|
new Component({
|
||||||
|
selector: 'hero-io',
|
||||||
|
template: `
|
||||||
|
<app-confirm [okMsg]="'OK'"
|
||||||
|
[cancelMsg]="'Cancel'"
|
||||||
|
(ok)="onOk()"
|
||||||
|
(cancel)="onCancel()">
|
||||||
|
</app-confirm>
|
||||||
|
<span *ngIf="okClicked">OK clicked</span>
|
||||||
|
<span *ngIf="cancelClicked">Cancel clicked</span>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
];
|
|
@ -0,0 +1,15 @@
|
||||||
|
// #docregion
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
export class HeroComponent {
|
||||||
|
ngOnInit() {
|
||||||
|
// todo: fetch from server async
|
||||||
|
setTimeout(() => this.name = 'Windstorm', 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HeroComponent.annotations = [
|
||||||
|
new Component({
|
||||||
|
selector: 'hero-lifecycle',
|
||||||
|
template: `<h1>Hero: {{name}}</h1>`
|
||||||
|
})
|
||||||
|
];
|
|
@ -0,0 +1,97 @@
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
ContentChild,
|
||||||
|
Input,
|
||||||
|
QueryList,
|
||||||
|
ViewChildren
|
||||||
|
} from '@angular/core';
|
||||||
|
|
||||||
|
export class ContentChildComponent {
|
||||||
|
constructor() {
|
||||||
|
this.active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
activate() {
|
||||||
|
this.active = !this.active;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentChildComponent.annotations = [
|
||||||
|
new Component({
|
||||||
|
selector: 'content-child',
|
||||||
|
template: `
|
||||||
|
<span class="content-child" *ngIf="active">
|
||||||
|
Active
|
||||||
|
</span>`
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
|
||||||
|
// #docregion content
|
||||||
|
export class ViewChildComponent {
|
||||||
|
constructor() {
|
||||||
|
this.active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
activate() {
|
||||||
|
this.active = !this.active;
|
||||||
|
this.content.activate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewChildComponent.annotations = [
|
||||||
|
new Component({
|
||||||
|
selector: 'view-child',
|
||||||
|
template: `<h2 [class.active]=active>
|
||||||
|
{{hero.name}}
|
||||||
|
<ng-content></ng-content>
|
||||||
|
</h2>`,
|
||||||
|
styles: ['.active {font-weight: bold; background-color: skyblue;}'],
|
||||||
|
inputs: ['hero'],
|
||||||
|
queries: {
|
||||||
|
content: new ContentChild(ContentChildComponent)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
];
|
||||||
|
// #enddocregion content
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
|
||||||
|
// #docregion view
|
||||||
|
export class HeroQueriesComponent {
|
||||||
|
constructor(){
|
||||||
|
this.active = false;
|
||||||
|
this.heroData = [
|
||||||
|
{id: 1, name: 'Windstorm'},
|
||||||
|
{id: 2, name: 'LaughingGas'}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
activate() {
|
||||||
|
this.active = !this.active;
|
||||||
|
this.views.forEach(
|
||||||
|
view => view.activate()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
get buttonLabel() {
|
||||||
|
return this.active ? 'Deactivate' : 'Activate';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HeroQueriesComponent.annotations = [
|
||||||
|
new Component({
|
||||||
|
selector: 'hero-queries',
|
||||||
|
template: `
|
||||||
|
<view-child *ngFor="let hero of heroData" [hero]="hero">
|
||||||
|
<content-child></content-child>
|
||||||
|
</view-child>
|
||||||
|
<button (click)="activate()">{{buttonLabel}} All</button>
|
||||||
|
`,
|
||||||
|
queries: {
|
||||||
|
views: new ViewChildren(ViewChildComponent)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
];
|
||||||
|
// #enddocregion view
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { Attribute, Component, Inject, Optional } from '@angular/core';
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
export class HeroTitleComponent {
|
||||||
|
constructor(titlePrefix, title) {
|
||||||
|
this.titlePrefix = titlePrefix;
|
||||||
|
this.title = title;
|
||||||
|
this.msg = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
ok() {
|
||||||
|
this.msg = 'OK!';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #docregion templateUrl
|
||||||
|
HeroTitleComponent.annotations = [
|
||||||
|
new Component({
|
||||||
|
moduleId: module.id,
|
||||||
|
selector: 'hero-title',
|
||||||
|
templateUrl: 'hero-title.component.html'
|
||||||
|
})
|
||||||
|
];
|
||||||
|
// #enddocregion templateUrl
|
||||||
|
|
||||||
|
HeroTitleComponent.parameters = [
|
||||||
|
[new Optional(), new Inject('titlePrefix')],
|
||||||
|
[new Attribute('title')]
|
||||||
|
];
|
|
@ -0,0 +1,4 @@
|
||||||
|
<!-- #docregion -->
|
||||||
|
<h1>{{titlePrefix}} {{title}}</h1>
|
||||||
|
<button (click)="ok()">OK</button>
|
||||||
|
<p>{{ msg }}</p>
|
|
@ -0,0 +1,20 @@
|
||||||
|
// #docplaster
|
||||||
|
// #docregion metadata
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
// #docregion appexport, class
|
||||||
|
export class HeroComponent {
|
||||||
|
constructor() {
|
||||||
|
this.title = 'Hero Detail';
|
||||||
|
}
|
||||||
|
getName() {return 'Windstorm'; }
|
||||||
|
}
|
||||||
|
// #enddocregion appexport, class
|
||||||
|
|
||||||
|
HeroComponent.annotations = [
|
||||||
|
new Component({
|
||||||
|
selector: 'hero-view',
|
||||||
|
template: '<h1>{{title}}: {{getName()}}</h1>'
|
||||||
|
})
|
||||||
|
];
|
||||||
|
// #enddocregion metadata
|
|
@ -0,0 +1,4 @@
|
||||||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
import { AppModule } from './app.module';
|
||||||
|
|
||||||
|
platformBrowserDynamic().bootstrapModule(AppModule);
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"build": "build:babel",
|
||||||
|
"run": "http-server:e2e"
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
<!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">
|
||||||
|
<title>TypeScript to JavaScript</title>
|
||||||
|
|
||||||
|
<!-- 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>
|
||||||
|
<my-app>Loading...</my-app>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"description": "TypeScript to JavaScript",
|
||||||
|
"files":[
|
||||||
|
"!**/*.d.ts",
|
||||||
|
"!**/*.js"
|
||||||
|
],
|
||||||
|
"tags":["cookbook"]
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
<a id="toc"></a>
|
||||||
|
<h1>{{title}}</h1>
|
||||||
|
<a href="#class-metadata">Classes and Class Metadata</a><br>
|
||||||
|
<a href="#interfaces">Interfaces</a><br>
|
||||||
|
<a href="#io-metadata">Input and Output Metadata</a><br>
|
||||||
|
<a href="#dependency-injection">Dependency Injection</a><br>
|
||||||
|
<a href="#host-metadata">Host Metadata</a><br>
|
||||||
|
<a href="#view-child-metadata">View and Child Metadata</a><br>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="class-metadata">Classes and Class Metadata</h4>
|
||||||
|
<hero-view></hero-view>
|
||||||
|
<h4 id="class-metadata-dsl">Classes and Class Metadata (DSL)</h4>
|
||||||
|
<hero-view-dsl></hero-view-dsl>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="interfaces">Interfaces</h4>
|
||||||
|
<hero-lifecycle></hero-lifecycle>
|
||||||
|
<h4 id="interfaces-dsl">Interfaces (DSL)</h4>
|
||||||
|
<hero-lifecycle-dsl></hero-lifecycle-dsl>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="io-metadata">Input and Output Metadata</h4>
|
||||||
|
<hero-io></hero-io>
|
||||||
|
<h4 id="io-metadata-dsl">Input and Output Metadata (DSL)</h4>
|
||||||
|
<hero-io-dsl></hero-io-dsl>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="dependency-injection">Dependency Injection</h4>
|
||||||
|
<hero-di></hero-di>
|
||||||
|
<hero-di-inject></hero-di-inject>
|
||||||
|
<hero-di-inject-additional></hero-di-inject-additional>
|
||||||
|
|
||||||
|
<h4 id="dependency-injection-dsl">Dependency Injection (DSL)</h4>
|
||||||
|
<hero-di-dsl></hero-di-dsl>
|
||||||
|
<hero-di-inject-dsl></hero-di-inject-dsl>
|
||||||
|
<hero-di-inject-additional-dsl></hero-di-inject-additional-dsl>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="host-metadata">Host Metadata</h4>
|
||||||
|
<hero-host></hero-host>
|
||||||
|
<h4 id="host-metadata-dsl">Host Metadata (DSL)</h4>
|
||||||
|
<hero-host-dsl></hero-host-dsl>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="view-child-metadata">View and Child Metadata (DSL)</h4>
|
||||||
|
<hero-queries></hero-queries>
|
|
@ -0,0 +1,20 @@
|
||||||
|
(function(app) {
|
||||||
|
|
||||||
|
app.AppComponent = AppComponent;
|
||||||
|
function AppComponent() {
|
||||||
|
this.title = 'ES5 JavaScript';
|
||||||
|
}
|
||||||
|
|
||||||
|
AppComponent.annotations = [
|
||||||
|
new ng.core.Component({
|
||||||
|
selector: 'my-app',
|
||||||
|
templateUrl: 'app/app.component.html',
|
||||||
|
styles: [
|
||||||
|
// See hero-di-inject-additional.component
|
||||||
|
'hero-host, hero-host-dsl { border: 1px dashed black; display: block; padding: 4px;}',
|
||||||
|
'.heading {font-style: italic}'
|
||||||
|
]
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
})(window.app = window.app || {});
|
|
@ -0,0 +1,46 @@
|
||||||
|
(function(app) {
|
||||||
|
|
||||||
|
app.AppModule = AppModule;
|
||||||
|
function AppModule() { }
|
||||||
|
|
||||||
|
AppModule.annotations = [
|
||||||
|
new ng.core.NgModule({
|
||||||
|
imports: [ ng.platformBrowser.BrowserModule ],
|
||||||
|
declarations: [
|
||||||
|
app.AppComponent,
|
||||||
|
app.ConfirmComponent, app.ConfirmDslComponent,
|
||||||
|
app.HeroComponent, app.HeroDslComponent,
|
||||||
|
app.HeroDIComponent, app.HeroDIDslComponent,
|
||||||
|
app.HeroDIInjectComponent, app.HeroDIInjectDslComponent,
|
||||||
|
app.HeroDIInjectAdditionalComponent, app.HeroDIInjectAdditionalDslComponent,
|
||||||
|
app.HeroHostComponent, app.HeroHostDslComponent,
|
||||||
|
app.HeroIOComponent, app.HeroIODslComponent,
|
||||||
|
app.HeroLifecycleComponent, app.HeroLifecycleDslComponent,
|
||||||
|
app.heroQueries.HeroQueriesComponent, app.heroQueries.ViewChildComponent, app.heroQueries.ContentChildComponent,
|
||||||
|
app.HeroTitleComponent, app.HeroTitleDslComponent
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
app.DataService,
|
||||||
|
{ provide: 'heroName', useValue: 'Windstorm' }
|
||||||
|
],
|
||||||
|
bootstrap: [ app.AppComponent ],
|
||||||
|
|
||||||
|
// schemas: [ ng.core.NO_ERRORS_SCHEMA ] // helpful for debugging!
|
||||||
|
})
|
||||||
|
]
|
||||||
|
|
||||||
|
})(window.app = window.app || {});
|
||||||
|
|
||||||
|
|
||||||
|
///// For documentation only /////
|
||||||
|
(function () {
|
||||||
|
// #docregion appimport
|
||||||
|
var HeroComponent = app.HeroComponent;
|
||||||
|
// #enddocregion appimport
|
||||||
|
|
||||||
|
// #docregion ng2import
|
||||||
|
var platformBrowserDynamic = ng.platformBrowserDynamic.platformBrowserDynamic;
|
||||||
|
var LocationStrategy = ng.common.LocationStrategy;
|
||||||
|
var HashLocationStrategy = ng.common.HashLocationStrategy;
|
||||||
|
// #enddocregion ng2import
|
||||||
|
})
|
|
@ -0,0 +1,6 @@
|
||||||
|
<button (click)="onOkClick()">
|
||||||
|
{{okMsg}}
|
||||||
|
</button>
|
||||||
|
<button (click)="onNotOkClick()">
|
||||||
|
{{notOkMsg}}
|
||||||
|
</button>
|
|
@ -0,0 +1,73 @@
|
||||||
|
(function(app) {
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
app.ConfirmComponent = ConfirmComponent;
|
||||||
|
|
||||||
|
ConfirmComponent.annotations = [
|
||||||
|
new ng.core.Component({
|
||||||
|
selector: 'app-confirm',
|
||||||
|
templateUrl: 'app/confirm.component.html',
|
||||||
|
inputs: [
|
||||||
|
'okMsg',
|
||||||
|
'notOkMsg: cancelMsg'
|
||||||
|
],
|
||||||
|
outputs: [
|
||||||
|
'ok',
|
||||||
|
'notOk: cancel'
|
||||||
|
]
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
function ConfirmComponent() {
|
||||||
|
this.ok = new ng.core.EventEmitter();
|
||||||
|
this.notOk = new ng.core.EventEmitter();
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfirmComponent.prototype.onOkClick = function() {
|
||||||
|
this.ok.emit(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfirmComponent.prototype.onNotOkClick = function() {
|
||||||
|
this.notOk.emit(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #enddocregion
|
||||||
|
|
||||||
|
})(window.app = window.app || {});
|
||||||
|
|
||||||
|
/////// DSL version ////////
|
||||||
|
|
||||||
|
(function(app) {
|
||||||
|
|
||||||
|
// #docregion dsl
|
||||||
|
app.ConfirmDslComponent = ng.core.Component({
|
||||||
|
selector: 'app-confirm-dsl',
|
||||||
|
templateUrl: 'app/confirm.component.html',
|
||||||
|
inputs: [
|
||||||
|
'okMsg',
|
||||||
|
'notOkMsg: cancelMsg'
|
||||||
|
],
|
||||||
|
outputs: [
|
||||||
|
'ok',
|
||||||
|
'notOk: cancel'
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.Class({
|
||||||
|
constructor: function ConfirmDslComponent() {
|
||||||
|
this.ok = new ng.core.EventEmitter();
|
||||||
|
this.notOk = new ng.core.EventEmitter();
|
||||||
|
},
|
||||||
|
|
||||||
|
onOkClick: function() {
|
||||||
|
this.ok.emit(true);
|
||||||
|
},
|
||||||
|
|
||||||
|
onNotOkClick: function() {
|
||||||
|
this.notOk.emit(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// #enddocregion dsl
|
||||||
|
|
||||||
|
})(window.app = window.app || {});
|
|
@ -1,13 +1,10 @@
|
||||||
(function(app) {
|
(function(app) {
|
||||||
|
|
||||||
function DataService() {
|
app.DataService = DataService;
|
||||||
}
|
function DataService() { }
|
||||||
DataService.annotations = [
|
|
||||||
new ng.core.Injectable()
|
|
||||||
];
|
|
||||||
DataService.prototype.getHeroName = function() {
|
DataService.prototype.getHeroName = function() {
|
||||||
return 'Windstorm';
|
return 'Windstorm';
|
||||||
};
|
};
|
||||||
app.DataService = DataService;
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
})(window.app = window.app || {});
|
||||||
|
|
|
@ -1,50 +1,26 @@
|
||||||
(function(app) {
|
(function(app) {
|
||||||
|
|
||||||
// #docregion
|
app.HeroDIInjectAdditionalComponent = HeroDIInjectAdditionalComponent;
|
||||||
var TitleComponent = ng.core.Component({
|
|
||||||
selector: 'hero-title',
|
|
||||||
template:
|
|
||||||
'<h1>{{titlePrefix}} {{title}}</h1>' +
|
|
||||||
'<button (click)="ok()">OK</button>' +
|
|
||||||
'<p>{{ msg }}</p>'
|
|
||||||
}).Class({
|
|
||||||
constructor: [
|
|
||||||
[
|
|
||||||
new ng.core.Optional(),
|
|
||||||
new ng.core.Inject('titlePrefix')
|
|
||||||
],
|
|
||||||
new ng.core.Attribute('title'),
|
|
||||||
function(titlePrefix, title) {
|
|
||||||
this.titlePrefix = titlePrefix;
|
|
||||||
this.title = title;
|
|
||||||
this.msg = '';
|
|
||||||
}
|
|
||||||
],
|
|
||||||
ok: function() {
|
|
||||||
this.msg = 'OK!';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// #enddocregion
|
|
||||||
|
|
||||||
var AppComponent = ng.core.Component({
|
HeroDIInjectAdditionalComponent.annotations = [
|
||||||
|
new ng.core.Component({
|
||||||
selector: 'hero-di-inject-additional',
|
selector: 'hero-di-inject-additional',
|
||||||
template: '<hero-title title="Tour of Heroes">' +
|
template: '<hero-title title="Tour of Heroes"></hero-title>'
|
||||||
'</hero-title>'
|
|
||||||
}).Class({
|
|
||||||
constructor: function() { }
|
|
||||||
});
|
|
||||||
|
|
||||||
app.HeroesDIInjectAdditionalModule =
|
|
||||||
ng.core.NgModule({
|
|
||||||
imports: [ ng.platformBrowser.BrowserModule ],
|
|
||||||
declarations: [
|
|
||||||
AppComponent,
|
|
||||||
TitleComponent
|
|
||||||
],
|
|
||||||
bootstrap: [ AppComponent ]
|
|
||||||
})
|
})
|
||||||
.Class({
|
];
|
||||||
constructor: function() {}
|
|
||||||
|
function HeroDIInjectAdditionalComponent() {}
|
||||||
|
|
||||||
|
})(window.app = window.app || {});
|
||||||
|
|
||||||
|
////// DSL Version /////////
|
||||||
|
(function(app) {
|
||||||
|
|
||||||
|
app.HeroDIInjectAdditionalDslComponent = ng.core.Component({
|
||||||
|
selector: 'hero-di-inject-additional-dsl',
|
||||||
|
template: '<hero-title-dsl title="Tour of Heroes"></hero-title-dsl>'
|
||||||
|
}).Class({
|
||||||
|
constructor: function HeroDIInjectAdditionalDslComponent() { }
|
||||||
});
|
});
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
})(window.app = window.app || {});
|
||||||
|
|
|
@ -1,57 +1,41 @@
|
||||||
(function(app) {
|
(function(app) {
|
||||||
|
|
||||||
// #docregion parameters
|
// #docregion
|
||||||
function HeroComponent(name) {
|
app.HeroDIInjectComponent = HeroDIInjectComponent;
|
||||||
this.name = name;
|
|
||||||
}
|
HeroDIInjectComponent.annotations = [
|
||||||
HeroComponent.parameters = [
|
|
||||||
'heroName'
|
|
||||||
];
|
|
||||||
HeroComponent.annotations = [
|
|
||||||
new ng.core.Component({
|
new ng.core.Component({
|
||||||
selector: 'hero-di-inject',
|
selector: 'hero-di-inject',
|
||||||
template: '<h1>Hero: {{name}}</h1>'
|
template: '<h1>Hero: {{name}}</h1>'
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
// #enddocregion parameters
|
|
||||||
|
|
||||||
app.HeroesDIInjectModule =
|
HeroDIInjectComponent.parameters = [ 'heroName' ];
|
||||||
ng.core.NgModule({
|
|
||||||
imports: [ ng.platformBrowser.BrowserModule ],
|
function HeroDIInjectComponent(name) {
|
||||||
providers: [ { provide: 'heroName', useValue: 'Windstorm' } ],
|
this.name = name;
|
||||||
declarations: [ HeroComponent ],
|
}
|
||||||
bootstrap: [ HeroComponent ]
|
// #enddocregion
|
||||||
})
|
|
||||||
.Class({
|
|
||||||
constructor: function() {}
|
|
||||||
});
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
})(window.app = window.app || {});
|
||||||
|
|
||||||
|
/////// DSL version ////////
|
||||||
|
|
||||||
(function(app) {
|
(function(app) {
|
||||||
// #docregion ctor
|
|
||||||
var HeroComponent = ng.core.Component({
|
// #docregion dsl
|
||||||
selector: 'hero-di-inline2',
|
app.HeroDIInjectDslComponent = ng.core.Component({
|
||||||
|
selector: 'hero-di-inject-dsl',
|
||||||
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 HeroDIInjectDslComponent(name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}]
|
}
|
||||||
});
|
]
|
||||||
// #enddocregion ctor
|
|
||||||
|
|
||||||
app.HeroesDIInjectModule2 =
|
|
||||||
ng.core.NgModule({
|
|
||||||
imports: [ ng.platformBrowser.BrowserModule ],
|
|
||||||
providers: [ { provide: 'heroName', useValue: 'Bombasto' } ],
|
|
||||||
declarations: [ HeroComponent ],
|
|
||||||
bootstrap: [ HeroComponent ]
|
|
||||||
})
|
|
||||||
.Class({
|
|
||||||
constructor: function() {}
|
|
||||||
});
|
});
|
||||||
|
// #enddocregion dsl
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
})(window.app = window.app || {});
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
(function(app) {
|
|
||||||
// #docregion
|
|
||||||
var HeroComponent = ng.core.Component({
|
|
||||||
selector: 'hero-di-inline',
|
|
||||||
template: '<h1>Hero: {{name}}</h1>'
|
|
||||||
})
|
|
||||||
.Class({
|
|
||||||
constructor:
|
|
||||||
[app.DataService,
|
|
||||||
function(service) {
|
|
||||||
this.name = service.getHeroName();
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
// #enddocregion
|
|
||||||
|
|
||||||
app.HeroDIInlineModule =
|
|
||||||
ng.core.NgModule({
|
|
||||||
imports: [ ng.platformBrowser.BrowserModule ],
|
|
||||||
providers: [ app.DataService ],
|
|
||||||
declarations: [ HeroComponent ],
|
|
||||||
bootstrap: [ HeroComponent ]
|
|
||||||
})
|
|
||||||
.Class({
|
|
||||||
constructor: function() {}
|
|
||||||
});
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
|
|
@ -1,31 +1,43 @@
|
||||||
(function(app) {
|
(function(app) {
|
||||||
|
|
||||||
// #docregion
|
// #docregion
|
||||||
app.HeroDIComponent = HeroComponent;
|
app.HeroDIComponent = HeroDIComponent;
|
||||||
|
|
||||||
function HeroComponent(dataService) {
|
HeroDIComponent.annotations = [
|
||||||
this.name = dataService.getHeroName();
|
|
||||||
}
|
|
||||||
HeroComponent.parameters = [
|
|
||||||
app.DataService
|
|
||||||
];
|
|
||||||
HeroComponent.annotations = [
|
|
||||||
new ng.core.Component({
|
new ng.core.Component({
|
||||||
selector: 'hero-di',
|
selector: 'hero-di',
|
||||||
template: '<h1>Hero: {{name}}</h1>'
|
template: '<h1>Hero: {{name}}</h1>'
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
|
HeroDIComponent.parameters = [ app.DataService ];
|
||||||
|
|
||||||
|
function HeroDIComponent(dataService) {
|
||||||
|
this.name = dataService.getHeroName();
|
||||||
|
}
|
||||||
|
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
||||||
app.HeroesDIModule =
|
|
||||||
ng.core.NgModule({
|
})(window.app = window.app || {});
|
||||||
imports: [ ng.platformBrowser.BrowserModule ],
|
|
||||||
providers: [ app.DataService ],
|
////// DSL Version /////
|
||||||
declarations: [ HeroComponent ],
|
|
||||||
bootstrap: [ HeroComponent ]
|
(function(app) {
|
||||||
})
|
|
||||||
.Class({
|
// #docregion dsl
|
||||||
constructor: function() {}
|
app.HeroDIDslComponent = ng.core.Component({
|
||||||
});
|
selector: 'hero-di-dsl',
|
||||||
|
template: '<h1>Hero: {{name}}</h1>'
|
||||||
|
})
|
||||||
|
.Class({
|
||||||
|
constructor: [
|
||||||
|
app.DataService,
|
||||||
|
function HeroDIDslComponent(service) {
|
||||||
|
this.name = service.getHeroName();
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
// #enddocregion dsl
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
})(window.app = window.app || {});
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
// #docplaster
|
|
||||||
// #docregion appexport
|
|
||||||
(function(app) {
|
|
||||||
|
|
||||||
// #docregion component
|
|
||||||
var HeroComponent = ng.core.Component({
|
|
||||||
selector: 'hero-view-2',
|
|
||||||
template:
|
|
||||||
'<h1>Name: {{getName()}}</h1>',
|
|
||||||
})
|
|
||||||
.Class({
|
|
||||||
constructor: function() {
|
|
||||||
},
|
|
||||||
getName: function() {
|
|
||||||
return 'Windstorm';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// #enddocregion component
|
|
||||||
|
|
||||||
app.HeroesDslModule =
|
|
||||||
ng.core.NgModule({
|
|
||||||
imports: [ ng.platformBrowser.BrowserModule ],
|
|
||||||
declarations: [ HeroComponent ],
|
|
||||||
bootstrap: [ HeroComponent ]
|
|
||||||
})
|
|
||||||
.Class({
|
|
||||||
constructor: function() {}
|
|
||||||
});
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
|
||||||
// #enddocregion appexport
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
(function(app) {
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
app.HeroHostComponent = HeroHostComponent;
|
||||||
|
|
||||||
|
HeroHostComponent.annotations = [
|
||||||
|
new ng.core.Component({
|
||||||
|
selector: 'hero-host',
|
||||||
|
template:
|
||||||
|
'<h1 [class.active]="active">Hero Host</h1>' +
|
||||||
|
'<div>Heading clicks: {{clicks}}</div>',
|
||||||
|
host: {
|
||||||
|
// HostBindings to the <hero-host> element
|
||||||
|
'[title]': 'title',
|
||||||
|
'[class.heading]': 'headingClass',
|
||||||
|
'(click)': 'clicked()',
|
||||||
|
|
||||||
|
// HostListeners on the entire <hero-host> element
|
||||||
|
'(mouseenter)': 'enter($event)',
|
||||||
|
'(mouseleave)': 'leave($event)'
|
||||||
|
},
|
||||||
|
// Styles within (but excluding) the <hero-host> element
|
||||||
|
styles: ['.active {background-color: yellow;}']
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
function HeroHostComponent() {
|
||||||
|
this.clicks = 0;
|
||||||
|
this.headingClass = true;
|
||||||
|
this.title = 'Hero Host Tooltip content';
|
||||||
|
}
|
||||||
|
|
||||||
|
HeroHostComponent.prototype.clicked = function() {
|
||||||
|
this.clicks += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
HeroHostComponent.prototype.enter = function(event) {
|
||||||
|
this.active = true;
|
||||||
|
this.headingClass = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
HeroHostComponent.prototype.leave = function(event) {
|
||||||
|
this.active = false;
|
||||||
|
this.headingClass = true;
|
||||||
|
}
|
||||||
|
// #enddocregion
|
||||||
|
|
||||||
|
})(window.app = window.app || {});
|
||||||
|
|
||||||
|
//// DSL Version ////
|
||||||
|
|
||||||
|
(function(app) {
|
||||||
|
|
||||||
|
// #docregion dsl
|
||||||
|
app.HeroHostDslComponent = ng.core.Component({
|
||||||
|
selector: 'hero-host-dsl',
|
||||||
|
template: `
|
||||||
|
<h1 [class.active]="active">Hero Host (DSL)</h1>
|
||||||
|
<div>Heading clicks: {{clicks}}</div>
|
||||||
|
`,
|
||||||
|
host: {
|
||||||
|
// HostBindings to the <hero-host-dsl> element
|
||||||
|
'[title]': 'title',
|
||||||
|
'[class.heading]': 'headingClass',
|
||||||
|
'(click)': 'clicked()',
|
||||||
|
|
||||||
|
// HostListeners on the entire <hero-host-dsl> element
|
||||||
|
'(mouseenter)': 'enter($event)',
|
||||||
|
'(mouseleave)': 'leave($event)'
|
||||||
|
},
|
||||||
|
// Styles within (but excluding) the <hero-host-dsl> element
|
||||||
|
styles: ['.active {background-color: coral;}']
|
||||||
|
})
|
||||||
|
.Class({
|
||||||
|
constructor: function HeroHostDslComponent() {
|
||||||
|
this.clicks = 0;
|
||||||
|
this.headingClass = true;
|
||||||
|
this.title = 'Hero Host Tooltip DSL content';
|
||||||
|
},
|
||||||
|
|
||||||
|
clicked() {
|
||||||
|
this.clicks += 1;
|
||||||
|
},
|
||||||
|
|
||||||
|
enter(event) {
|
||||||
|
this.active = true;
|
||||||
|
this.headingClass = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
leave(event) {
|
||||||
|
this.active = false;
|
||||||
|
this.headingClass = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// #enddocregion dsl
|
||||||
|
|
||||||
|
})(window.app = window.app || {});
|
|
@ -0,0 +1,7 @@
|
||||||
|
<app-confirm-dsl [okMsg]="'OK'"
|
||||||
|
[cancelMsg]="'Cancel'"
|
||||||
|
(ok)="onOk()"
|
||||||
|
(cancel)="onCancel()">
|
||||||
|
</app-confirm-dsl>
|
||||||
|
<span *ngIf="okClicked">OK clicked</span>
|
||||||
|
<span *ngIf="cancelClicked">Cancel clicked</span>
|
|
@ -0,0 +1,7 @@
|
||||||
|
<app-confirm [okMsg]="'OK'"
|
||||||
|
[cancelMsg]="'Cancel'"
|
||||||
|
(ok)="onOk()"
|
||||||
|
(cancel)="onCancel()">
|
||||||
|
</app-confirm>
|
||||||
|
<span *ngIf="okClicked">OK clicked</span>
|
||||||
|
<span *ngIf="cancelClicked">Cancel clicked</span>
|
|
@ -1,68 +1,42 @@
|
||||||
(function(app) {
|
(function(app) {
|
||||||
// #docregion
|
|
||||||
var ConfirmComponent = ng.core.Component({
|
|
||||||
selector: 'my-confirm',
|
|
||||||
inputs: [
|
|
||||||
'okMsg',
|
|
||||||
'notOkMsg: cancelMsg'
|
|
||||||
],
|
|
||||||
outputs: [
|
|
||||||
'ok',
|
|
||||||
'notOk: cancel'
|
|
||||||
],
|
|
||||||
template:
|
|
||||||
'<button (click)="onOkClick()">' +
|
|
||||||
'{{okMsg}}' +
|
|
||||||
'</button>' +
|
|
||||||
'<button (click)="onNotOkClick()">' +
|
|
||||||
'{{notOkMsg}}' +
|
|
||||||
'</button>'
|
|
||||||
}).Class({
|
|
||||||
constructor: function() {
|
|
||||||
this.ok = new ng.core.EventEmitter();
|
|
||||||
this.notOk = new ng.core.EventEmitter();
|
|
||||||
},
|
|
||||||
onOkClick: function() {
|
|
||||||
this.ok.next(true);
|
|
||||||
},
|
|
||||||
onNotOkClick: function() {
|
|
||||||
this.notOk.next(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// #enddocregion
|
|
||||||
|
|
||||||
function AppComponent() {
|
app.HeroIOComponent = HeroComponent;
|
||||||
}
|
|
||||||
AppComponent.annotations = [
|
HeroComponent.annotations = [
|
||||||
new ng.core.Component({
|
new ng.core.Component({
|
||||||
selector: 'hero-io',
|
selector: 'hero-io',
|
||||||
template: '<my-confirm [okMsg]="\'OK\'"' +
|
templateUrl: 'app/hero-io.component.html'
|
||||||
'[cancelMsg]="\'Cancel\'"' +
|
|
||||||
'(ok)="onOk()"' +
|
|
||||||
'(cancel)="onCancel()">' +
|
|
||||||
'</my-confirm>' +
|
|
||||||
'<span *ngIf="okClicked">OK clicked</span>' +
|
|
||||||
'<span *ngIf="cancelClicked">Cancel clicked</span>'
|
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
AppComponent.prototype.onOk = function() {
|
|
||||||
|
function HeroComponent() { }
|
||||||
|
|
||||||
|
HeroComponent.prototype.onOk = function() {
|
||||||
this.okClicked = true;
|
this.okClicked = true;
|
||||||
}
|
}
|
||||||
AppComponent.prototype.onCancel = function() {
|
|
||||||
|
HeroComponent.prototype.onCancel = function() {
|
||||||
this.cancelClicked = true;
|
this.cancelClicked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
app.HeroesIOModule =
|
})(window.app = window.app || {});
|
||||||
ng.core.NgModule({
|
|
||||||
imports: [ ng.platformBrowser.BrowserModule ],
|
///// DSL Version ////
|
||||||
declarations: [
|
|
||||||
AppComponent,
|
(function(app) {
|
||||||
ConfirmComponent
|
|
||||||
],
|
app.HeroIODslComponent = ng.core.Component({
|
||||||
bootstrap: [ AppComponent ]
|
selector: 'hero-io-dsl',
|
||||||
|
templateUrl: 'app/hero-io-dsl.component.html'
|
||||||
})
|
})
|
||||||
.Class({
|
.Class({
|
||||||
constructor: function() {}
|
constructor: function HeroIODslComponent() { },
|
||||||
|
onOk: function() {
|
||||||
|
this.okClicked = true;
|
||||||
|
},
|
||||||
|
onCancel: function() {
|
||||||
|
this.cancelClicked = true;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
})(window.app = window.app || {});
|
||||||
|
|
|
@ -1,29 +1,42 @@
|
||||||
// #docplaster
|
// #docplaster
|
||||||
(function(app) {
|
(function(app) {
|
||||||
|
|
||||||
// #docregion
|
// #docregion
|
||||||
function HeroComponent() {}
|
app.HeroLifecycleComponent = HeroComponent;
|
||||||
// #enddocregion
|
|
||||||
HeroComponent.annotations = [
|
HeroComponent.annotations = [
|
||||||
new ng.core.Component({
|
new ng.core.Component({
|
||||||
selector: 'hero-lifecycle',
|
selector: 'hero-lifecycle',
|
||||||
template: '<h1>Hero: {{name}}</h1>'
|
template: '<h1>Hero: {{name}}</h1>'
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
// #docregion
|
|
||||||
HeroComponent.prototype.ngOnInit =
|
function HeroComponent() { }
|
||||||
function() {
|
|
||||||
this.name = 'Windstorm';
|
HeroComponent.prototype.ngOnInit = function() {
|
||||||
|
// todo: fetch from server async
|
||||||
|
setTimeout(() => this.name = 'Windstorm', 0);
|
||||||
};
|
};
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
||||||
app.HeroesLifecycleModule =
|
})(window.app = window.app || {});
|
||||||
ng.core.NgModule({
|
|
||||||
imports: [ ng.platformBrowser.BrowserModule ],
|
/////// DSL version ////
|
||||||
declarations: [ HeroComponent ],
|
|
||||||
bootstrap: [ HeroComponent ]
|
(function(app) {
|
||||||
|
|
||||||
|
// #docregion dsl
|
||||||
|
app.HeroLifecycleDslComponent = ng.core.Component({
|
||||||
|
selector: 'hero-lifecycle-dsl',
|
||||||
|
template: '<h1>Hero: {{name}}</h1>'
|
||||||
})
|
})
|
||||||
.Class({
|
.Class({
|
||||||
constructor: function() {}
|
constructor: function HeroLifecycleDslComponent() { },
|
||||||
|
ngOnInit: function() {
|
||||||
|
// todo: fetch from server async
|
||||||
|
setTimeout(() => this.name = 'Windstorm', 0);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
// #enddocregion dsl
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
})(window.app = window.app || {});
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
(function(app) {
|
||||||
|
|
||||||
|
app.heroQueries = app.heroQueries || {};
|
||||||
|
|
||||||
|
app.heroQueries.ContentChildComponent = ng.core.Component({
|
||||||
|
selector: 'content-child',
|
||||||
|
template:
|
||||||
|
'<span class="content-child" *ngIf="active">' +
|
||||||
|
'Active' +
|
||||||
|
'</span>'
|
||||||
|
}).Class({
|
||||||
|
constructor: function ContentChildComponent() {
|
||||||
|
this.active = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
activate: function() {
|
||||||
|
this.active = !this.active;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
|
||||||
|
// #docregion content
|
||||||
|
app.heroQueries.ViewChildComponent = ng.core.Component({
|
||||||
|
selector: 'view-child',
|
||||||
|
template:
|
||||||
|
'<h2 [class.active]=active>' +
|
||||||
|
'{{hero.name}} ' +
|
||||||
|
'<ng-content></ng-content>' +
|
||||||
|
'</h2>',
|
||||||
|
styles: ['.active {font-weight: bold; background-color: skyblue;}'],
|
||||||
|
inputs: ['hero'],
|
||||||
|
queries: {
|
||||||
|
content: new ng.core.ContentChild(app.heroQueries.ContentChildComponent)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.Class({
|
||||||
|
constructor: function HeroQueriesHeroComponent() {
|
||||||
|
this.active = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
activate: function() {
|
||||||
|
this.active = !this.active;
|
||||||
|
this.content.activate();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// #enddocregion content
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
|
||||||
|
// #docregion view
|
||||||
|
app.heroQueries.HeroQueriesComponent = ng.core.Component({
|
||||||
|
selector: 'hero-queries',
|
||||||
|
template:
|
||||||
|
'<view-child *ngFor="let hero of heroData" [hero]="hero">' +
|
||||||
|
'<content-child></content-child>' +
|
||||||
|
'</view-child>' +
|
||||||
|
'<button (click)="activate()">{{buttonLabel}} All</button>',
|
||||||
|
queries: {
|
||||||
|
views: new ng.core.ViewChildren(app.heroQueries.ViewChildComponent)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.Class({
|
||||||
|
constructor: function HeroQueriesComponent() {
|
||||||
|
this.active = false;
|
||||||
|
this.heroData = [
|
||||||
|
{id: 1, name: 'Windstorm'},
|
||||||
|
{id: 2, name: 'LaughingGas'}
|
||||||
|
];
|
||||||
|
},
|
||||||
|
|
||||||
|
activate: function() {
|
||||||
|
this.active = !this.active;
|
||||||
|
this.views.forEach(function(view) {
|
||||||
|
view.activate();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// #docregion defined-property
|
||||||
|
// add prototype property w/ getter outside the DSL
|
||||||
|
var proto = app.heroQueries.HeroQueriesComponent.prototype;
|
||||||
|
Object.defineProperty(proto, "buttonLabel", {
|
||||||
|
get: function () {
|
||||||
|
return this.active ? 'Deactivate' : 'Activate';
|
||||||
|
},
|
||||||
|
enumerable: true
|
||||||
|
});
|
||||||
|
// #enddocregion defined-property
|
||||||
|
// #enddocregion view
|
||||||
|
|
||||||
|
})(window.app = window.app || {});
|
|
@ -0,0 +1,4 @@
|
||||||
|
<!-- #docregion -->
|
||||||
|
<h1>{{titlePrefix}} {{title}}</h1>
|
||||||
|
<button (click)="ok()">OK</button>
|
||||||
|
<p>{{ msg }}</p>
|
|
@ -0,0 +1,60 @@
|
||||||
|
(function(app) {
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
app.HeroTitleComponent = HeroTitleComponent;
|
||||||
|
|
||||||
|
// #docregion templateUrl
|
||||||
|
HeroTitleComponent.annotations = [
|
||||||
|
new ng.core.Component({
|
||||||
|
selector: 'hero-title',
|
||||||
|
templateUrl: 'app/hero-title.component.html'
|
||||||
|
})
|
||||||
|
];
|
||||||
|
// #enddocregion templateUrl
|
||||||
|
|
||||||
|
function HeroTitleComponent(titlePrefix, title) {
|
||||||
|
this.titlePrefix = titlePrefix;
|
||||||
|
this.title = title;
|
||||||
|
this.msg = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
HeroTitleComponent.prototype.ok = function() {
|
||||||
|
this.msg = 'OK!';
|
||||||
|
}
|
||||||
|
|
||||||
|
HeroTitleComponent.parameters = [
|
||||||
|
[new ng.core.Optional(), new ng.core.Inject('titlePrefix')],
|
||||||
|
[new ng.core.Attribute('title')]
|
||||||
|
];
|
||||||
|
|
||||||
|
// #enddocregion
|
||||||
|
|
||||||
|
})(window.app = window.app || {});
|
||||||
|
|
||||||
|
////////// DSL version ////////////
|
||||||
|
|
||||||
|
(function(app) {
|
||||||
|
|
||||||
|
// #docregion dsl
|
||||||
|
app.HeroTitleDslComponent = ng.core.Component({
|
||||||
|
selector: 'hero-title-dsl',
|
||||||
|
templateUrl: 'app/hero-title.component.html'
|
||||||
|
})
|
||||||
|
.Class({
|
||||||
|
constructor: [
|
||||||
|
[ new ng.core.Optional(), new ng.core.Inject('titlePrefix') ],
|
||||||
|
new ng.core.Attribute('title'),
|
||||||
|
function HeroTitleDslComponent(titlePrefix, title) {
|
||||||
|
this.titlePrefix = titlePrefix;
|
||||||
|
this.title = title;
|
||||||
|
this.msg = '';
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
ok: function() {
|
||||||
|
this.msg = 'OK!';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// #enddocregion dsl
|
||||||
|
|
||||||
|
})(window.app = window.app || {});
|
|
@ -1,42 +1,48 @@
|
||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion appexport
|
|
||||||
(function(app) {
|
(function(app) {
|
||||||
// #enddocregion appexport
|
|
||||||
|
|
||||||
// #docregion metadata
|
// #docregion
|
||||||
// #docregion appexport
|
// #docregion appexport
|
||||||
|
// #docregion metadata
|
||||||
|
app.HeroComponent = HeroComponent; // "export"
|
||||||
|
|
||||||
|
HeroComponent.annotations = [
|
||||||
|
new ng.core.Component({
|
||||||
|
selector: 'hero-view',
|
||||||
|
template: '<h1>{{title}}: {{getName()}}</h1>'
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
// #docregion constructorproto
|
// #docregion constructorproto
|
||||||
function HeroComponent() {
|
function HeroComponent() {
|
||||||
this.title = "Hero Detail";
|
this.title = "Hero Detail";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HeroComponent.prototype.getName = function() { return 'Windstorm'; };
|
||||||
// #enddocregion constructorproto
|
// #enddocregion constructorproto
|
||||||
// #enddocregion appexport
|
|
||||||
HeroComponent.annotations = [
|
|
||||||
new ng.core.Component({
|
|
||||||
selector: 'hero-view',
|
|
||||||
template:
|
|
||||||
'<h1>Hero: {{getName()}}</h1>'
|
|
||||||
})
|
|
||||||
];
|
|
||||||
// #docregion constructorproto
|
|
||||||
HeroComponent.prototype.getName =
|
|
||||||
function() {return 'Windstorm';};
|
|
||||||
// #enddocregion constructorproto
|
|
||||||
// #enddocregion metadata
|
// #enddocregion metadata
|
||||||
|
// #enddocregion appexport
|
||||||
app.HeroesModule =
|
// #enddocregion
|
||||||
ng.core.NgModule({
|
|
||||||
imports: [ ng.platformBrowser.BrowserModule ],
|
})(window.app = window.app || {});
|
||||||
declarations: [ HeroComponent ],
|
|
||||||
bootstrap: [ HeroComponent ]
|
//////////// DSL version ///////////
|
||||||
})
|
|
||||||
.Class({
|
(function(app) {
|
||||||
constructor: function() {}
|
|
||||||
});
|
// #docregion dsl
|
||||||
|
app.HeroDslComponent = ng.core.Component({
|
||||||
// #docregion appexport
|
selector: 'hero-view-dsl',
|
||||||
app.HeroComponent = HeroComponent;
|
template: '<h1>{{title}}: {{getName()}}</h1>',
|
||||||
|
})
|
||||||
|
.Class({
|
||||||
|
constructor: function HeroDslComponent() {
|
||||||
|
this.title = "Hero Detail";
|
||||||
|
},
|
||||||
|
|
||||||
|
getName: function() { return 'Windstorm'; }
|
||||||
|
});
|
||||||
|
// #enddocregion dsl
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
})(window.app = window.app || {});
|
||||||
// #enddocregion appexport
|
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
(function(app) {
|
|
||||||
|
|
||||||
// #docregion
|
|
||||||
var HeroesComponent = ng.core.Component({
|
|
||||||
selector: 'heroes-bindings',
|
|
||||||
template: '<h1 [class.active]="active">' +
|
|
||||||
'Tour of Heroes' +
|
|
||||||
'</h1>',
|
|
||||||
host: {
|
|
||||||
'[title]': 'title',
|
|
||||||
'[class.heading]': 'hClass',
|
|
||||||
'(click)': 'clicked()',
|
|
||||||
'(dblclick)': 'doubleClicked($event)'
|
|
||||||
}
|
|
||||||
}).Class({
|
|
||||||
constructor: function() {
|
|
||||||
this.title = 'Tooltip content';
|
|
||||||
this.hClass = true;
|
|
||||||
},
|
|
||||||
clicked: function() {
|
|
||||||
this.active = !this.active;
|
|
||||||
},
|
|
||||||
doubleClicked: function(evt) {
|
|
||||||
this.active = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// #enddocregion
|
|
||||||
|
|
||||||
app.HeroesHostBindingsModule =
|
|
||||||
ng.core.NgModule({
|
|
||||||
imports: [ ng.platformBrowser.BrowserModule ],
|
|
||||||
declarations: [ HeroesComponent ],
|
|
||||||
bootstrap: [ HeroesComponent ]
|
|
||||||
})
|
|
||||||
.Class({
|
|
||||||
constructor: function() {}
|
|
||||||
});
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
|
|
@ -1,82 +0,0 @@
|
||||||
(function(app) {
|
|
||||||
|
|
||||||
var ActiveLabelComponent = ng.core.Component({
|
|
||||||
selector: 'active-label',
|
|
||||||
template: '<span class="active-label"' +
|
|
||||||
'*ngIf="active">' +
|
|
||||||
'Active' +
|
|
||||||
'</span>'
|
|
||||||
}).Class({
|
|
||||||
constructor: [function() { }],
|
|
||||||
activate: function() {
|
|
||||||
this.active = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// #docregion content
|
|
||||||
var HeroComponent = ng.core.Component({
|
|
||||||
selector: 'a-hero',
|
|
||||||
template: '<h2 [class.active]=active>' +
|
|
||||||
'{{hero.name}} ' +
|
|
||||||
'<ng-content></ng-content>' +
|
|
||||||
'</h2>',
|
|
||||||
inputs: ['hero'],
|
|
||||||
queries: {
|
|
||||||
label: new ng.core.ContentChild(
|
|
||||||
ActiveLabelComponent)
|
|
||||||
}
|
|
||||||
}).Class({
|
|
||||||
constructor: [function() { }],
|
|
||||||
activate: function() {
|
|
||||||
this.active = true;
|
|
||||||
this.label.activate();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
app.HeroQueriesComponent = HeroComponent;
|
|
||||||
// #enddocregion content
|
|
||||||
|
|
||||||
// #docregion view
|
|
||||||
var AppComponent = ng.core.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 ng.core.ViewChildren(
|
|
||||||
HeroComponent)
|
|
||||||
}
|
|
||||||
}).Class({
|
|
||||||
constructor: function() {
|
|
||||||
this.heroData = [
|
|
||||||
{id: 1, name: 'Windstorm'},
|
|
||||||
{id: 2, name: 'Superman'}
|
|
||||||
];
|
|
||||||
},
|
|
||||||
activate: function() {
|
|
||||||
this.heroCmps.forEach(function(cmp) {
|
|
||||||
cmp.activate();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// #enddocregion view
|
|
||||||
|
|
||||||
app.HeroesQueriesModule =
|
|
||||||
ng.core.NgModule({
|
|
||||||
imports: [ ng.platformBrowser.BrowserModule ],
|
|
||||||
declarations: [
|
|
||||||
AppComponent,
|
|
||||||
HeroComponent,
|
|
||||||
ActiveLabelComponent
|
|
||||||
],
|
|
||||||
bootstrap: [ AppComponent ]
|
|
||||||
})
|
|
||||||
.Class({
|
|
||||||
constructor: function() {}
|
|
||||||
});
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
|
|
@ -1,35 +1,9 @@
|
||||||
// #docplaster
|
|
||||||
// #docregion appimport
|
|
||||||
(function(app) {
|
(function(app) {
|
||||||
// #enddocregion appimport
|
|
||||||
|
|
||||||
// #docregion ng2import
|
var platformBrowserDynamic = ng.platformBrowserDynamic.platformBrowserDynamic;
|
||||||
var platformBrowserDynamic =
|
|
||||||
ng.platformBrowserDynamic.platformBrowserDynamic;
|
|
||||||
var LocationStrategy =
|
|
||||||
ng.common.LocationStrategy;
|
|
||||||
var HashLocationStrategy =
|
|
||||||
ng.common.HashLocationStrategy;
|
|
||||||
// #enddocregion ng2import
|
|
||||||
|
|
||||||
// #docregion appimport
|
|
||||||
var HeroComponent = app.HeroComponent;
|
|
||||||
// #enddocregion appimport
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
platformBrowserDynamic().bootstrapModule(app.HeroesModule);
|
platformBrowserDynamic().bootstrapModule(app.AppModule);
|
||||||
platformBrowserDynamic().bootstrapModule(app.HeroesDslModule);
|
|
||||||
platformBrowserDynamic().bootstrapModule(app.HeroesLifecycleModule);
|
|
||||||
platformBrowserDynamic().bootstrapModule(app.HeroesDIModule);
|
|
||||||
platformBrowserDynamic().bootstrapModule(app.HeroDIInlineModule);
|
|
||||||
platformBrowserDynamic().bootstrapModule(app.HeroesDIInjectModule);
|
|
||||||
platformBrowserDynamic().bootstrapModule(app.HeroesDIInjectModule2);
|
|
||||||
platformBrowserDynamic().bootstrapModule(app.HeroesDIInjectAdditionalModule);
|
|
||||||
platformBrowserDynamic().bootstrapModule(app.HeroesIOModule);
|
|
||||||
platformBrowserDynamic().bootstrapModule(app.HeroesHostBindingsModule);
|
|
||||||
platformBrowserDynamic().bootstrapModule(app.HeroesQueriesModule);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// #docregion appimport
|
|
||||||
})(window.app = window.app || {});
|
})(window.app = window.app || {});
|
||||||
// #enddocregion appimport
|
|
||||||
|
|
|
@ -4,64 +4,41 @@
|
||||||
<base href="/">
|
<base href="/">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="stylesheet" href="styles.css">
|
<link rel="stylesheet" href="styles.css">
|
||||||
|
<title>TypeScript to JavaScript</title>
|
||||||
|
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
<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/zone.js/dist/zone.js"></script>
|
||||||
<script src="node_modules/reflect-metadata/Reflect.js"></script>
|
<script src="node_modules/reflect-metadata/Reflect.js"></script>
|
||||||
|
|
||||||
|
<!-- Angular and RxJS umd scripts -->
|
||||||
<script src="node_modules/rxjs/bundles/Rx.js"></script>
|
<script src="node_modules/rxjs/bundles/Rx.js"></script>
|
||||||
<script src="node_modules/@angular/core/bundles/core.umd.js"></script>
|
<script src="node_modules/@angular/core/bundles/core.umd.js"></script>
|
||||||
<script src="node_modules/@angular/common/bundles/common.umd.js"></script>
|
<script src="node_modules/@angular/common/bundles/common.umd.js"></script>
|
||||||
<script src="node_modules/@angular/compiler/bundles/compiler.umd.js"></script>
|
<script src="node_modules/@angular/compiler/bundles/compiler.umd.js"></script>
|
||||||
<script src="node_modules/@angular/platform-browser/bundles/platform-browser.umd.js"></script>
|
<script src="node_modules/@angular/platform-browser/bundles/platform-browser.umd.js"></script>
|
||||||
<script src="node_modules/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js"></script>
|
<script src="node_modules/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js"></script>
|
||||||
<script src="node_modules/@angular/router-deprecated/bundles/router-deprecated.umd.js"></script>
|
|
||||||
|
|
||||||
|
<!-- Application scripts -->
|
||||||
|
<script src="app/app.component.js"></script>
|
||||||
|
<script src="app/confirm.component.js"></script>
|
||||||
<script src="app/data.service.js"></script>
|
<script src="app/data.service.js"></script>
|
||||||
<script src="app/hero.component.js"></script>
|
<script src="app/hero.component.js"></script>
|
||||||
<script src="app/hero-dsl.component.js"></script>
|
|
||||||
<script src="app/hero-lifecycle.component.js"></script>
|
|
||||||
<script src="app/hero-io.component.js"></script>
|
<script src="app/hero-io.component.js"></script>
|
||||||
<script src="app/hero-di.component.js"></script>
|
<script src="app/hero-di.component.js"></script>
|
||||||
<script src="app/hero-di-inline.component.js"></script>
|
|
||||||
<script src="app/hero-di-inject.component.js"></script>
|
<script src="app/hero-di-inject.component.js"></script>
|
||||||
<script src="app/hero-di-inject-additional.component.js"></script>
|
<script src="app/hero-di-inject-additional.component.js"></script>
|
||||||
<script src="app/heroes-bindings.component.js"></script>
|
<script src="app/hero-host.component.js"></script>
|
||||||
<script src="app/heroes-queries.component.js"></script>
|
<script src="app/hero-lifecycle.component.js"></script>
|
||||||
|
<script src="app/hero-queries.component.js"></script>
|
||||||
|
<script src="app/hero-title.component.js"></script>
|
||||||
|
|
||||||
|
<script src="app/app.module.js"></script>
|
||||||
<script src="app/main.js"></script>
|
<script src="app/main.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<a id="toc"></a>
|
<my-app>Loading...</my-app>
|
||||||
<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>Loading hero-view...</hero-view>
|
|
||||||
<hero-view-2>Loading hero-view2...</hero-view-2>
|
|
||||||
<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-inline>Loading hero-di-inline...</hero-di-inline>
|
|
||||||
<hero-di-inline2>Loading hero-di-inline2...</hero-di-inline2>
|
|
||||||
<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>Loading heroes-queries...</heroes-queries>
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
<a id="toc"></a>
|
||||||
|
<h1>{{title}}</h1>
|
||||||
|
<a href="#class-metadata">Classes and Class Metadata</a><br>
|
||||||
|
<a href="#io-metadata">Input and Output Decorators</a><br>
|
||||||
|
<a href="#dependency-injection">Dependency Injection</a><br>
|
||||||
|
<a href="#host-metadata">Host Metadata</a><br>
|
||||||
|
<a href="#view-child-metadata">View and Child Metadata</a><br>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="class-metadata">Classes and Class Metadata</h4>
|
||||||
|
<hero-view></hero-view>
|
||||||
|
<hero-lifecycle></hero-lifecycle>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="io-metadata">Input and Output Metadata</h4>
|
||||||
|
<hero-io></hero-io>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="dependency-injection">Dependency Injection</h4>
|
||||||
|
<hero-di></hero-di>
|
||||||
|
<hero-di-inject></hero-di-inject>
|
||||||
|
<hero-di-inject-additional></hero-di-inject-additional>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="host-metadata">Host Metadata</h4>
|
||||||
|
<hero-host></hero-host>
|
||||||
|
<hero-host-meta></hero-host-meta>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="view-child-metadata">View and Child Metadata</h4>
|
||||||
|
<hero-queries></hero-queries>
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
moduleId: module.id,
|
||||||
|
selector: 'my-app',
|
||||||
|
templateUrl: 'app.component.html',
|
||||||
|
styles: [
|
||||||
|
// See hero-di-inject-additional.component
|
||||||
|
'hero-host, hero-host-meta { border: 1px dashed black; display: block; padding: 4px;}',
|
||||||
|
'.heading {font-style: italic}'
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
title = 'TypeScript';
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/* tslint:disable-next-line:no-unused-variable */
|
||||||
|
import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
import { ConfirmComponent } from './confirm.component';
|
||||||
|
// #docregion appimport
|
||||||
|
import { HeroComponent } from './hero.component';
|
||||||
|
// #enddocregion appimport
|
||||||
|
import { HeroComponent as HeroDIComponent } from './hero-di.component';
|
||||||
|
import { HeroComponent as HeroDIInjectComponent } from './hero-di-inject.component';
|
||||||
|
import { HeroComponent as HeroDIInjectAdditionalComponent } from './hero-di-inject-additional.component';
|
||||||
|
import { HeroHostComponent } from './hero-host.component';
|
||||||
|
import { HeroHostMetaComponent } from './hero-host-meta.component';
|
||||||
|
import { HeroIOComponent } from './hero-io.component';
|
||||||
|
import { HeroComponent as HeroLifecycleComponent } from './hero-lifecycle.component';
|
||||||
|
import { HeroQueriesComponent, ViewChildComponent, ContentChildComponent } from './hero-queries.component';
|
||||||
|
import { HeroTitleComponent } from './hero-title.component';
|
||||||
|
|
||||||
|
import { DataService } from './data.service';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
BrowserModule
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
AppComponent,
|
||||||
|
ConfirmComponent,
|
||||||
|
HeroComponent,
|
||||||
|
HeroDIComponent,
|
||||||
|
HeroDIInjectComponent,
|
||||||
|
HeroDIInjectAdditionalComponent,
|
||||||
|
HeroHostComponent, HeroHostMetaComponent,
|
||||||
|
HeroIOComponent,
|
||||||
|
HeroLifecycleComponent,
|
||||||
|
HeroQueriesComponent, ViewChildComponent, ContentChildComponent,
|
||||||
|
HeroTitleComponent
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
DataService,
|
||||||
|
{ provide: 'heroName', useValue: 'Windstorm' }
|
||||||
|
],
|
||||||
|
bootstrap: [ AppComponent ],
|
||||||
|
|
||||||
|
// schemas: [ NO_ERRORS_SCHEMA ] // helpful for debugging!
|
||||||
|
})
|
||||||
|
export class AppModule { }
|
||||||
|
|
||||||
|
/* tslint:disable no-unused-variable */
|
||||||
|
// #docregion ng2import
|
||||||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
import {
|
||||||
|
LocationStrategy,
|
||||||
|
HashLocationStrategy
|
||||||
|
} from '@angular/common';
|
||||||
|
// #enddocregion ng2import
|
|
@ -0,0 +1,6 @@
|
||||||
|
<button (click)="onOkClick()">
|
||||||
|
{{okMsg}}
|
||||||
|
</button>
|
||||||
|
<button (click)="onNotOkClick()">
|
||||||
|
{{notOkMsg}}
|
||||||
|
</button>
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
@Component({
|
||||||
|
moduleId: module.id,
|
||||||
|
selector: 'app-confirm',
|
||||||
|
templateUrl: 'confirm.component.html'
|
||||||
|
})
|
||||||
|
export class ConfirmComponent {
|
||||||
|
@Input() okMsg = '';
|
||||||
|
@Input('cancelMsg') notOkMsg = '';
|
||||||
|
@Output() ok = new EventEmitter();
|
||||||
|
@Output('cancel') notOk = new EventEmitter();
|
||||||
|
|
||||||
|
onOkClick() {
|
||||||
|
this.ok.emit(true);
|
||||||
|
}
|
||||||
|
onNotOkClick() {
|
||||||
|
this.notOk.emit(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion
|
|
@ -2,8 +2,8 @@ import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DataService {
|
export class DataService {
|
||||||
constructor() {
|
constructor() { }
|
||||||
}
|
|
||||||
getHeroName() {
|
getHeroName() {
|
||||||
return 'Windstorm';
|
return 'Windstorm';
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,50 +1,7 @@
|
||||||
import {
|
import { Component } from '@angular/core';
|
||||||
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 {
|
|
||||||
private msg: string = '';
|
|
||||||
constructor(
|
|
||||||
@Inject('titlePrefix')
|
|
||||||
@Optional()
|
|
||||||
private titlePrefix: string,
|
|
||||||
@Attribute('title')
|
|
||||||
private title: string) {
|
|
||||||
}
|
|
||||||
|
|
||||||
ok() {
|
|
||||||
this.msg = 'OK!';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// #enddocregion
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'hero-di-inject-additional',
|
selector: 'hero-di-inject-additional',
|
||||||
template: `<hero-title title="Tour of Heroes">
|
template: `<hero-title title="Tour of Heroes"></hero-title>`
|
||||||
</hero-title>`
|
|
||||||
})
|
})
|
||||||
class AppComponent { }
|
export class HeroComponent { }
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [ BrowserModule ],
|
|
||||||
declarations: [
|
|
||||||
AppComponent,
|
|
||||||
TitleComponent
|
|
||||||
],
|
|
||||||
bootstrap: [ AppComponent ]
|
|
||||||
})
|
|
||||||
export class HeroesDIInjectAdditionalModule { }
|
|
||||||
|
|
|
@ -1,23 +1,11 @@
|
||||||
import { Component, Inject, NgModule } from '@angular/core';
|
import { Component, Inject } from '@angular/core';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
|
||||||
|
|
||||||
// #docregion
|
// #docregion
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'hero-di-inject',
|
selector: 'hero-di-inject',
|
||||||
template: `<h1>Hero: {{name}}</h1>`
|
template: `<h1>Hero: {{name}}</h1>`
|
||||||
})
|
})
|
||||||
class HeroComponent {
|
export class HeroComponent {
|
||||||
constructor(
|
constructor(@Inject('heroName') private name: string) { }
|
||||||
@Inject('heroName')
|
|
||||||
private name: string) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [ BrowserModule ],
|
|
||||||
providers: [ { provide: 'heroName', useValue: 'Windstorm' } ],
|
|
||||||
declarations: [ HeroComponent ],
|
|
||||||
bootstrap: [ HeroComponent ]
|
|
||||||
})
|
|
||||||
export class HeroesDIInjectModule { }
|
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
import { Component, NgModule } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
|
||||||
|
|
||||||
import { DataService } from './data.service';
|
import { DataService } from './data.service';
|
||||||
|
|
||||||
// #docregion
|
// #docregion
|
||||||
|
@ -8,18 +6,10 @@ import { DataService } from './data.service';
|
||||||
selector: 'hero-di',
|
selector: 'hero-di',
|
||||||
template: `<h1>Hero: {{name}}</h1>`
|
template: `<h1>Hero: {{name}}</h1>`
|
||||||
})
|
})
|
||||||
class HeroComponent {
|
export class HeroComponent {
|
||||||
name: string;
|
name = '';
|
||||||
constructor(dataService: DataService) {
|
constructor(dataService: DataService) {
|
||||||
this.name = dataService.getHeroName();
|
this.name = dataService.getHeroName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [ BrowserModule ],
|
|
||||||
providers: [ DataService ],
|
|
||||||
declarations: [ HeroComponent ],
|
|
||||||
bootstrap: [ HeroComponent ]
|
|
||||||
})
|
|
||||||
export class HeroesDIModule { }
|
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
@Component({
|
||||||
|
selector: 'hero-host-meta',
|
||||||
|
template: `
|
||||||
|
<h1 [class.active]="active">Hero Host in Metadata</h1>
|
||||||
|
<div>Heading clicks: {{clicks}}</div>
|
||||||
|
`,
|
||||||
|
host: {
|
||||||
|
// HostBindings to the <hero-host-meta> element
|
||||||
|
'[title]': 'title',
|
||||||
|
'[class.heading]': 'headingClass',
|
||||||
|
|
||||||
|
// HostListeners on the entire <hero-host-meta> element
|
||||||
|
'(click)': 'clicked()',
|
||||||
|
'(mouseenter)': 'enter($event)',
|
||||||
|
'(mouseleave)': 'leave($event)'
|
||||||
|
},
|
||||||
|
// Styles within (but excluding) the <hero-host-meta> element
|
||||||
|
styles: ['.active {background-color: coral;}']
|
||||||
|
})
|
||||||
|
export class HeroHostMetaComponent {
|
||||||
|
title = 'Hero Host in Metadata Tooltip';
|
||||||
|
headingClass = true;
|
||||||
|
|
||||||
|
active = false;
|
||||||
|
clicks = 0;
|
||||||
|
|
||||||
|
clicked() {
|
||||||
|
this.clicks += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enter(event: Event) {
|
||||||
|
this.active = true;
|
||||||
|
this.headingClass = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
leave(event: Event) {
|
||||||
|
this.active = false;
|
||||||
|
this.headingClass = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion
|
|
@ -0,0 +1,39 @@
|
||||||
|
import { Component, HostBinding, HostListener } from '@angular/core';
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
@Component({
|
||||||
|
selector: 'hero-host',
|
||||||
|
template: `
|
||||||
|
<h1 [class.active]="active">Hero Host in Decorators</h1>
|
||||||
|
<div>Heading clicks: {{clicks}}</div>
|
||||||
|
`,
|
||||||
|
// Styles within (but excluding) the <hero-host> element
|
||||||
|
styles: ['.active {background-color: yellow;}']
|
||||||
|
})
|
||||||
|
export class HeroHostComponent {
|
||||||
|
// HostBindings to the <hero-host> element
|
||||||
|
@HostBinding() title = 'Hero Host in Decorators Tooltip';
|
||||||
|
@HostBinding('class.heading') headingClass = true;
|
||||||
|
|
||||||
|
active = false;
|
||||||
|
clicks = 0;
|
||||||
|
|
||||||
|
// HostListeners on the entire <hero-host> element
|
||||||
|
@HostListener('click')
|
||||||
|
clicked() {
|
||||||
|
this.clicks += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('mouseenter', ['$event'])
|
||||||
|
enter(event: Event) {
|
||||||
|
this.active = true;
|
||||||
|
this.headingClass = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('mouseleave', ['$event'])
|
||||||
|
leave(event: Event) {
|
||||||
|
this.active = false;
|
||||||
|
this.headingClass = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion
|
|
@ -1,73 +1,26 @@
|
||||||
import {
|
import { Component } from '@angular/core';
|
||||||
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: string;
|
|
||||||
@Input('cancelMsg') notOkMsg: string;
|
|
||||||
@Output() ok =
|
|
||||||
new EventEmitter();
|
|
||||||
@Output('cancel') notOk =
|
|
||||||
new EventEmitter();
|
|
||||||
|
|
||||||
onOkClick() {
|
|
||||||
this.ok.next(true);
|
|
||||||
}
|
|
||||||
onNotOkClick() {
|
|
||||||
this.notOk.next(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// #enddocregion
|
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'hero-io',
|
selector: 'hero-io',
|
||||||
template: `
|
template: `
|
||||||
<my-confirm [okMsg]="'OK'"
|
<app-confirm [okMsg]="'OK'"
|
||||||
[cancelMsg]="'Cancel'"
|
[cancelMsg]="'Cancel'"
|
||||||
(ok)="onOk()"
|
(ok)="onOk()"
|
||||||
(cancel)="onCancel()">
|
(cancel)="onCancel()">
|
||||||
</my-confirm>
|
</app-confirm>
|
||||||
<span *ngIf="okClicked">OK clicked</span>
|
<span *ngIf="okClicked">OK clicked</span>
|
||||||
<span *ngIf="cancelClicked">Cancel clicked</span>
|
<span *ngIf="cancelClicked">Cancel clicked</span>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
class AppComponent {
|
export class HeroIOComponent {
|
||||||
okClicked: boolean;
|
okClicked = false;
|
||||||
cancelClicked: boolean;
|
cancelClicked = false;
|
||||||
|
|
||||||
onOk() {
|
onOk() {
|
||||||
this.okClicked = true;
|
this.okClicked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
onCancel() {
|
onCancel() {
|
||||||
this.cancelClicked = true;
|
this.cancelClicked = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [ BrowserModule ],
|
|
||||||
declarations: [
|
|
||||||
AppComponent,
|
|
||||||
ConfirmComponent
|
|
||||||
],
|
|
||||||
bootstrap: [ AppComponent ]
|
|
||||||
})
|
|
||||||
export class HeroesIOModule { }
|
|
||||||
|
|
|
@ -1,28 +1,14 @@
|
||||||
// #docplaster
|
|
||||||
// #docregion
|
// #docregion
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
// #enddocregion
|
|
||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'hero-lifecycle',
|
selector: 'hero-lifecycle',
|
||||||
template: `<h1>Hero: {{name}}</h1>`
|
template: `<h1>Hero: {{name}}</h1>`
|
||||||
})
|
})
|
||||||
// #docregion
|
export class HeroComponent implements OnInit {
|
||||||
class HeroComponent
|
|
||||||
implements OnInit {
|
|
||||||
name: string;
|
name: string;
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.name = 'Windstorm';
|
// todo: fetch from server async
|
||||||
|
setTimeout(() => this.name = 'Windstorm', 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #enddocregion
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [ BrowserModule ],
|
|
||||||
declarations: [ HeroComponent ],
|
|
||||||
bootstrap: [ HeroComponent ]
|
|
||||||
})
|
|
||||||
export class HeroesLifecycleModule { }
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
ContentChild,
|
||||||
|
Input,
|
||||||
|
QueryList,
|
||||||
|
ViewChildren
|
||||||
|
} from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'content-child',
|
||||||
|
template: `
|
||||||
|
<span class="content-child" *ngIf="active">
|
||||||
|
Active
|
||||||
|
</span>`
|
||||||
|
})
|
||||||
|
export class ContentChildComponent {
|
||||||
|
active = false;
|
||||||
|
|
||||||
|
activate() {
|
||||||
|
this.active = !this.active;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
|
||||||
|
// #docregion content
|
||||||
|
@Component({
|
||||||
|
selector: 'view-child',
|
||||||
|
template: `
|
||||||
|
<h2 [class.active]=active>
|
||||||
|
{{hero.name}}
|
||||||
|
<ng-content></ng-content>
|
||||||
|
</h2>`,
|
||||||
|
styles: ['.active {font-weight: bold; background-color: skyblue;}']
|
||||||
|
})
|
||||||
|
export class ViewChildComponent {
|
||||||
|
@Input() hero: any;
|
||||||
|
active = false;
|
||||||
|
|
||||||
|
@ContentChild(ContentChildComponent) content: ContentChildComponent;
|
||||||
|
|
||||||
|
activate() {
|
||||||
|
this.active = !this.active;
|
||||||
|
this.content.activate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion content
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
|
||||||
|
// #docregion view
|
||||||
|
@Component({
|
||||||
|
selector: 'hero-queries',
|
||||||
|
template: `
|
||||||
|
<view-child *ngFor="let hero of heroData" [hero]="hero">
|
||||||
|
<content-child></content-child>
|
||||||
|
</view-child>
|
||||||
|
<button (click)="activate()">{{buttonLabel}} All</button>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
export class HeroQueriesComponent {
|
||||||
|
active = false;
|
||||||
|
heroData = [
|
||||||
|
{id: 1, name: 'Windstorm'},
|
||||||
|
{id: 2, name: 'LaughingGas'}
|
||||||
|
];
|
||||||
|
|
||||||
|
@ViewChildren(ViewChildComponent) views: QueryList<ViewChildComponent>;
|
||||||
|
|
||||||
|
activate() {
|
||||||
|
this.active = !this.active;
|
||||||
|
this.views.forEach(
|
||||||
|
view => view.activate()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #docregion defined-property
|
||||||
|
get buttonLabel() {
|
||||||
|
return this.active ? 'Deactivate' : 'Activate';
|
||||||
|
}
|
||||||
|
// #enddocregion defined-property
|
||||||
|
}
|
||||||
|
// #enddocregion view
|
|
@ -0,0 +1,4 @@
|
||||||
|
<!-- #docregion -->
|
||||||
|
<h1>{{titlePrefix}} {{title}}</h1>
|
||||||
|
<button (click)="ok()">OK</button>
|
||||||
|
<p>{{ msg }}</p>
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { Attribute, Component, Inject, Optional } from '@angular/core';
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
// #docregion templateUrl
|
||||||
|
@Component({
|
||||||
|
moduleId: module.id,
|
||||||
|
selector: 'hero-title',
|
||||||
|
templateUrl: 'hero-title.component.html'
|
||||||
|
})
|
||||||
|
// #enddocregion templateUrl
|
||||||
|
export class HeroTitleComponent {
|
||||||
|
msg: string = '';
|
||||||
|
constructor(
|
||||||
|
@Inject('titlePrefix') @Optional() private titlePrefix: string,
|
||||||
|
@Attribute('title') private title: string
|
||||||
|
) { }
|
||||||
|
|
||||||
|
ok() {
|
||||||
|
this.msg = 'OK!';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion
|
|
@ -1,30 +1,14 @@
|
||||||
// #docplaster
|
|
||||||
// #docregion metadata
|
// #docregion metadata
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'hero-view',
|
selector: 'hero-view',
|
||||||
template:
|
template: '<h1>{{title}}: {{getName()}}</h1>'
|
||||||
'<h1>Hero: {{getName()}}</h1>'
|
|
||||||
})
|
})
|
||||||
// #docregion appexport
|
// #docregion appexport, class
|
||||||
// #docregion class
|
|
||||||
export class HeroComponent {
|
export class HeroComponent {
|
||||||
title = 'Hero Detail';
|
title = 'Hero Detail';
|
||||||
getName() {return 'Windstorm'; }
|
getName() {return 'Windstorm'; }
|
||||||
}
|
}
|
||||||
// #enddocregion class
|
// #enddocregion appexport, class
|
||||||
// #enddocregion appexport
|
|
||||||
// #enddocregion metadata
|
// #enddocregion metadata
|
||||||
|
|
||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [ BrowserModule ],
|
|
||||||
declarations: [ HeroComponent ],
|
|
||||||
bootstrap: [ HeroComponent ]
|
|
||||||
})
|
|
||||||
export class HeroesModule { }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
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: boolean;
|
|
||||||
|
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
@HostListener('click')
|
|
||||||
clicked() {
|
|
||||||
this.active = !this.active;
|
|
||||||
}
|
|
||||||
|
|
||||||
@HostListener('dblclick', ['$event'])
|
|
||||||
doubleClicked(evt: Event) {
|
|
||||||
this.active = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// #enddocregion
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [ BrowserModule ],
|
|
||||||
declarations: [ HeroesComponent ],
|
|
||||||
bootstrap: [ HeroesComponent ]
|
|
||||||
})
|
|
||||||
export class HeroesHostBindingsModule { }
|
|
|
@ -1,88 +0,0 @@
|
||||||
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: boolean;
|
|
||||||
|
|
||||||
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: any;
|
|
||||||
active: boolean;
|
|
||||||
|
|
||||||
@ContentChild(ActiveLabelComponent)
|
|
||||||
label: ActiveLabelComponent;
|
|
||||||
|
|
||||||
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: QueryList<HeroComponent>;
|
|
||||||
|
|
||||||
activate() {
|
|
||||||
this.heroCmps.forEach(
|
|
||||||
(cmp) => cmp.activate()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// #enddocregion view
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [ BrowserModule ],
|
|
||||||
declarations: [
|
|
||||||
HeroesQueriesComponent,
|
|
||||||
HeroComponent,
|
|
||||||
ActiveLabelComponent
|
|
||||||
],
|
|
||||||
bootstrap: [ HeroesQueriesComponent ]
|
|
||||||
})
|
|
||||||
export class HeroesQueriesModule { }
|
|
|
@ -1,30 +1,4 @@
|
||||||
/* tslint:disable no-unused-variable */
|
|
||||||
// #docregion ng2import
|
|
||||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
import {
|
import { AppModule } from './app.module';
|
||||||
LocationStrategy,
|
|
||||||
HashLocationStrategy
|
|
||||||
} from '@angular/common';
|
|
||||||
// #enddocregion ng2import
|
|
||||||
|
|
||||||
// #docregion appimport
|
platformBrowserDynamic().bootstrapModule(AppModule);
|
||||||
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);
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="stylesheet" href="styles.css">
|
<link rel="stylesheet" href="styles.css">
|
||||||
|
<title>TypeScript to JavaScript</title>
|
||||||
|
|
||||||
<!-- Polyfills for older browsers -->
|
<!-- Polyfills for older browsers -->
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
<script src="node_modules/core-js/client/shim.min.js"></script>
|
||||||
|
@ -20,32 +21,7 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<a id="toc"></a>
|
<my-app>Loading...</my-app>
|
||||||
<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>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -60,7 +60,7 @@
|
||||||
|
|
||||||
"ts-to-js": {
|
"ts-to-js": {
|
||||||
"title": "TypeScript to JavaScript",
|
"title": "TypeScript to JavaScript",
|
||||||
"intro": "Convert Angular TypeScript examples into ES5 JavaScript",
|
"intro": "Convert Angular TypeScript examples into ES6 and ES5 JavaScript",
|
||||||
"hide": true
|
"hide": true
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
|
|
||||||
"ts-to-js": {
|
"ts-to-js": {
|
||||||
"title": "TypeScript to JavaScript",
|
"title": "TypeScript to JavaScript",
|
||||||
"intro": "Convert Angular TypeScript examples into ES5 JavaScript"
|
"intro": "Convert Angular TypeScript examples into ES6 and ES5 JavaScript"
|
||||||
},
|
},
|
||||||
|
|
||||||
"visual-studio-2015": {
|
"visual-studio-2015": {
|
||||||
|
|
|
@ -1,469 +1 @@
|
||||||
include ../../../../_includes/_util-fns
|
include ../../../ts/latest/cookbook/ts-to-js
|
||||||
|
|
||||||
:marked
|
|
||||||
Everything that we can do in Angular in TypeScript, we can also do
|
|
||||||
in JavaScript. Translating from one language to the other is mostly a
|
|
||||||
matter of changing the way we organize our code and the way we access
|
|
||||||
Angular APIs.
|
|
||||||
|
|
||||||
Since TypeScript is a popular language option in Angular, many of the
|
|
||||||
code examples you see on the Internet as well as on this site are written
|
|
||||||
in TypeScript. This cookbook contains recipes for translating these kinds of
|
|
||||||
code examples to ES5, so that they can be applied to Angular JavaScript
|
|
||||||
applications.
|
|
||||||
|
|
||||||
<a id="toc"></a>
|
|
||||||
:marked
|
|
||||||
## Table of contents
|
|
||||||
|
|
||||||
[Modularity: imports and exports](#modularity)
|
|
||||||
|
|
||||||
[Classes and Class Metadata](#class-metadata)
|
|
||||||
|
|
||||||
[Input and Output Metadata](#property-metadata)
|
|
||||||
|
|
||||||
[Dependency Injection](#dependency-injection)
|
|
||||||
|
|
||||||
[Host and Query Metadata](#other-property-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>
|
|
||||||
code shown in this cookbook.**
|
|
||||||
|
|
||||||
a(id="modularity")
|
|
||||||
.l-main-section
|
|
||||||
:marked
|
|
||||||
## Importing and Exporting
|
|
||||||
|
|
||||||
- var top="vertical-align:top"
|
|
||||||
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
|
|
||||||
are imported with TypeScript `import` statements:
|
|
||||||
|
|
||||||
+makeExample('cb-ts-to-js/ts/app/main.ts', 'ng2import')(format="." )
|
|
||||||
|
|
||||||
td
|
|
||||||
:marked
|
|
||||||
### Accessing Angular Code through the ng global
|
|
||||||
|
|
||||||
In 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:
|
|
||||||
|
|
||||||
+makeExample('cb-ts-to-js/js/app/main.js', 'ng2import')(format="." )
|
|
||||||
|
|
||||||
tr(style=top)
|
|
||||||
td
|
|
||||||
:marked
|
|
||||||
### Importing and Exporting Application Code
|
|
||||||
|
|
||||||
Each file in an Angular TypeScript application constitutes a
|
|
||||||
TypeScript module. When we want to make something from a module available
|
|
||||||
to other modules, we `export` it.
|
|
||||||
|
|
||||||
+makeExample('cb-ts-to-js/ts/app/hero.component.ts', 'appexport')(format="." )
|
|
||||||
|
|
||||||
:marked
|
|
||||||
In other modules we can then `import` things that have been exported
|
|
||||||
elsewhere.
|
|
||||||
|
|
||||||
+makeExample('cb-ts-to-js/ts/app/main.ts', 'appimport')(format="." )
|
|
||||||
|
|
||||||
td
|
|
||||||
:marked
|
|
||||||
### Sharing Application Code
|
|
||||||
|
|
||||||
In an Angular JavaScript application, we load each file to the page
|
|
||||||
using a `<script>` tag. Each file can make things available to other
|
|
||||||
files via the shared global `window` scope.
|
|
||||||
|
|
||||||
We often introduce an application namespace
|
|
||||||
object (such as `"app"`) onto `window` and attach everything we need
|
|
||||||
to share to that namespace object.
|
|
||||||
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/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
|
|
||||||
:marked
|
|
||||||
Alternatively, we can use a module loader such as Webpack or
|
|
||||||
Browserify in an Angular JavaScript project. In such a project, we would
|
|
||||||
use CommonJS modules and the `require` function to load Angular framework code.
|
|
||||||
We would then use `module.exports` and `require` to export and import application
|
|
||||||
code.
|
|
||||||
|
|
||||||
|
|
||||||
a(id="class-metadata")
|
|
||||||
.l-main-section
|
|
||||||
:marked
|
|
||||||
## Classes and Class Metadata
|
|
||||||
|
|
||||||
- var top="vertical-align:top"
|
|
||||||
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.
|
|
||||||
|
|
||||||
+makeExample('cb-ts-to-js/ts/app/hero.component.ts', 'class')(format="." )
|
|
||||||
|
|
||||||
td
|
|
||||||
:marked
|
|
||||||
### Constructors and Prototypes
|
|
||||||
|
|
||||||
ES5 JavaScript has no classes. We use the constructor
|
|
||||||
pattern instead which works with Angular as well as classes do.
|
|
||||||
|
|
||||||
+makeExample('cb-ts-to-js/js/app/hero.component.js', 'constructorproto')(format="." )
|
|
||||||
|
|
||||||
tr(style=top)
|
|
||||||
td
|
|
||||||
:marked
|
|
||||||
### Metadata with Decorators
|
|
||||||
|
|
||||||
Most Angular classes have one or more TypeScript *decorators*
|
|
||||||
attached to provide configuration and metadata. For example,
|
|
||||||
a component must have a [`@Component`](../api/core/index/Component-decorator.html) decorator.
|
|
||||||
|
|
||||||
+makeExample('cb-ts-to-js/ts/app/hero.component.ts', 'metadata')(format="." )
|
|
||||||
|
|
||||||
td
|
|
||||||
:marked
|
|
||||||
### Metadata with the Annotations Array
|
|
||||||
|
|
||||||
In JavaScript, we can attach an `annotations` array to a constructor
|
|
||||||
to provide metadata.
|
|
||||||
Each item in the array corresponds to a TypeScript decorator.
|
|
||||||
|
|
||||||
In the following example, we create a new instance of `Component` that corresponds
|
|
||||||
to the [`@Component`](../api/core/index/Component-decorator.html) TypeScript decorator.
|
|
||||||
|
|
||||||
+makeExample('cb-ts-to-js/js/app/hero.component.js', 'metadata')(format="." )
|
|
||||||
|
|
||||||
:marked
|
|
||||||
### Metadata with The Class Convenience API
|
|
||||||
|
|
||||||
The pattern of creating a constructor and decorating it with metadata
|
|
||||||
is so common that Angular provides an alternative convenience API for it.
|
|
||||||
This API lets us define everything in a single expression.
|
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
+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")
|
|
||||||
.l-main-section
|
|
||||||
:marked
|
|
||||||
## Input and Output Metadata
|
|
||||||
|
|
||||||
- var top="vertical-align:top"
|
|
||||||
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
|
|
||||||
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.
|
|
||||||
|
|
||||||
+makeExample('cb-ts-to-js/ts/app/hero-io.component.ts')(format="." )
|
|
||||||
|
|
||||||
.alert.is-helpful
|
|
||||||
:marked
|
|
||||||
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="." )
|
|
||||||
|
|
||||||
|
|
||||||
.l-main-section
|
|
||||||
:marked
|
|
||||||
## Dependency Injection
|
|
||||||
|
|
||||||
- var top="vertical-align:top"
|
|
||||||
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
|
|
||||||
determine what needs to be injected.
|
|
||||||
|
|
||||||
+makeExample('cb-ts-to-js/ts/app/hero-di.component.ts')(format="." )
|
|
||||||
|
|
||||||
td
|
|
||||||
:marked
|
|
||||||
### Injection with Parameter Tokens
|
|
||||||
|
|
||||||
Since no type information is available in ES5 JavaScript,
|
|
||||||
we must identify "injectables" in some other way.
|
|
||||||
|
|
||||||
We attach a `parameters` array to the constructor function.
|
|
||||||
Each array item is the dependency injection token that identifies the thing to be injected.
|
|
||||||
Often the token is the constructor function for the class-like dependency.
|
|
||||||
|
|
||||||
+makeExample('cb-ts-to-js/js/app/hero-di.component.js')(format="." )
|
|
||||||
|
|
||||||
:marked
|
|
||||||
When using the class convenience API, we can also supply the parameter
|
|
||||||
tokens by wrapping the constructor in an array.
|
|
||||||
|
|
||||||
+makeExample('cb-ts-to-js/js/app/hero-di-inline.component.js')(format="." )
|
|
||||||
|
|
||||||
tr(style=top)
|
|
||||||
td
|
|
||||||
:marked
|
|
||||||
### Injection with the @Inject decorator
|
|
||||||
|
|
||||||
When the thing being injected doesn't correspond directly to a type,
|
|
||||||
we use the `@Inject()` decorator to supply the injection token.
|
|
||||||
|
|
||||||
In this example, we're injecting a string identified by the "heroName" token.
|
|
||||||
|
|
||||||
+makeExample('cb-ts-to-js/ts/app/hero-di-inject.component.ts')(format="." )
|
|
||||||
|
|
||||||
td
|
|
||||||
:marked
|
|
||||||
### Injection with plain string tokens
|
|
||||||
|
|
||||||
In JavaScript we add the token string to the injection parameters array.
|
|
||||||
|
|
||||||
+makeExample('cb-ts-to-js/js/app/hero-di-inject.component.js','parameters')(format="." )
|
|
||||||
|
|
||||||
: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
|
|
||||||
:marked
|
|
||||||
## Host and Query Metadata
|
|
||||||
|
|
||||||
- var top="vertical-align:top"
|
|
||||||
table(width="100%")
|
|
||||||
col(width="50%")
|
|
||||||
col(width="50%")
|
|
||||||
tr
|
|
||||||
th TypeScript
|
|
||||||
th ES5 JavaScript
|
|
||||||
tr(style=top)
|
|
||||||
|
|
||||||
td
|
|
||||||
:marked
|
|
||||||
### Host Decorators
|
|
||||||
|
|
||||||
We can use host property decorators to bind a host element to a component or directive.
|
|
||||||
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 bimds
|
|
||||||
host element events to component event handlers.
|
|
||||||
|
|
||||||
+makeExample('cb-ts-to-js/ts/app/heroes-bindings.component.ts')(format="." )
|
|
||||||
|
|
||||||
.alert.is-helpful
|
|
||||||
:marked
|
|
||||||
In TypeScript we can also use `host` metadata
|
|
||||||
instead of the `@HostBinding` and `@HostListener` property decorators.
|
|
||||||
td
|
|
||||||
:marked
|
|
||||||
### Host Metadata
|
|
||||||
|
|
||||||
We add a `host` attribute to the component metadata to achieve the
|
|
||||||
same effect as `@HostBinding` and `@HostListener`.
|
|
||||||
|
|
||||||
The `host` value is an object whose properties are host property and listener bindings:
|
|
||||||
|
|
||||||
* Each key follows regular Angular binding syntax: `[property]` for host bindings
|
|
||||||
or `(event)` for host listeners.
|
|
||||||
* Each value identifies the corresponding component property or method.
|
|
||||||
|
|
||||||
+makeExample('cb-ts-to-js/js/app/heroes-bindings.component.js')(format="." )
|
|
||||||
|
|
||||||
tr(style=top)
|
|
||||||
td
|
|
||||||
:marked
|
|
||||||
### Query Decorators
|
|
||||||
|
|
||||||
There are several property decorators for querying the descendants of
|
|
||||||
a component or directive.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
+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.
|
|
||||||
|
|
||||||
+makeExample('cb-ts-to-js/ts/app/heroes-queries.component.ts', 'content')(format="." )
|
|
||||||
|
|
||||||
.alert.is-helpful
|
|
||||||
:marked
|
|
||||||
In TypeScript we can also use the `queries` metadata
|
|
||||||
instead of the `@ViewChild` and `@ContentChild` property decorators.
|
|
||||||
td
|
|
||||||
:marked
|
|
||||||
### Query Metadata
|
|
||||||
|
|
||||||
We access a component's view children by adding a `queries` attribute to
|
|
||||||
the component metadata. It should be an object where:
|
|
||||||
|
|
||||||
* Each key is the name of a component property that will hold the view children
|
|
||||||
* Each value is an instance of either `ViewChild` or `ViewChildren`.
|
|
||||||
|
|
||||||
+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="." )
|
|
||||||
|
|
|
@ -58,7 +58,7 @@
|
||||||
|
|
||||||
"ts-to-js": {
|
"ts-to-js": {
|
||||||
"title": "TypeScript to JavaScript",
|
"title": "TypeScript to JavaScript",
|
||||||
"intro": "Convert Angular TypeScript examples into ES5 JavaScript"
|
"intro": "Convert Angular TypeScript examples into ES6 and ES5 JavaScript"
|
||||||
},
|
},
|
||||||
|
|
||||||
"visual-studio-2015": {
|
"visual-studio-2015": {
|
||||||
|
|
|
@ -1 +1,669 @@
|
||||||
include ../../../js/latest/cookbook/ts-to-js
|
include ../../../../_includes/_util-fns
|
||||||
|
|
||||||
|
:marked
|
||||||
|
Anything you can do with Angular in _TypeScript_, you can also do
|
||||||
|
in JavaScript. Translating from one language to the other is mostly a
|
||||||
|
matter of changing the way you organize your code and access Angular APIs.
|
||||||
|
|
||||||
|
_TypeScript_ is a popular language option for Angular development.
|
||||||
|
Most code examples on the Internet as well as on this site are written in _TypeScript_.
|
||||||
|
This cookbook contains recipes for translating _TypeScript_
|
||||||
|
code examples to _ES6_ and to _ES5_ so that JavaScript developers
|
||||||
|
can read and write Angular apps in their preferred dialect.
|
||||||
|
|
||||||
|
a#toc
|
||||||
|
:marked
|
||||||
|
## Table of contents
|
||||||
|
|
||||||
|
[_TypeScript_ to _ES6_ to _ES5_](#from-ts)<br>
|
||||||
|
[Modularity: imports and exports](#modularity)<br>
|
||||||
|
[Classes and Class Metadata](#class-metadata)<br>
|
||||||
|
[_ES5_ DSL](#dsl)<br>
|
||||||
|
[Interfaces](#interfaces)<br>
|
||||||
|
[Input and Output Metadata](#io-decorators)<br>
|
||||||
|
[Dependency Injection](#dependency-injection)<br>
|
||||||
|
[Host Binding](#host-binding)<br>
|
||||||
|
[View and Child Decorators](#view-child-decorators)<br>
|
||||||
|
[AoT compilation in _TypeScript_ Only](#aot)<br>
|
||||||
|
|
||||||
|
**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.**
|
||||||
|
|
||||||
|
a#from-ts
|
||||||
|
.l-main-section
|
||||||
|
:marked
|
||||||
|
## _TypeScript_ to _ES6_ to _ES5_
|
||||||
|
|
||||||
|
_TypeScript_
|
||||||
|
<a href="https://www.typescriptlang.org" target="_blank" title='"TypeScript is a typed, superset of JavaScript"'>is a typed superset of _ES6 JavaScript_</a>.
|
||||||
|
_ES6 JavaScript_ is a superset of _ES5 JavaScript_. _ES5_ is the kind of JavaScript that runs natively in all modern browsers.
|
||||||
|
The transformation of _TypeScript_ code all the way down to _ES5_ code can be seen as "shedding" features.
|
||||||
|
|
||||||
|
The downgrade progression is
|
||||||
|
* _TypeScript_ to _ES6-with-decorators_
|
||||||
|
* _ES6-with-decorators_ to _ES6-without-decorators_ ("_plain ES6_")
|
||||||
|
* _ES6-without-decorators_ to _ES5_
|
||||||
|
|
||||||
|
When translating from _TypeScript_ to _ES6-with-decorators_, remove
|
||||||
|
[class property access modifiers](http://www.typescriptlang.org/docs/handbook/classes.html#public-private-and-protected-modifiers)
|
||||||
|
such as `public` and `private`.
|
||||||
|
Remove most of the
|
||||||
|
[type declarations](https://www.typescriptlang.org/docs/handbook/basic-types.html),
|
||||||
|
such as `:string` and `:boolean`
|
||||||
|
but **keep the constructor parameter types which are used for dependency injection**.
|
||||||
|
|
||||||
|
|
||||||
|
From _ES6-with-decorators_ to _plain ES6_, remove all
|
||||||
|
[decorators](https://www.typescriptlang.org/docs/handbook/decorators.html)
|
||||||
|
and the remaining types.
|
||||||
|
You must declare properties in the class constructor (`this.title = '...'`) rather than in the body of the class.
|
||||||
|
|
||||||
|
Finally, from _plain ES6_ to _ES5_, the main missing features are `import`
|
||||||
|
statements and `class` declarations.
|
||||||
|
|
||||||
|
For _plain ES6_ transpilation you can _start_ with a setup similar to the
|
||||||
|
[_TypeScript_ quickstart](https://github.com/angular/quickstart) and adjust the application code accordingly.
|
||||||
|
Transpile 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#modularity
|
||||||
|
.l-main-section
|
||||||
|
:marked
|
||||||
|
## Importing and Exporting
|
||||||
|
|
||||||
|
### Importing Angular Code
|
||||||
|
|
||||||
|
In both _TypeScript_ and _ES6_, you import Angular classes, functions, and other members with _ES6_ `import` statements.
|
||||||
|
|
||||||
|
In _ES5_, you access the Angular entities of the [the Angular packages](../glossary.html#!#scoped-package)
|
||||||
|
through the global `ng` object.
|
||||||
|
Anything you can import from `@angular` is a nested member of this `ng` object:
|
||||||
|
|
||||||
|
+makeTabs(`
|
||||||
|
cb-ts-to-js/ts/app/app.module.ts,
|
||||||
|
cb-ts-to-js/js-es6-decorators/app/app.module.es6,
|
||||||
|
cb-ts-to-js/js-es6/app/app.module.es6,
|
||||||
|
cb-ts-to-js/js/app/app.module.js
|
||||||
|
`,
|
||||||
|
'ng2import,ng2import,ng2import,ng2import',
|
||||||
|
` TypeScript,
|
||||||
|
ES6 JavaScript with decorators,
|
||||||
|
ES6 JavaScript,
|
||||||
|
ES5 JavaScript
|
||||||
|
`)(format='.')
|
||||||
|
|
||||||
|
:marked
|
||||||
|
### Exporting Application Code
|
||||||
|
|
||||||
|
Each file in a _TypeScript_ or _ES6_ Angular application constitutes an _ES6_ module.
|
||||||
|
When you want to make something available to other modules, you `export` it.
|
||||||
|
|
||||||
|
_ES5_ lacks native support for modules.
|
||||||
|
In an Angular _ES5_ application, you load each file manually by adding a `<script>` tag to `index.html`.
|
||||||
|
.alert.is-important
|
||||||
|
:marked
|
||||||
|
The order of `<script>` tags is often significant.
|
||||||
|
You must load a file that defines a public JavaScript entity before a file that references that entity.
|
||||||
|
:marked
|
||||||
|
The best practice in _ES5_ is to create a form of modularity that avoids polluting the global scope.
|
||||||
|
Add one application namespace object such as `app` to the global `document`.
|
||||||
|
Then each code file "exports" public entities by attaching them to that namespace object, e.g., `app.HeroComponent`.
|
||||||
|
You could factor a large application into several sub-namespaces
|
||||||
|
which leads to "exports" along the lines of `app.heroQueries.HeroComponent`.
|
||||||
|
|
||||||
|
Every _ES5_ file should wrap code in an
|
||||||
|
[Immediately Invoked Function Expression (IIFE)](https://en.wikipedia.org/wiki/Immediately-invoked_function_expression)
|
||||||
|
to limit unintentional leaking of private symbols into the global scope.
|
||||||
|
|
||||||
|
Here is a `HeroComponent` as it might be defined and "exported" in each of the four language variants.
|
||||||
|
|
||||||
|
+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
|
||||||
|
### Importing Application Code
|
||||||
|
|
||||||
|
In _TypeScript_ and _ES6_ apps, you `import` things that have been exported from other modules.
|
||||||
|
|
||||||
|
In _ES5_ you use the shared namespace object to access "exported" entities from other files.
|
||||||
|
|
||||||
|
+makeTabs(`
|
||||||
|
cb-ts-to-js/ts/app/app.module.ts,
|
||||||
|
cb-ts-to-js/js-es6-decorators/app/app.module.es6,
|
||||||
|
cb-ts-to-js/js-es6/app/app.module.es6,
|
||||||
|
cb-ts-to-js/js/app/app.module.js
|
||||||
|
`,
|
||||||
|
'appimport,appimport,appimport,appimport',
|
||||||
|
` TypeScript,
|
||||||
|
ES6 JavaScript with decorators,
|
||||||
|
ES6 JavaScript,
|
||||||
|
ES5 JavaScript
|
||||||
|
`)(format='.')
|
||||||
|
|
||||||
|
.alert.is-helpful
|
||||||
|
:marked
|
||||||
|
Alternatively, you can use a module loader such as Webpack or
|
||||||
|
Browserify in an Angular JavaScript project. In such a project, you would
|
||||||
|
use _CommonJS_ modules and the `require` function to load Angular framework code.
|
||||||
|
Then use `module.exports` and `require` to export and import application code.
|
||||||
|
|
||||||
|
|
||||||
|
a#class-metadata
|
||||||
|
.l-main-section
|
||||||
|
:marked
|
||||||
|
## Classes and Class Metadata
|
||||||
|
|
||||||
|
### Classes
|
||||||
|
|
||||||
|
Most Angular _TypeScript_ and _ES6_ code is written as classes.
|
||||||
|
|
||||||
|
Properties and method parameters of _TypeScript_ classes may be marked with the access modifiers
|
||||||
|
`private`, `internal`, and `public`.
|
||||||
|
Remove these modifiers when translating to JavaScript.
|
||||||
|
|
||||||
|
Most type declarations (e.g, `:string` and `:boolean`) should be removed when translating to JavaScript.
|
||||||
|
When translating to _ES6-with-decorators_, ***do not remove types from constructor parameters!***
|
||||||
|
|
||||||
|
Look for types in _TypeScript_ property declarations.
|
||||||
|
In general it is better to initialize such properties with default values because
|
||||||
|
many browser JavaScript engines can generate more performant code.
|
||||||
|
When _TypeScript_ code follows this same advice, it can infer the property types
|
||||||
|
and there is nothing to remove during translation.
|
||||||
|
|
||||||
|
In _ES6-without-decorators_, properties of classes must be assigned inside the constructor.
|
||||||
|
|
||||||
|
_ES5_ JavaScript has no classes.
|
||||||
|
Use the constructor function pattern instead, adding methods to the prototype.
|
||||||
|
|
||||||
|
+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
|
||||||
|
`,
|
||||||
|
'class,class,class,constructorproto',
|
||||||
|
` TypeScript,
|
||||||
|
ES6 JavaScript with decorators,
|
||||||
|
ES6 JavaScript,
|
||||||
|
ES5 JavaScript
|
||||||
|
`)
|
||||||
|
|
||||||
|
:marked
|
||||||
|
### Metadata
|
||||||
|
|
||||||
|
When writing in _TypeScript_ or _ES6-with-decorators_,
|
||||||
|
provide configuration and metadata by adorning a class with one or more *decorators*.
|
||||||
|
For example, you supply metadata to a component class by preceding its definition with a
|
||||||
|
[`@Component`](../api/core/index/Component-decorator.html) decorator function whose
|
||||||
|
argument is an object literal with metadata properties.
|
||||||
|
|
||||||
|
In _plain ES6_, you provide metadata by attaching an `annotations` array to the _class_.
|
||||||
|
Each item in the array is a new instance of a metadata decorator created with a similar metadata object literal.
|
||||||
|
|
||||||
|
In _ES5_, you also provide an `annotations` array but you attach it to the _constructor function_ rather than to a class.
|
||||||
|
|
||||||
|
See these variations side-by-side:
|
||||||
|
|
||||||
|
+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
|
||||||
|
`,
|
||||||
|
'metadata,metadata,metadata,metadata',
|
||||||
|
` TypeScript,
|
||||||
|
ES6 JavaScript with decorators,
|
||||||
|
ES6 JavaScript,
|
||||||
|
ES5 JavaScript
|
||||||
|
`)
|
||||||
|
|
||||||
|
:marked
|
||||||
|
***External Template file***
|
||||||
|
|
||||||
|
A large component template is often kept in a separate template file.
|
||||||
|
+makeExample('cb-ts-to-js/ts/app/hero-title.component.html', '', 'app/hero-title.component.html')(format='.')
|
||||||
|
:marked
|
||||||
|
The component (`HeroTitleComponent` in this case) then references the template file in its metadata `templateUrl` property:
|
||||||
|
+makeTabs(`
|
||||||
|
cb-ts-to-js/ts/app/hero-title.component.ts,
|
||||||
|
cb-ts-to-js/js-es6-decorators/app/hero-title.component.es6,
|
||||||
|
cb-ts-to-js/js-es6/app/hero-title.component.es6,
|
||||||
|
cb-ts-to-js/js/app/hero-title.component.js`,
|
||||||
|
'templateUrl, templateUrl, templateUrl, templateUrl',
|
||||||
|
`TypeScript,
|
||||||
|
ES6 JavaScript with decorators,
|
||||||
|
ES6 JavaScript,
|
||||||
|
ES5 JavaScript
|
||||||
|
`)(format='.')
|
||||||
|
|
||||||
|
:marked
|
||||||
|
Note that the _TypeScript_ and both _ES6_ `templateUrl` properties identify the location of the template file _relative to the component module_.
|
||||||
|
All three metadata configurations specify the `moduleId` property
|
||||||
|
so that Angular can calculate the proper module address.
|
||||||
|
|
||||||
|
The _ES5_ approach shown here does not support modules and therefore there is no way to calculate a _module-relative URL_.
|
||||||
|
The `templateUrl` for the _ES5_ code must specify the _path from the project root_ and
|
||||||
|
omits the irrelevant `moduleId` property.
|
||||||
|
|
||||||
|
.l-sub-section
|
||||||
|
:marked
|
||||||
|
With the right tooling, the `moduleId` may not be needed in the other JavaScript dialects either.
|
||||||
|
But it's safest to provide it anyway.
|
||||||
|
|
||||||
|
a#dsl
|
||||||
|
.l-main-section
|
||||||
|
:marked
|
||||||
|
## _ES5_ DSL
|
||||||
|
|
||||||
|
This _ES5_ pattern of creating a constructor and annotating it with metadata is so common that Angular
|
||||||
|
provides a convenience API to make it a little more compact and locates the metadata above the constructor,
|
||||||
|
as you would if you wrote in _TypeScript_ or _ES6-with-decorators_.
|
||||||
|
|
||||||
|
This _API_ (_Application Programming Interface_) is commonly known as the _ES5 DSL_ (_Domain Specific Language_).
|
||||||
|
|
||||||
|
Set an application namespace property (e.g., `app.HeroDslComponent`) to the result of an `ng.core.Component` function call.
|
||||||
|
Pass the same metadata object to `ng.core.Component` as you did before.
|
||||||
|
Then chain a call to the `Class` method which takes an object defining the class constructor and instance methods.
|
||||||
|
|
||||||
|
Here is an example of the `HeroComponent`, re-written with the DSL,
|
||||||
|
next to the original _ES5_ version for comparison:
|
||||||
|
|
||||||
|
+makeTabs(`
|
||||||
|
cb-ts-to-js/js/app/hero.component.js,
|
||||||
|
cb-ts-to-js/js/app/hero.component.js
|
||||||
|
`,
|
||||||
|
'dsl,',
|
||||||
|
`
|
||||||
|
ES5 JavaScript with DSL,
|
||||||
|
ES5 JavaScript
|
||||||
|
`)
|
||||||
|
|
||||||
|
.callout.is-helpful
|
||||||
|
header Name the constructor
|
||||||
|
:marked
|
||||||
|
A **named** constructor displays clearly in the console log
|
||||||
|
if the component throws a runtime error.
|
||||||
|
An **unnamed** constructor displays as an anonymous function (e.g., `class0`)
|
||||||
|
which is impossible to find in the source code.
|
||||||
|
|
||||||
|
:marked
|
||||||
|
### Properties with getters and setters
|
||||||
|
|
||||||
|
_TypeScript_ and _ES6_ support with getters and setters.
|
||||||
|
Here's an example of a read-only _TypeScript_ property with a getter
|
||||||
|
that prepares a toggle-button label for the next clicked state:
|
||||||
|
+makeExample('cb-ts-to-js/ts/app/hero-queries.component.ts', 'defined-property', 'ts/app/hero-queries.component.ts')(format='.')
|
||||||
|
|
||||||
|
:marked
|
||||||
|
This _TypeScript_ "getter" property is transpiled to an _ES5_
|
||||||
|
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty"
|
||||||
|
target="_blank" title="Defined Properties">defined property</a>.
|
||||||
|
The _ES5 DSL_ does not support _defined properties_ directly
|
||||||
|
but you can still create them by extracting the "class" prototype and
|
||||||
|
adding the _defined property_ in raw JavaScript like this:
|
||||||
|
+makeExample('cb-ts-to-js/js/app/hero-queries.component.js', 'defined-property','js/app/hero-queries.component.ts')(format='.')
|
||||||
|
|
||||||
|
:marked
|
||||||
|
### DSL for other classes
|
||||||
|
There are similar DSLs for other decorated classes.
|
||||||
|
You can define a directive with `ng.core.Directive`:
|
||||||
|
|
||||||
|
code-example.
|
||||||
|
app.MyDirective = ng.core.Directive({
|
||||||
|
selector: '[myDirective]'
|
||||||
|
}).Class({
|
||||||
|
...
|
||||||
|
});
|
||||||
|
:marked
|
||||||
|
and a pipe with `ng.core.Pipe`:
|
||||||
|
code-example.
|
||||||
|
app.MyPipe = ng.core.Pipe({
|
||||||
|
name: 'myPipe'
|
||||||
|
}).Class({
|
||||||
|
...
|
||||||
|
});
|
||||||
|
|
||||||
|
a#interfaces
|
||||||
|
.l-main-section
|
||||||
|
:marked
|
||||||
|
## Interfaces
|
||||||
|
|
||||||
|
A _TypeScript_ interface helps ensure that a class implements the interface's members correctly.
|
||||||
|
We strongly recommend Angular interfaces where appropriate.
|
||||||
|
For example, the component class that implements the `ngOnInit` lifecycle hook method
|
||||||
|
should implement the `OnInit` interface.
|
||||||
|
|
||||||
|
_TypeScript_ interfaces exist for developer convenience and are not used by Angular at runtime.
|
||||||
|
They have no physical manifestation in the generated JavaScript code.
|
||||||
|
Just implement the methods and ignore interfaces when translating code samples from _TypeScript_ to JavaScript.
|
||||||
|
|
||||||
|
+makeTabs(`
|
||||||
|
cb-ts-to-js/ts/app/hero-lifecycle.component.ts,
|
||||||
|
cb-ts-to-js/js-es6-decorators/app/hero-lifecycle.component.es6,
|
||||||
|
cb-ts-to-js/js-es6/app/hero-lifecycle.component.es6,
|
||||||
|
cb-ts-to-js/js/app/hero-lifecycle.component.js,
|
||||||
|
cb-ts-to-js/js/app/hero-lifecycle.component.js
|
||||||
|
`,
|
||||||
|
',,,,dsl',
|
||||||
|
` TypeScript,
|
||||||
|
ES6 JavaScript with decorators,
|
||||||
|
ES6 JavaScript,
|
||||||
|
ES5 JavaScript,
|
||||||
|
ES5 JavaScript with DSL
|
||||||
|
`)
|
||||||
|
|
||||||
|
a#io-decorators
|
||||||
|
.l-main-section
|
||||||
|
:marked
|
||||||
|
## Input and Output Metadata
|
||||||
|
|
||||||
|
### Input and Output Decorators
|
||||||
|
|
||||||
|
In _TypeScript_ and _ES6-with-decorators_, you often add metadata to class _properties_ with _property decorators_.
|
||||||
|
For example, you apply [`@Input` and `@Output` property decorators](../guide/template-syntax.html#inputs-outputs)
|
||||||
|
to public class properties that will be the target of data binding expressions in parent components.
|
||||||
|
|
||||||
|
There is no equivalent of a property decorator in _ES5_ or _plain ES6_.
|
||||||
|
Fortunately, every property decorator has an equivalent representation in a class decorator metadata property.
|
||||||
|
A _TypeScript_ `@Input` property decorator can be represented by an item in the `Component` metadata's `inputs` array.
|
||||||
|
|
||||||
|
You already know how to add `Component` or `Directive` class metadata in _any_ JavaScript dialect so
|
||||||
|
there's nothing fundamentally new about adding another property.
|
||||||
|
But note that what would have been _separate_ `@Input` and `@Output` property decorators for each class property are
|
||||||
|
combined in the metadata `inputs` and `outputs` _arrays_.
|
||||||
|
|
||||||
|
+makeTabs(`
|
||||||
|
cb-ts-to-js/ts/app/confirm.component.ts,
|
||||||
|
cb-ts-to-js/js-es6-decorators/app/confirm.component.es6,
|
||||||
|
cb-ts-to-js/js-es6/app/confirm.component.es6,
|
||||||
|
cb-ts-to-js/js/app/confirm.component.js,
|
||||||
|
cb-ts-to-js/js/app/confirm.component.js
|
||||||
|
`,
|
||||||
|
',,,,dsl',
|
||||||
|
` TypeScript,
|
||||||
|
ES6 JavaScript with decorators,
|
||||||
|
ES6 JavaScript,
|
||||||
|
ES5 JavaScript,
|
||||||
|
ES5 JavaScript with DSL
|
||||||
|
`)
|
||||||
|
:marked
|
||||||
|
In the previous example, one of the public-facing binding names (`cancelMsg`)
|
||||||
|
differs from the corresponding class property name (`notOkMsg`).
|
||||||
|
That's OK but you must tell Angular about it so that it can map an external binding of `cancelMsg`
|
||||||
|
to the component's `notOkMsg` property.
|
||||||
|
|
||||||
|
In _TypeScript_ and _ES6-with-decorators_,
|
||||||
|
you specify the special binding name in the argument to the property decorator.
|
||||||
|
|
||||||
|
In _ES5_ and _plain ES6_ code, convey this pairing with the `propertyName: bindingName` syntax in the class metadata.
|
||||||
|
|
||||||
|
.l-main-section
|
||||||
|
:marked
|
||||||
|
## Dependency Injection
|
||||||
|
Angular relies heavily on [Dependency Injection](../guide/dependency-injection.html) to provide services to the objects it creates.
|
||||||
|
When Angular creates a new component, directive, pipe or another service,
|
||||||
|
it sets the class constructor parameters to instances of services provided by an _Injector_.
|
||||||
|
|
||||||
|
The developer must tell Angular what to inject into each parameter.
|
||||||
|
|
||||||
|
### Injection by Class Type
|
||||||
|
|
||||||
|
The easiest and most popular technique in _TypeScript_ and _ES6-with-decorators_ is to set the constructor parameter type
|
||||||
|
to the class associated with the service to inject.
|
||||||
|
|
||||||
|
The _TypeScript_ transpiler writes parameter type information into the generated JavaScript.
|
||||||
|
Angular reads that information at runtime and locates the corresponding service in the appropriate _Injector_..
|
||||||
|
The _ES6-with-decorators_ transpiler does essentially the same thing using the same parameter-typing syntax.
|
||||||
|
|
||||||
|
_ES5_ and _plain ES6_ lack types so you must identify "injectables" by attaching a **`parameters`** array to the constructor function.
|
||||||
|
Each item in the array specifies the service's injection token.
|
||||||
|
|
||||||
|
As with _TypeScript_ the most popular token is a class,
|
||||||
|
or rather a _constructor function_ that represents a class in _ES5_ and _plain ES6_.
|
||||||
|
The format of the `parameters` array varies:
|
||||||
|
|
||||||
|
* _plain ES6_ — nest each constructor function in a sub-array.
|
||||||
|
|
||||||
|
* _ES5_ — simply list the constructor functions.
|
||||||
|
|
||||||
|
When writing with _ES5 DSL_, set the `Class.constructor` property to
|
||||||
|
an array whose first parameters are the injectable constructor functions and whose
|
||||||
|
last parameter is the class constructor itself.
|
||||||
|
This format should be familiar to Angular 1 developers.
|
||||||
|
|
||||||
|
+makeTabs(`
|
||||||
|
cb-ts-to-js/ts/app/hero-di.component.ts,
|
||||||
|
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.component.js
|
||||||
|
`,
|
||||||
|
',,,,dsl',
|
||||||
|
` TypeScript,
|
||||||
|
ES6 JavaScript with decorators,
|
||||||
|
ES6 JavaScript,
|
||||||
|
ES5 JavaScript,
|
||||||
|
ES5 JavaScript with DSL
|
||||||
|
`)
|
||||||
|
|
||||||
|
:marked
|
||||||
|
### Injection with the @Inject decorator
|
||||||
|
|
||||||
|
Sometimes the dependency injection token isn't a class or constructor function.
|
||||||
|
|
||||||
|
In _TypeScript_ and _ES6-with-decorators_, you precede the class constructor parameter
|
||||||
|
by calling the `@Inject()` decorator with the injection token.
|
||||||
|
In the following example, the token is the string `'heroName'`.
|
||||||
|
|
||||||
|
The other JavaScript dialogs add a `parameters` array to the class contructor function.
|
||||||
|
Each item constains a new instance of `Inject('heroName')`:
|
||||||
|
|
||||||
|
* _plain ES6_ — each item is a new instance of `Inject(token)` in a sub-array.
|
||||||
|
|
||||||
|
* _ES5_ — simply list the string tokens.
|
||||||
|
|
||||||
|
When writing with _ES5 DSL_, set the `Class.constructor` property to a function definition
|
||||||
|
array as before. Create a `new ng.core.Inject(token)` for each parameter.
|
||||||
|
|
||||||
|
+makeTabs(`
|
||||||
|
cb-ts-to-js/ts/app/hero-di-inject.component.ts,
|
||||||
|
cb-ts-to-js/js-es6-decorators/app/hero-di-inject.component.es6,
|
||||||
|
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
|
||||||
|
`,
|
||||||
|
',,,,dsl',
|
||||||
|
` TypeScript,
|
||||||
|
ES6 JavaScript with decorators,
|
||||||
|
ES6 JavaScript,
|
||||||
|
ES5 JavaScript,
|
||||||
|
ES5 JavaScript with DSL
|
||||||
|
`)
|
||||||
|
|
||||||
|
:marked
|
||||||
|
### Additional Injection Decorators
|
||||||
|
|
||||||
|
You can qualify injection behavior with injection decorators from `@angular/core`.
|
||||||
|
|
||||||
|
In _TypeScript_ and _ES6-with-decorators_,
|
||||||
|
you precede the constructor parameters with injection qualifiers such as:
|
||||||
|
* [`@Optional`](../api/core/index/Optional-decorator.html) sets the parameter to `null` if the service is missing
|
||||||
|
* [`@Attribute`](../api/core/index/Attribute-interface.html) to inject a host element attribute value
|
||||||
|
* [`@ContentChild`](../api/core/index/ContentChild-decorator.html) to inject a content child
|
||||||
|
* [`@ViewChild`](../api/core/index/ViewChild-decorator.html) to inject a view child
|
||||||
|
* [`@Host`](../api/core/index/Host-decorator.html) to inject a service in this component or its host
|
||||||
|
* [`@SkipSelf`](../api/core/index/SkipSelf-decorator.html) to inject a service provided in an ancestor of this component
|
||||||
|
|
||||||
|
In _plain ES6_ and _ES5_, create an instance of the equivalent injection qualifier in a nested array within the `parameters` array.
|
||||||
|
For example, you'd write `new Optional()` in _plain ES6_ and `new ng.core.Optional()` in _ES5_.
|
||||||
|
|
||||||
|
|
||||||
|
When writing with _ES5 DSL_, set the `Class.constructor` property to a function definition
|
||||||
|
array as before. Use a nested array to define a parameter's complete injection specification.
|
||||||
|
|
||||||
|
+makeTabs(`
|
||||||
|
cb-ts-to-js/ts/app/hero-title.component.ts,
|
||||||
|
cb-ts-to-js/js-es6-decorators/app/hero-title.component.es6,
|
||||||
|
cb-ts-to-js/js-es6/app/hero-title.component.es6,
|
||||||
|
cb-ts-to-js/js/app/hero-title.component.js,
|
||||||
|
cb-ts-to-js/js/app/hero-title.component.js
|
||||||
|
`,
|
||||||
|
',,,,dsl',
|
||||||
|
` TypeScript,
|
||||||
|
ES6 JavaScript with decorators,
|
||||||
|
ES6 JavaScript,
|
||||||
|
ES5 JavaScript,
|
||||||
|
ES5 JavaScript with DSL
|
||||||
|
`)
|
||||||
|
.l-sub-section
|
||||||
|
:marked
|
||||||
|
In the example above, there is no provider for the `'titlePrefix'` token.
|
||||||
|
Without `Optional`, Angular would raise an error.
|
||||||
|
With `Optional`, Angular sets the constructor parameter to `null`
|
||||||
|
and the component displays the title without a prefix.
|
||||||
|
|
||||||
|
a#host-binding
|
||||||
|
.l-main-section
|
||||||
|
:marked
|
||||||
|
## Host Binding
|
||||||
|
Angular supports bindings to properties and events of the _host element_ which is the
|
||||||
|
element whose tag matches the component selector.
|
||||||
|
|
||||||
|
### Host Decorators
|
||||||
|
|
||||||
|
In _TypeScript_ and _ES6-with-decorators_, you can use host property decorators to bind a host
|
||||||
|
element to a component or directive.
|
||||||
|
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.
|
||||||
|
|
||||||
|
In _plain ES6_ or _ES5_, add a `host` attribute to the component metadata to achieve the
|
||||||
|
same effect as `@HostBinding` and `@HostListener`.
|
||||||
|
|
||||||
|
The `host` value is an object whose properties are host property and listener bindings:
|
||||||
|
|
||||||
|
* Each key follows regular Angular binding syntax: `[property]` for host bindings
|
||||||
|
or `(event)` for host listeners.
|
||||||
|
* Each value identifies the corresponding component property or method.
|
||||||
|
|
||||||
|
+makeTabs(`
|
||||||
|
cb-ts-to-js/ts/app/hero-host.component.ts,
|
||||||
|
cb-ts-to-js/js-es6-decorators/app/hero-host.component.es6,
|
||||||
|
cb-ts-to-js/js-es6/app/hero-host.component.es6,
|
||||||
|
cb-ts-to-js/js/app/hero-host.component.js,
|
||||||
|
cb-ts-to-js/js/app/hero-host.component.js
|
||||||
|
`,
|
||||||
|
',,,,dsl',
|
||||||
|
` TypeScript,
|
||||||
|
ES6 JavaScript with decorators,
|
||||||
|
ES6 JavaScript,
|
||||||
|
ES5 JavaScript,
|
||||||
|
ES5 JavaScript with DSL
|
||||||
|
`)
|
||||||
|
|
||||||
|
:marked
|
||||||
|
### Host Metadata
|
||||||
|
Some developers prefer to specify host properties and listeners
|
||||||
|
in the component metadata.
|
||||||
|
They'd _rather_ do it the way you _must_ do it _ES5_ and _plain ES6_.
|
||||||
|
|
||||||
|
The following re-implementation of the `HeroComponent` reminds us that _any property metadata decorator_
|
||||||
|
can be expressed as component or directive metadata in both _TypeScript_ and _ES6-with-decorators_.
|
||||||
|
These particular _TypeScript_ and _ES6_ code snippets happen to be identical.
|
||||||
|
+makeTabs(`
|
||||||
|
cb-ts-to-js/ts/app/hero-host-meta.component.ts,
|
||||||
|
cb-ts-to-js/js-es6-decorators/app/hero-host-meta.component.es6
|
||||||
|
`,
|
||||||
|
'',
|
||||||
|
` TypeScript,
|
||||||
|
ES6 JavaScript with decorators
|
||||||
|
`)
|
||||||
|
|
||||||
|
a#view-child-decorators
|
||||||
|
.l-main-section
|
||||||
|
:marked
|
||||||
|
### View and Child Decorators
|
||||||
|
|
||||||
|
Several _property_ decorators query a component's nested view and content components.
|
||||||
|
|
||||||
|
.l-sub-section
|
||||||
|
:marked
|
||||||
|
_View_ children are associated with element tags that appear _within_ the component's template.
|
||||||
|
|
||||||
|
_Content_ children are associated with elements that appear _between_ the component's element tags;
|
||||||
|
they are projected into an `<ng-content>` slot in the component's template.
|
||||||
|
:marked
|
||||||
|
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.
|
||||||
|
|
||||||
|
In _ES5_ and _ES6_, you access a component's view children by adding a `queries` property to the component metadata.
|
||||||
|
The `queries` property value is a hash map.
|
||||||
|
|
||||||
|
* each _key_ is the name of a component property that will hold the view child or children.
|
||||||
|
* each _value_ is a new instance of either `ViewChild` or `ViewChildren`.
|
||||||
|
|
||||||
|
+makeTabs(`
|
||||||
|
cb-ts-to-js/ts/app/hero-queries.component.ts,
|
||||||
|
cb-ts-to-js/js-es6-decorators/app/hero-queries.component.es6,
|
||||||
|
cb-ts-to-js/js-es6/app/hero-queries.component.es6,
|
||||||
|
cb-ts-to-js/js/app/hero-queries.component.js
|
||||||
|
`,
|
||||||
|
'view, view, view, view',
|
||||||
|
` TypeScript,
|
||||||
|
ES6 JavaScript with decorators,
|
||||||
|
ES6 JavaScript,
|
||||||
|
ES5 JavaScript with DSL
|
||||||
|
`)
|
||||||
|
|
||||||
|
: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.
|
||||||
|
|
||||||
|
They can be added in the same way as [`@ViewChild`](../api/core/index/ViewChild-decorator.html) and
|
||||||
|
[`@ViewChildren`](../api/core/index/ViewChildren-decorator.html).
|
||||||
|
|
||||||
|
+makeTabs(`
|
||||||
|
cb-ts-to-js/ts/app/hero-queries.component.ts,
|
||||||
|
cb-ts-to-js/js-es6-decorators/app/hero-queries.component.es6,
|
||||||
|
cb-ts-to-js/js-es6/app/hero-queries.component.es6,
|
||||||
|
cb-ts-to-js/js/app/hero-queries.component.js
|
||||||
|
`,
|
||||||
|
'content, content, content, content',
|
||||||
|
` TypeScript,
|
||||||
|
ES6 JavaScript with decorators,
|
||||||
|
ES6 JavaScript,
|
||||||
|
ES5 JavaScript with DSL
|
||||||
|
`)
|
||||||
|
|
||||||
|
.alert.is-helpful
|
||||||
|
:marked
|
||||||
|
In _TypeScript_ and _ES6-with-decorators_ you can also use the `queries` metadata
|
||||||
|
instead of the `@ViewChild` and `@ContentChild` property decorators.
|
||||||
|
|
||||||
|
a#aot
|
||||||
|
.l-main-section
|
||||||
|
:marked
|
||||||
|
## AoT Compilation in _TypeScript_ only
|
||||||
|
|
||||||
|
Angular offers two modes of template compilation, JiT (_Just-in-Time_) and
|
||||||
|
[AoT (_Ahead-of-Time_)](aot-compiler.html).
|
||||||
|
Currently the AoT compiler only works with _TypeScript_ applications because, in part, it generates
|
||||||
|
_TypeScript_ files as an intermediate result.
|
||||||
|
**AoT is not an option for pure JavaScript applications** at this time.
|
||||||
|
|
|
@ -7,6 +7,12 @@ block includes
|
||||||
The Angular documentation is a living document with continuous improvements.
|
The Angular documentation is a living document with continuous improvements.
|
||||||
This log calls attention to recent significant changes.
|
This log calls attention to recent significant changes.
|
||||||
|
|
||||||
|
## ES6 described in "TypeScript to JavaScript" (2016-11-03)
|
||||||
|
The updated "[TypeScript to JavaScript](../cookbook/ts-to-js.html)" cookbook
|
||||||
|
now explains how to write apps in ES6/7
|
||||||
|
by translating the common idioms in the TypeScript documentation examples
|
||||||
|
(and elsewhere on the web) to ES6/7 and ES5.
|
||||||
|
|
||||||
## Sync with Angular v.2.1.1 (2016-10-21)
|
## Sync with Angular v.2.1.1 (2016-10-21)
|
||||||
Docs and code samples updated and tested with Angular v.2.1.0
|
Docs and code samples updated and tested with Angular v.2.1.0
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue