docs: remove TypeScript to JavaScript guide & sample
This commit is contained in:
parent
0a73e8d062
commit
697c6ed0fe
|
@ -55,10 +55,6 @@ dist/
|
||||||
!testing/src/browser-test-shim.js
|
!testing/src/browser-test-shim.js
|
||||||
!testing/karma*.js
|
!testing/karma*.js
|
||||||
|
|
||||||
# TS to JS
|
|
||||||
!ts-to-js/js*/**/*.js
|
|
||||||
ts-to-js/js*/**/system*.js
|
|
||||||
|
|
||||||
# webpack
|
# webpack
|
||||||
!webpack/**/config/*.js
|
!webpack/**/config/*.js
|
||||||
!webpack/**/*webpack*.js
|
!webpack/**/*webpack*.js
|
||||||
|
|
|
@ -1,77 +0,0 @@
|
||||||
'use strict'; // necessary for es6 output in node
|
|
||||||
|
|
||||||
import { browser, element, by } from 'protractor';
|
|
||||||
|
|
||||||
describe('TypeScript to Javascript tests', function () {
|
|
||||||
|
|
||||||
beforeAll(function () {
|
|
||||||
browser.get('');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display the basic component example', function () {
|
|
||||||
testTag('hero-view', 'Hero Detail: Windstorm');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display the component example with lifecycle methods', function () {
|
|
||||||
testTag('hero-lifecycle', 'Hero: Windstorm');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display component with DI example', function () {
|
|
||||||
testTag('hero-di', 'Hero: Windstorm');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display component with DI using @Inject example', function () {
|
|
||||||
testTag('hero-di-inject', 'Hero: Windstorm');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should support optional, attribute, and query injections', function () {
|
|
||||||
let app = element(by.css('hero-di-inject-additional'));
|
|
||||||
let h1 = app.element(by.css('h1'));
|
|
||||||
let okMsg = app.element(by.css('p'));
|
|
||||||
|
|
||||||
expect(h1.getText()).toBe('Tour of Heroes');
|
|
||||||
app.element(by.buttonText('OK')).click();
|
|
||||||
expect(okMsg.getText()).toBe('OK!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should support component with inputs and outputs', function () {
|
|
||||||
let app = element(by.css('hero-io'));
|
|
||||||
let confirmComponent = app.element(by.css('app-confirm'));
|
|
||||||
|
|
||||||
confirmComponent.element(by.buttonText('OK')).click();
|
|
||||||
expect(app.element(by.cssContainingText('span', 'OK clicked')).isPresent()).toBe(true);
|
|
||||||
|
|
||||||
confirmComponent.element(by.buttonText('Cancel')).click();
|
|
||||||
expect(app.element(by.cssContainingText('span', 'Cancel clicked')).isPresent()).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should support host bindings and host listeners', function() {
|
|
||||||
let app = element(by.css('hero-host'));
|
|
||||||
let h1 = app.element(by.css('h1'));
|
|
||||||
|
|
||||||
expect(app.getAttribute('class')).toBe('heading');
|
|
||||||
expect(app.getAttribute('title')).toContain('Tooltip');
|
|
||||||
|
|
||||||
h1.click();
|
|
||||||
expect(h1.getAttribute('class')).toBe('active');
|
|
||||||
|
|
||||||
h1.click();
|
|
||||||
browser.actions().doubleClick(h1.getWebElement()).perform();
|
|
||||||
expect(h1.getAttribute('class')).toBe('active');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should support content and view queries', function() {
|
|
||||||
let app = element(by.css('hero-queries'));
|
|
||||||
let windstorm = app.element(by.css('view-child:first-child'));
|
|
||||||
|
|
||||||
app.element(by.css('button')).click();
|
|
||||||
expect(windstorm.element(by.css('h2')).getAttribute('class')).toBe('active');
|
|
||||||
expect(windstorm.element(by.css('content-child')).getText()).toBe('Active');
|
|
||||||
});
|
|
||||||
|
|
||||||
function testTag(selector: string, expectedText: string) {
|
|
||||||
let component = element(by.css(selector));
|
|
||||||
expect(component.getText()).toBe(expectedText);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
|
@ -1,3 +0,0 @@
|
||||||
{
|
|
||||||
"build": "build:babel"
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"description": "TypeScript to JavaScript",
|
|
||||||
"basePath": "src/",
|
|
||||||
"files":[
|
|
||||||
"!**/*.d.ts",
|
|
||||||
"!**/*.js"
|
|
||||||
],
|
|
||||||
"tags":["cookbook"]
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"presets": [
|
|
||||||
"es2015",
|
|
||||||
"angular2"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
import { Component } from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'my-app',
|
|
||||||
templateUrl: './app.component.html',
|
|
||||||
styles: [
|
|
||||||
// See hero-di-inject-additional.component
|
|
||||||
'hero-host, hero-host-meta { border: 1px dashed black; display: block; padding: 4px;}',
|
|
||||||
'.heading {font-style: italic}'
|
|
||||||
]
|
|
||||||
})
|
|
||||||
export class AppComponent {
|
|
||||||
title = 'ES6 JavaScript with Decorators';
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
<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>
|
|
|
@ -1,55 +0,0 @@
|
||||||
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
|
|
|
@ -1,21 +0,0 @@
|
||||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
|
||||||
|
|
||||||
// #docregion
|
|
||||||
@Component({
|
|
||||||
selector: 'app-confirm',
|
|
||||||
templateUrl: './confirm.component.html'
|
|
||||||
})
|
|
||||||
export class ConfirmComponent {
|
|
||||||
@Input() okMsg = '';
|
|
||||||
@Input('cancelMsg') notOkMsg = '';
|
|
||||||
@Output() ok = new EventEmitter();
|
|
||||||
@Output('cancel') notOk = new EventEmitter();
|
|
||||||
|
|
||||||
onOkClick() {
|
|
||||||
this.ok.emit(true);
|
|
||||||
}
|
|
||||||
onNotOkClick() {
|
|
||||||
this.notOk.emit(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// #enddocregion
|
|
|
@ -1,6 +0,0 @@
|
||||||
<button (click)="onOkClick()">
|
|
||||||
{{okMsg}}
|
|
||||||
</button>
|
|
||||||
<button (click)="onNotOkClick()">
|
|
||||||
{{notOkMsg}}
|
|
||||||
</button>
|
|
|
@ -1,10 +0,0 @@
|
||||||
import { Injectable } from '@angular/core';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class DataService {
|
|
||||||
constructor() { }
|
|
||||||
|
|
||||||
getHeroName() {
|
|
||||||
return 'Windstorm';
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
import { Component } from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'hero-di-inject-additional',
|
|
||||||
template: `<hero-title title="Tour of Heroes"></hero-title>`
|
|
||||||
})
|
|
||||||
export class HeroComponent { }
|
|
|
@ -1,13 +0,0 @@
|
||||||
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
|
|
|
@ -1,15 +0,0 @@
|
||||||
// #docregion
|
|
||||||
import { Component } from '@angular/core';
|
|
||||||
import { DataService } from './data.service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'hero-di',
|
|
||||||
template: `<h1>Hero: {{name}}</h1>`
|
|
||||||
})
|
|
||||||
export class HeroComponent {
|
|
||||||
name = '';
|
|
||||||
constructor(dataService: DataService) {
|
|
||||||
this.name = dataService.getHeroName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// #enddocregion
|
|
|
@ -1,44 +0,0 @@
|
||||||
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
|
|
|
@ -1,39 +0,0 @@
|
||||||
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,26 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
// #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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,81 +0,0 @@
|
||||||
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
|
|
|
@ -1,25 +0,0 @@
|
||||||
import { Attribute, Component, Inject, Optional } from '@angular/core';
|
|
||||||
|
|
||||||
// #docregion
|
|
||||||
// #docregion templateUrl
|
|
||||||
@Component({
|
|
||||||
selector: 'hero-title',
|
|
||||||
templateUrl: './hero-title.component.html'
|
|
||||||
})
|
|
||||||
// #enddocregion templateUrl
|
|
||||||
export class HeroTitleComponent {
|
|
||||||
msg = '';
|
|
||||||
constructor(
|
|
||||||
@Inject('titlePrefix') @Optional() titlePrefix,
|
|
||||||
@Attribute('title') title
|
|
||||||
) {
|
|
||||||
this.titlePrefix = titlePrefix;
|
|
||||||
this.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
ok() {
|
|
||||||
this.msg = 'OK!';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// #enddocregion
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
<!-- #docregion -->
|
|
||||||
<h1>{{titlePrefix}} {{title}}</h1>
|
|
||||||
<button (click)="ok()">OK</button>
|
|
||||||
<p>{{ msg }}</p>
|
|
|
@ -1,15 +0,0 @@
|
||||||
// #docregion
|
|
||||||
// #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
|
|
|
@ -1,26 +0,0 @@
|
||||||
<!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/systemjs/dist/system.src.js"></script>
|
|
||||||
|
|
||||||
<script src="systemjs.config.js"></script>
|
|
||||||
<script>
|
|
||||||
System.import('main.js').catch(function(err){ console.error(err); });
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<my-app>Loading...</my-app>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
|
@ -1,4 +0,0 @@
|
||||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
|
||||||
import { AppModule } from './app/app.module';
|
|
||||||
|
|
||||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
|
|
@ -1,3 +0,0 @@
|
||||||
{
|
|
||||||
"build": "build:babel"
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"description": "TypeScript to JavaScript",
|
|
||||||
"basePath": "src/",
|
|
||||||
"files":[
|
|
||||||
"!**/*.d.ts",
|
|
||||||
"!**/*.js"
|
|
||||||
],
|
|
||||||
"tags":["cookbook"]
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
{
|
|
||||||
"presets": [
|
|
||||||
"es2015"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
import { Component } from '@angular/core';
|
|
||||||
|
|
||||||
export class AppComponent {
|
|
||||||
constructor() {
|
|
||||||
this.title = 'Plain ES6 JavaScript';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AppComponent.annotations = [
|
|
||||||
new Component({
|
|
||||||
selector: 'my-app',
|
|
||||||
templateUrl: './app.component.html',
|
|
||||||
styles: [
|
|
||||||
// See hero-di-inject-additional.component
|
|
||||||
'hero-host { border: 1px dashed black; display: block; padding: 4px;}',
|
|
||||||
'.heading {font-style: italic}'
|
|
||||||
]
|
|
||||||
})
|
|
||||||
];
|
|
|
@ -1,30 +0,0 @@
|
||||||
<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>
|
|
|
@ -1,56 +0,0 @@
|
||||||
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
|
|
|
@ -1,31 +0,0 @@
|
||||||
import { Component, EventEmitter } from '@angular/core';
|
|
||||||
|
|
||||||
// #docregion
|
|
||||||
export class ConfirmComponent {
|
|
||||||
constructor(){
|
|
||||||
this.ok = new EventEmitter();
|
|
||||||
this.notOk = new EventEmitter();
|
|
||||||
}
|
|
||||||
onOkClick() {
|
|
||||||
this.ok.emit(true);
|
|
||||||
}
|
|
||||||
onNotOkClick() {
|
|
||||||
this.notOk.emit(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfirmComponent.annotations = [
|
|
||||||
new Component({
|
|
||||||
selector: 'app-confirm',
|
|
||||||
templateUrl: './confirm.component.html',
|
|
||||||
inputs: [
|
|
||||||
'okMsg',
|
|
||||||
'notOkMsg: cancelMsg'
|
|
||||||
],
|
|
||||||
outputs: [
|
|
||||||
'ok',
|
|
||||||
'notOk: cancel'
|
|
||||||
]
|
|
||||||
})
|
|
||||||
];
|
|
||||||
// #enddocregion
|
|
|
@ -1,6 +0,0 @@
|
||||||
<button (click)="onOkClick()">
|
|
||||||
{{okMsg}}
|
|
||||||
</button>
|
|
||||||
<button (click)="onNotOkClick()">
|
|
||||||
{{notOkMsg}}
|
|
||||||
</button>
|
|
|
@ -1,13 +0,0 @@
|
||||||
import { Injectable } from '@angular/core';
|
|
||||||
|
|
||||||
export class DataService {
|
|
||||||
constructor() {
|
|
||||||
}
|
|
||||||
getHeroName() {
|
|
||||||
return 'Windstorm';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DataService.annotations = [
|
|
||||||
new Injectable()
|
|
||||||
];
|
|
|
@ -1,10 +0,0 @@
|
||||||
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>`
|
|
||||||
})
|
|
||||||
];
|
|
|
@ -1,20 +0,0 @@
|
||||||
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
|
|
|
@ -1,21 +0,0 @@
|
||||||
// #docregion
|
|
||||||
import { Component } from '@angular/core';
|
|
||||||
import { DataService } from './data.service';
|
|
||||||
|
|
||||||
export class HeroComponent {
|
|
||||||
constructor(dataService) {
|
|
||||||
this.name = dataService.getHeroName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HeroComponent.annotations = [
|
|
||||||
new Component({
|
|
||||||
selector: 'hero-di',
|
|
||||||
template: `<h1>Hero: {{name}}</h1>`
|
|
||||||
})
|
|
||||||
];
|
|
||||||
|
|
||||||
HeroComponent.parameters = [
|
|
||||||
[DataService]
|
|
||||||
];
|
|
||||||
// #enddocregion
|
|
|
@ -1,50 +0,0 @@
|
||||||
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;}']
|
|
||||||
})
|
|
||||||
];
|
|
||||||
// #enddocregion metadata
|
|
||||||
// #enddocregion
|
|
|
@ -1,31 +0,0 @@
|
||||||
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>
|
|
||||||
`
|
|
||||||
})
|
|
||||||
];
|
|
|
@ -1,15 +0,0 @@
|
||||||
// #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>`
|
|
||||||
})
|
|
||||||
];
|
|
|
@ -1,97 +0,0 @@
|
||||||
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
|
|
|
@ -1,28 +0,0 @@
|
||||||
import { Attribute, Component, Inject, Optional } from '@angular/core';
|
|
||||||
|
|
||||||
// #docregion
|
|
||||||
export class HeroTitleComponent {
|
|
||||||
constructor(titlePrefix, title) {
|
|
||||||
this.titlePrefix = titlePrefix;
|
|
||||||
this.title = title;
|
|
||||||
this.msg = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
ok() {
|
|
||||||
this.msg = 'OK!';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// #docregion templateUrl
|
|
||||||
HeroTitleComponent.annotations = [
|
|
||||||
new Component({
|
|
||||||
selector: 'hero-title',
|
|
||||||
templateUrl: './hero-title.component.html'
|
|
||||||
})
|
|
||||||
];
|
|
||||||
// #enddocregion templateUrl
|
|
||||||
|
|
||||||
HeroTitleComponent.parameters = [
|
|
||||||
[new Optional(), new Inject('titlePrefix')],
|
|
||||||
[new Attribute('title')]
|
|
||||||
];
|
|
|
@ -1,4 +0,0 @@
|
||||||
<!-- #docregion -->
|
|
||||||
<h1>{{titlePrefix}} {{title}}</h1>
|
|
||||||
<button (click)="ok()">OK</button>
|
|
||||||
<p>{{ msg }}</p>
|
|
|
@ -1,21 +0,0 @@
|
||||||
// #docplaster
|
|
||||||
// #docregion
|
|
||||||
// #docregion metadata
|
|
||||||
import { Component } from '@angular/core';
|
|
||||||
|
|
||||||
// #docregion appexport, class
|
|
||||||
export class HeroComponent {
|
|
||||||
constructor() {
|
|
||||||
this.title = 'Hero Detail';
|
|
||||||
}
|
|
||||||
getName() {return 'Windstorm'; }
|
|
||||||
}
|
|
||||||
// #enddocregion appexport, class
|
|
||||||
|
|
||||||
HeroComponent.annotations = [
|
|
||||||
new Component({
|
|
||||||
selector: 'hero-view',
|
|
||||||
template: '<h1>{{title}}: {{getName()}}</h1>'
|
|
||||||
})
|
|
||||||
];
|
|
||||||
// #enddocregion metadata
|
|
|
@ -1,26 +0,0 @@
|
||||||
<!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/systemjs/dist/system.src.js"></script>
|
|
||||||
|
|
||||||
<script src="systemjs.config.js"></script>
|
|
||||||
<script>
|
|
||||||
System.import('main.js').catch(function(err){ console.error(err); });
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<my-app>Loading...</my-app>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
|
@ -1,4 +0,0 @@
|
||||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
|
||||||
import { AppModule } from './app/app.module';
|
|
||||||
|
|
||||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
|
|
@ -1,3 +0,0 @@
|
||||||
{
|
|
||||||
"build": "build:babel"
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"description": "TypeScript to JavaScript",
|
|
||||||
"basePath": "src/",
|
|
||||||
"files":[
|
|
||||||
"!**/karma*.*"
|
|
||||||
],
|
|
||||||
"tags":["cookbook"]
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
<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>
|
|
|
@ -1,20 +0,0 @@
|
||||||
(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 || {});
|
|
|
@ -1,46 +0,0 @@
|
||||||
(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
|
|
||||||
})
|
|
|
@ -1,6 +0,0 @@
|
||||||
<button (click)="onOkClick()">
|
|
||||||
{{okMsg}}
|
|
||||||
</button>
|
|
||||||
<button (click)="onNotOkClick()">
|
|
||||||
{{notOkMsg}}
|
|
||||||
</button>
|
|
|
@ -1,75 +0,0 @@
|
||||||
(function(app) {
|
|
||||||
|
|
||||||
// #docregion
|
|
||||||
app.ConfirmComponent = ConfirmComponent;
|
|
||||||
|
|
||||||
ConfirmComponent.annotations = [
|
|
||||||
new ng.core.Component({
|
|
||||||
selector: 'app-confirm',
|
|
||||||
templateUrl: 'app/confirm.component.html',
|
|
||||||
inputs: [
|
|
||||||
'okMsg',
|
|
||||||
'notOkMsg: cancelMsg'
|
|
||||||
],
|
|
||||||
outputs: [
|
|
||||||
'ok',
|
|
||||||
'notOk: cancel'
|
|
||||||
]
|
|
||||||
})
|
|
||||||
];
|
|
||||||
|
|
||||||
function ConfirmComponent() {
|
|
||||||
this.ok = new ng.core.EventEmitter();
|
|
||||||
this.notOk = new ng.core.EventEmitter();
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfirmComponent.prototype.onOkClick = function() {
|
|
||||||
this.ok.emit(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfirmComponent.prototype.onNotOkClick = function() {
|
|
||||||
this.notOk.emit(true);
|
|
||||||
}
|
|
||||||
// #enddocregion
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
|
||||||
|
|
||||||
/////// DSL version ////////
|
|
||||||
|
|
||||||
(function(app) {
|
|
||||||
|
|
||||||
var old = app.ConfirmComponent;
|
|
||||||
|
|
||||||
// #docregion dsl
|
|
||||||
app.ConfirmComponent = ng.core.Component({
|
|
||||||
selector: 'app-confirm-dsl',
|
|
||||||
templateUrl: 'app/confirm.component.html',
|
|
||||||
inputs: [
|
|
||||||
'okMsg',
|
|
||||||
'notOkMsg: cancelMsg'
|
|
||||||
],
|
|
||||||
outputs: [
|
|
||||||
'ok',
|
|
||||||
'notOk: cancel'
|
|
||||||
]
|
|
||||||
})
|
|
||||||
.Class({
|
|
||||||
constructor: function ConfirmComponent() {
|
|
||||||
this.ok = new ng.core.EventEmitter();
|
|
||||||
this.notOk = new ng.core.EventEmitter();
|
|
||||||
},
|
|
||||||
|
|
||||||
onOkClick: function() {
|
|
||||||
this.ok.emit(true);
|
|
||||||
},
|
|
||||||
|
|
||||||
onNotOkClick: function() {
|
|
||||||
this.notOk.emit(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// #enddocregion dsl
|
|
||||||
|
|
||||||
app.ConfirmDslComponent = app.ConfirmComponent;
|
|
||||||
app.ConfirmComponent = old;
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
|
|
@ -1,10 +0,0 @@
|
||||||
(function(app) {
|
|
||||||
|
|
||||||
app.DataService = DataService;
|
|
||||||
function DataService() { }
|
|
||||||
|
|
||||||
DataService.prototype.getHeroName = function() {
|
|
||||||
return 'Windstorm';
|
|
||||||
};
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
|
|
@ -1,36 +0,0 @@
|
||||||
(function(app) {
|
|
||||||
|
|
||||||
var old = app.HeroComponent;
|
|
||||||
|
|
||||||
app.HeroComponent = HeroComponent;
|
|
||||||
|
|
||||||
HeroComponent.annotations = [
|
|
||||||
new ng.core.Component({
|
|
||||||
selector: 'hero-di-inject-additional',
|
|
||||||
template: '<hero-title title="Tour of Heroes"></hero-title>'
|
|
||||||
})
|
|
||||||
];
|
|
||||||
|
|
||||||
function HeroComponent() {}
|
|
||||||
|
|
||||||
app.HeroDIInjectAdditionalComponent = app.HeroComponent;
|
|
||||||
app.HeroComponent = old;
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
|
||||||
|
|
||||||
////// DSL Version /////////
|
|
||||||
(function(app) {
|
|
||||||
|
|
||||||
var old = app.HeroComponent;
|
|
||||||
|
|
||||||
app.HeroComponent = ng.core.Component({
|
|
||||||
selector: 'hero-di-inject-additional-dsl',
|
|
||||||
template: '<hero-title-dsl title="Tour of Heroes"></hero-title-dsl>'
|
|
||||||
}).Class({
|
|
||||||
constructor: function HeroComponent() { }
|
|
||||||
});
|
|
||||||
|
|
||||||
app.HeroDIInjectAdditionalDslComponent = app.HeroComponent;
|
|
||||||
app.HeroComponent = old;
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
|
|
@ -1,51 +0,0 @@
|
||||||
(function(app) {
|
|
||||||
|
|
||||||
var old = app.HeroComponent;
|
|
||||||
|
|
||||||
// #docregion
|
|
||||||
app.HeroComponent = HeroComponent;
|
|
||||||
|
|
||||||
HeroComponent.annotations = [
|
|
||||||
new ng.core.Component({
|
|
||||||
selector: 'hero-di-inject',
|
|
||||||
template: '<h1>Hero: {{name}}</h1>'
|
|
||||||
})
|
|
||||||
];
|
|
||||||
|
|
||||||
HeroComponent.parameters = [ 'heroName' ];
|
|
||||||
|
|
||||||
function HeroComponent(name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
// #enddocregion
|
|
||||||
|
|
||||||
app.HeroDIInjectComponent = app.HeroComponent;
|
|
||||||
app.HeroComponent = old;
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
|
||||||
|
|
||||||
/////// DSL version ////////
|
|
||||||
|
|
||||||
(function(app) {
|
|
||||||
|
|
||||||
var old = app.HeroComponent;
|
|
||||||
|
|
||||||
// #docregion dsl
|
|
||||||
app.HeroComponent = ng.core.Component({
|
|
||||||
selector: 'hero-di-inject-dsl',
|
|
||||||
template: '<h1>Hero: {{name}}</h1>'
|
|
||||||
})
|
|
||||||
.Class({
|
|
||||||
constructor: [
|
|
||||||
new ng.core.Inject('heroName'),
|
|
||||||
function HeroComponent(name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
// #enddocregion dsl
|
|
||||||
|
|
||||||
app.HeroDIInjectDslComponent = app.HeroComponent;
|
|
||||||
app.HeroComponent = old;
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
|
|
@ -1,51 +0,0 @@
|
||||||
(function(app) {
|
|
||||||
|
|
||||||
var old = app.HeroComponent;
|
|
||||||
|
|
||||||
// #docregion
|
|
||||||
app.HeroComponent = HeroComponent;
|
|
||||||
|
|
||||||
HeroComponent.annotations = [
|
|
||||||
new ng.core.Component({
|
|
||||||
selector: 'hero-di',
|
|
||||||
template: '<h1>Hero: {{name}}</h1>'
|
|
||||||
})
|
|
||||||
];
|
|
||||||
|
|
||||||
HeroComponent.parameters = [ app.DataService ];
|
|
||||||
|
|
||||||
function HeroComponent(dataService) {
|
|
||||||
this.name = dataService.getHeroName();
|
|
||||||
}
|
|
||||||
// #enddocregion
|
|
||||||
|
|
||||||
app.HeroDIComponent = app.HeroComponent;
|
|
||||||
app.HeroComponent = old;
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
|
||||||
|
|
||||||
////// DSL Version /////
|
|
||||||
|
|
||||||
(function(app) {
|
|
||||||
|
|
||||||
var old = app.HeroComponent;
|
|
||||||
|
|
||||||
// #docregion dsl
|
|
||||||
app.HeroComponent = ng.core.Component({
|
|
||||||
selector: 'hero-di-dsl',
|
|
||||||
template: '<h1>Hero: {{name}}</h1>'
|
|
||||||
})
|
|
||||||
.Class({
|
|
||||||
constructor: [
|
|
||||||
app.DataService,
|
|
||||||
function HeroComponent(service) {
|
|
||||||
this.name = service.getHeroName();
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
// #enddocregion dsl
|
|
||||||
|
|
||||||
app.HeroDIDslComponent = app.HeroComponent;
|
|
||||||
app.HeroComponent = old;
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
|
|
@ -1,107 +0,0 @@
|
||||||
(function(app) {
|
|
||||||
|
|
||||||
var old = app.HeroComponent
|
|
||||||
|
|
||||||
// #docregion
|
|
||||||
app.HeroComponent = HeroComponent;
|
|
||||||
|
|
||||||
HeroComponent.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 HeroComponent() {
|
|
||||||
this.clicks = 0;
|
|
||||||
this.headingClass = true;
|
|
||||||
this.title = 'Hero Host Tooltip content';
|
|
||||||
}
|
|
||||||
|
|
||||||
HeroComponent.prototype.clicked = function() {
|
|
||||||
this.clicks += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
HeroComponent.prototype.enter = function(event) {
|
|
||||||
this.active = true;
|
|
||||||
this.headingClass = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
HeroComponent.prototype.leave = function(event) {
|
|
||||||
this.active = false;
|
|
||||||
this.headingClass = true;
|
|
||||||
}
|
|
||||||
// #enddocregion
|
|
||||||
|
|
||||||
app.HeroHostComponent = app.HeroComponent;
|
|
||||||
app.HeroComponent = old;
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
|
||||||
|
|
||||||
//// DSL Version ////
|
|
||||||
|
|
||||||
(function(app) {
|
|
||||||
|
|
||||||
var old = app.HeroComponent;
|
|
||||||
|
|
||||||
// #docregion dsl
|
|
||||||
app.HeroComponent = ng.core.Component({
|
|
||||||
selector: 'hero-host-dsl',
|
|
||||||
template: `
|
|
||||||
<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 HeroComponent() {
|
|
||||||
this.clicks = 0;
|
|
||||||
this.headingClass = true;
|
|
||||||
this.title = 'Hero Host Tooltip DSL content';
|
|
||||||
},
|
|
||||||
|
|
||||||
clicked() {
|
|
||||||
this.clicks += 1;
|
|
||||||
},
|
|
||||||
|
|
||||||
enter(event) {
|
|
||||||
this.active = true;
|
|
||||||
this.headingClass = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
leave(event) {
|
|
||||||
this.active = false;
|
|
||||||
this.headingClass = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// #enddocregion dsl
|
|
||||||
|
|
||||||
app.HeroHostDslComponent = app.HeroComponent;
|
|
||||||
app.HeroComponent = old;
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
|
|
@ -1,7 +0,0 @@
|
||||||
<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>
|
|
|
@ -1,7 +0,0 @@
|
||||||
<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,52 +0,0 @@
|
||||||
(function(app) {
|
|
||||||
|
|
||||||
var old = app.HeroComponent
|
|
||||||
|
|
||||||
app.HeroComponent = HeroComponent;
|
|
||||||
|
|
||||||
HeroComponent.annotations = [
|
|
||||||
new ng.core.Component({
|
|
||||||
selector: 'hero-io',
|
|
||||||
templateUrl: 'app/hero-io.component.html'
|
|
||||||
})
|
|
||||||
];
|
|
||||||
|
|
||||||
function HeroComponent() { }
|
|
||||||
|
|
||||||
HeroComponent.prototype.onOk = function() {
|
|
||||||
this.okClicked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
HeroComponent.prototype.onCancel = function() {
|
|
||||||
this.cancelClicked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
app.HeroIOComponent = app.HeroComponent;
|
|
||||||
app.HeroComponent = old;
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
|
||||||
|
|
||||||
///// DSL Version ////
|
|
||||||
|
|
||||||
(function(app) {
|
|
||||||
|
|
||||||
var old = app.HeroComponent
|
|
||||||
|
|
||||||
app.HeroComponent = ng.core.Component({
|
|
||||||
selector: 'hero-io-dsl',
|
|
||||||
templateUrl: 'app/hero-io-dsl.component.html'
|
|
||||||
})
|
|
||||||
.Class({
|
|
||||||
constructor: function HeroComponent() { },
|
|
||||||
onOk: function() {
|
|
||||||
this.okClicked = true;
|
|
||||||
},
|
|
||||||
onCancel: function() {
|
|
||||||
this.cancelClicked = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
app.HeroIODslComponent = app.HeroComponent;
|
|
||||||
app.HeroComponent = old;
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
|
|
@ -1,52 +0,0 @@
|
||||||
// #docplaster
|
|
||||||
(function(app) {
|
|
||||||
|
|
||||||
var old = app.HeroComponent;
|
|
||||||
|
|
||||||
// #docregion
|
|
||||||
app.HeroComponent = HeroComponent;
|
|
||||||
|
|
||||||
HeroComponent.annotations = [
|
|
||||||
new ng.core.Component({
|
|
||||||
selector: 'hero-lifecycle',
|
|
||||||
template: '<h1>Hero: {{name}}</h1>'
|
|
||||||
})
|
|
||||||
];
|
|
||||||
|
|
||||||
function HeroComponent() { }
|
|
||||||
|
|
||||||
HeroComponent.prototype.ngOnInit = function() {
|
|
||||||
// todo: fetch from server async
|
|
||||||
setTimeout(() => this.name = 'Windstorm', 0);
|
|
||||||
};
|
|
||||||
// #enddocregion
|
|
||||||
|
|
||||||
app.HeroLifecycleComponent = app.HeroComponent;
|
|
||||||
app.HeroComponent = old;
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
|
||||||
|
|
||||||
/////// DSL version ////
|
|
||||||
|
|
||||||
(function(app) {
|
|
||||||
|
|
||||||
var old = app.HeroComponent;
|
|
||||||
|
|
||||||
// #docregion dsl
|
|
||||||
app.HeroComponent = ng.core.Component({
|
|
||||||
selector: 'hero-lifecycle-dsl',
|
|
||||||
template: '<h1>Hero: {{name}}</h1>'
|
|
||||||
})
|
|
||||||
.Class({
|
|
||||||
constructor: function HeroComponent() { },
|
|
||||||
ngOnInit: function() {
|
|
||||||
// todo: fetch from server async
|
|
||||||
setTimeout(() => this.name = 'Windstorm', 0);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// #enddocregion dsl
|
|
||||||
|
|
||||||
app.HeroLifecycleDslComponent = app.HeroComponent;
|
|
||||||
app.HeroComponent = old;
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
|
|
@ -1,92 +0,0 @@
|
||||||
(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 || {});
|
|
|
@ -1,4 +0,0 @@
|
||||||
<!-- #docregion -->
|
|
||||||
<h1>{{titlePrefix}} {{title}}</h1>
|
|
||||||
<button (click)="ok()">OK</button>
|
|
||||||
<p>{{ msg }}</p>
|
|
|
@ -1,64 +0,0 @@
|
||||||
(function(app) {
|
|
||||||
|
|
||||||
// #docregion
|
|
||||||
app.HeroTitleComponent = HeroTitleComponent;
|
|
||||||
|
|
||||||
// #docregion templateUrl
|
|
||||||
HeroTitleComponent.annotations = [
|
|
||||||
new ng.core.Component({
|
|
||||||
selector: 'hero-title',
|
|
||||||
templateUrl: 'app/hero-title.component.html'
|
|
||||||
})
|
|
||||||
];
|
|
||||||
// #enddocregion templateUrl
|
|
||||||
|
|
||||||
function HeroTitleComponent(titlePrefix, title) {
|
|
||||||
this.titlePrefix = titlePrefix;
|
|
||||||
this.title = title;
|
|
||||||
this.msg = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
HeroTitleComponent.prototype.ok = function() {
|
|
||||||
this.msg = 'OK!';
|
|
||||||
}
|
|
||||||
|
|
||||||
HeroTitleComponent.parameters = [
|
|
||||||
[new ng.core.Optional(), new ng.core.Inject('titlePrefix')],
|
|
||||||
[new ng.core.Attribute('title')]
|
|
||||||
];
|
|
||||||
// #enddocregion
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
|
||||||
|
|
||||||
////////// DSL version ////////////
|
|
||||||
|
|
||||||
(function(app) {
|
|
||||||
|
|
||||||
var old = app.HeroTitleComponent;
|
|
||||||
|
|
||||||
// #docregion dsl
|
|
||||||
app.HeroTitleComponent = ng.core.Component({
|
|
||||||
selector: 'hero-title-dsl',
|
|
||||||
templateUrl: 'app/hero-title.component.html'
|
|
||||||
})
|
|
||||||
.Class({
|
|
||||||
constructor: [
|
|
||||||
[ new ng.core.Optional(), new ng.core.Inject('titlePrefix') ],
|
|
||||||
new ng.core.Attribute('title'),
|
|
||||||
function HeroTitleComponent(titlePrefix, title) {
|
|
||||||
this.titlePrefix = titlePrefix;
|
|
||||||
this.title = title;
|
|
||||||
this.msg = '';
|
|
||||||
}
|
|
||||||
],
|
|
||||||
|
|
||||||
ok: function() {
|
|
||||||
this.msg = 'OK!';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// #enddocregion dsl
|
|
||||||
|
|
||||||
app.HeroTitleDslComponent = app.HeroTitleComponent;
|
|
||||||
app.HeroTitleComponent = old;
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
|
|
@ -1,53 +0,0 @@
|
||||||
// #docplaster
|
|
||||||
(function(app) {
|
|
||||||
|
|
||||||
// #docregion
|
|
||||||
// #docregion appexport
|
|
||||||
// #docregion metadata
|
|
||||||
app.HeroComponent = HeroComponent; // "export"
|
|
||||||
|
|
||||||
HeroComponent.annotations = [
|
|
||||||
new ng.core.Component({
|
|
||||||
selector: 'hero-view',
|
|
||||||
template: '<h1>{{title}}: {{getName()}}</h1>'
|
|
||||||
})
|
|
||||||
];
|
|
||||||
|
|
||||||
// #docregion constructorproto
|
|
||||||
function HeroComponent() {
|
|
||||||
this.title = "Hero Detail";
|
|
||||||
}
|
|
||||||
|
|
||||||
HeroComponent.prototype.getName = function() { return 'Windstorm'; };
|
|
||||||
// #enddocregion constructorproto
|
|
||||||
|
|
||||||
// #enddocregion metadata
|
|
||||||
// #enddocregion appexport
|
|
||||||
// #enddocregion
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
|
||||||
|
|
||||||
//////////// DSL version ///////////
|
|
||||||
|
|
||||||
(function(app) {
|
|
||||||
|
|
||||||
var old = app.HeroComponent;
|
|
||||||
|
|
||||||
// #docregion dsl
|
|
||||||
app.HeroComponent = ng.core.Component({
|
|
||||||
selector: 'hero-view-dsl',
|
|
||||||
template: '<h1>{{title}}: {{getName()}}</h1>',
|
|
||||||
})
|
|
||||||
.Class({
|
|
||||||
constructor: function HeroComponent() {
|
|
||||||
this.title = "Hero Detail";
|
|
||||||
},
|
|
||||||
|
|
||||||
getName: function() { return 'Windstorm'; }
|
|
||||||
});
|
|
||||||
// #enddocregion dsl
|
|
||||||
|
|
||||||
app.HeroDslComponent = app.HeroComponent;
|
|
||||||
app.HeroComponent = old;
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
|
|
@ -1,43 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<base href="/">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<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/zone.js/dist/zone.js"></script>
|
|
||||||
|
|
||||||
<!-- Angular and RxJS umd scripts -->
|
|
||||||
<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/common/bundles/common.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-dynamic/bundles/platform-browser-dynamic.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/hero.component.js"></script>
|
|
||||||
<script src="app/hero-io.component.js"></script>
|
|
||||||
<script src="app/hero-di.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-host.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="main.js"></script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<my-app>Loading...</my-app>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
|
@ -1,9 +0,0 @@
|
||||||
(function(app) {
|
|
||||||
|
|
||||||
var platformBrowserDynamic = ng.platformBrowserDynamic.platformBrowserDynamic;
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
platformBrowserDynamic().bootstrapModule(app.AppModule);
|
|
||||||
});
|
|
||||||
|
|
||||||
})(window.app = window.app || {});
|
|
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"description": "TypeScript to JavaScript",
|
|
||||||
"basePath": "src/",
|
|
||||||
"files":[
|
|
||||||
"!**/*.d.ts",
|
|
||||||
"!**/*.js"
|
|
||||||
],
|
|
||||||
"tags":["cookbook"]
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
<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>
|
|
|
@ -1,14 +0,0 @@
|
||||||
import { Component } from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'my-app',
|
|
||||||
templateUrl: './app.component.html',
|
|
||||||
styles: [
|
|
||||||
// See hero-di-inject-additional.component
|
|
||||||
'hero-host, hero-host-meta { border: 1px dashed black; display: block; padding: 4px;}',
|
|
||||||
'.heading {font-style: italic}'
|
|
||||||
]
|
|
||||||
})
|
|
||||||
export class AppComponent {
|
|
||||||
title = 'TypeScript';
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
/* 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
|
|
|
@ -1,6 +0,0 @@
|
||||||
<button (click)="onOkClick()">
|
|
||||||
{{okMsg}}
|
|
||||||
</button>
|
|
||||||
<button (click)="onNotOkClick()">
|
|
||||||
{{notOkMsg}}
|
|
||||||
</button>
|
|
|
@ -1,21 +0,0 @@
|
||||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
|
||||||
|
|
||||||
// #docregion
|
|
||||||
@Component({
|
|
||||||
selector: 'app-confirm',
|
|
||||||
templateUrl: './confirm.component.html'
|
|
||||||
})
|
|
||||||
export class ConfirmComponent {
|
|
||||||
@Input() okMsg = '';
|
|
||||||
@Input('cancelMsg') notOkMsg = '';
|
|
||||||
@Output() ok = new EventEmitter();
|
|
||||||
@Output('cancel') notOk = new EventEmitter();
|
|
||||||
|
|
||||||
onOkClick() {
|
|
||||||
this.ok.emit(true);
|
|
||||||
}
|
|
||||||
onNotOkClick() {
|
|
||||||
this.notOk.emit(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// #enddocregion
|
|
|
@ -1,10 +0,0 @@
|
||||||
import { Injectable } from '@angular/core';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class DataService {
|
|
||||||
constructor() { }
|
|
||||||
|
|
||||||
getHeroName() {
|
|
||||||
return 'Windstorm';
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
import { Component } from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'hero-di-inject-additional',
|
|
||||||
template: `<hero-title title="Tour of Heroes"></hero-title>`
|
|
||||||
})
|
|
||||||
export class HeroComponent { }
|
|
|
@ -1,11 +0,0 @@
|
||||||
import { Component, Inject } from '@angular/core';
|
|
||||||
|
|
||||||
// #docregion
|
|
||||||
@Component({
|
|
||||||
selector: 'hero-di-inject',
|
|
||||||
template: `<h1>Hero: {{name}}</h1>`
|
|
||||||
})
|
|
||||||
export class HeroComponent {
|
|
||||||
constructor(@Inject('heroName') private name: string) { }
|
|
||||||
}
|
|
||||||
// #enddocregion
|
|
|
@ -1,15 +0,0 @@
|
||||||
// #docregion
|
|
||||||
import { Component } from '@angular/core';
|
|
||||||
import { DataService } from './data.service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'hero-di',
|
|
||||||
template: `<h1>Hero: {{name}}</h1>`
|
|
||||||
})
|
|
||||||
export class HeroComponent {
|
|
||||||
name = '';
|
|
||||||
constructor(dataService: DataService) {
|
|
||||||
this.name = dataService.getHeroName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// #enddocregion
|
|
|
@ -1,44 +0,0 @@
|
||||||
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
|
|
|
@ -1,39 +0,0 @@
|
||||||
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,26 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
// #docregion
|
|
||||||
import { Component, OnInit } from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'hero-lifecycle',
|
|
||||||
template: `<h1>Hero: {{name}}</h1>`
|
|
||||||
})
|
|
||||||
export class HeroComponent implements OnInit {
|
|
||||||
name: string;
|
|
||||||
ngOnInit() {
|
|
||||||
// todo: fetch from server async
|
|
||||||
setTimeout(() => this.name = 'Windstorm', 0);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,83 +0,0 @@
|
||||||
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
|
|
|
@ -1,4 +0,0 @@
|
||||||
<!-- #docregion -->
|
|
||||||
<h1>{{titlePrefix}} {{title}}</h1>
|
|
||||||
<button (click)="ok()">OK</button>
|
|
||||||
<p>{{ msg }}</p>
|
|
|
@ -1,21 +0,0 @@
|
||||||
import { Attribute, Component, Inject, Optional } from '@angular/core';
|
|
||||||
|
|
||||||
// #docregion
|
|
||||||
// #docregion templateUrl
|
|
||||||
@Component({
|
|
||||||
selector: 'hero-title',
|
|
||||||
templateUrl: './hero-title.component.html'
|
|
||||||
})
|
|
||||||
// #enddocregion templateUrl
|
|
||||||
export class HeroTitleComponent {
|
|
||||||
msg = '';
|
|
||||||
constructor(
|
|
||||||
@Inject('titlePrefix') @Optional() private titlePrefix: string,
|
|
||||||
@Attribute('title') private title: string
|
|
||||||
) { }
|
|
||||||
|
|
||||||
ok() {
|
|
||||||
this.msg = 'OK!';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// #enddocregion
|
|
|
@ -1,15 +0,0 @@
|
||||||
// #docregion
|
|
||||||
// #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
|
|
|
@ -1,26 +0,0 @@
|
||||||
<!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>
|
|
||||||
|
|
||||||
<!-- Polyfills -->
|
|
||||||
<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/systemjs/dist/system.src.js"></script>
|
|
||||||
|
|
||||||
<script src="systemjs.config.js"></script>
|
|
||||||
<script>
|
|
||||||
System.import('main.js').catch(function(err){ console.error(err); });
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<my-app>Loading...</my-app>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
|
@ -1,4 +0,0 @@
|
||||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
|
||||||
import { AppModule } from './app/app.module';
|
|
||||||
|
|
||||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
|
|
@ -120,8 +120,8 @@ The documentation for the version prior to v.2.2.0 has been removed.
|
||||||
|
|
||||||
## ES6 described in "TypeScript to JavaScript" (2016-11-14)
|
## ES6 described in "TypeScript to JavaScript" (2016-11-14)
|
||||||
|
|
||||||
The updated [TypeScript to JavaScript](guide/ts-to-js) guide
|
The updated TypeScript to JavaScript guide (removed August 2017, PR #18694)
|
||||||
now explains how to write apps in ES6/7
|
explains how to write apps in ES6/7
|
||||||
by translating the common idioms in the TypeScript documentation examples
|
by translating the common idioms in the TypeScript documentation examples
|
||||||
(and elsewhere on the web) to ES6/7 and ES5.
|
(and elsewhere on the web) to ES6/7 and ES5.
|
||||||
|
|
||||||
|
|
|
@ -1,621 +0,0 @@
|
||||||
# TypeScript to JavaScript
|
|
||||||
|
|
||||||
## Introduction
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
Run and compare the live <live-example name="ts-to-js/ts">TypeScript</live-example> and <live-example name="ts-to-js/js">JavaScript</live-example>
|
|
||||||
code shown in this cookbook.
|
|
||||||
|
|
||||||
|
|
||||||
## _TypeScript_ to _ES6_ to _ES5_
|
|
||||||
|
|
||||||
_TypeScript_
|
|
||||||
<a href="https://www.typescriptlang.org" 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 as follows:
|
|
||||||
|
|
||||||
* _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}
|
|
||||||
|
|
||||||
## 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](guide/glossary#scoped-package)
|
|
||||||
through the global `ng` object.
|
|
||||||
Anything you can import from `@angular` is a nested member of this `ng` object:
|
|
||||||
|
|
||||||
<code-tabs>
|
|
||||||
<code-pane title="TypeScript" path="ts-to-js/ts/src/app/app.module.ts" region="ng2import">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 + Decorators" path="ts-to-js/js-es6-decorators/src/app/app.module.es6" region="ng2import">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 JavaScript" path="ts-to-js/js-es6/src/app/app.module.es6" region="ng2import">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES5 JavaScript" path="ts-to-js/js/src/app/app.module.js" region="ng2import">
|
|
||||||
</code-pane>
|
|
||||||
</code-tabs>
|
|
||||||
|
|
||||||
### 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`.
|
|
||||||
|
|
||||||
<div class="alert is-important">
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
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, for example, `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.
|
|
||||||
|
|
||||||
<code-tabs>
|
|
||||||
<code-pane title="TypeScript" path="ts-to-js/ts/src/app/hero.component.ts" region="appexport">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 + Decorators" path="ts-to-js/js-es6-decorators/src/app/hero.component.es6" region="appexport">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 JavaScript" path="ts-to-js/js-es6/src/app/hero.component.es6" region="appexport">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES5 JavaScript" path="ts-to-js/js/src/app/hero.component.js" region="appexport">
|
|
||||||
</code-pane>
|
|
||||||
</code-tabs>
|
|
||||||
|
|
||||||
### 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.
|
|
||||||
|
|
||||||
<code-tabs>
|
|
||||||
<code-pane title="TypeScript" path="ts-to-js/ts/src/app/app.module.ts" region="appimport">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 + Decorators" path="ts-to-js/js-es6-decorators/src/app/app.module.es6" region="appimport">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 JavaScript" path="ts-to-js/js-es6/src/app/app.module.es6" region="appimport">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES5 JavaScript" path="ts-to-js/js/src/app/app.module.js" region="appimport">
|
|
||||||
</code-pane>
|
|
||||||
</code-tabs>
|
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{@a class-metadata}
|
|
||||||
|
|
||||||
## 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, for example, `: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.
|
|
||||||
|
|
||||||
<code-tabs>
|
|
||||||
<code-pane title="TypeScript" path="ts-to-js/ts/src/app/hero.component.ts" region="class">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 + Decorators" path="ts-to-js/js-es6-decorators/src/app/hero.component.es6" region="class">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 JavaScript" path="ts-to-js/js-es6/src/app/hero.component.es6" region="class">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES5 JavaScript" path="ts-to-js/js/src/app/hero.component.js" region="constructorproto">
|
|
||||||
</code-pane>
|
|
||||||
</code-tabs>
|
|
||||||
|
|
||||||
### 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/Component) 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:
|
|
||||||
|
|
||||||
<code-tabs>
|
|
||||||
<code-pane title="TypeScript" path="ts-to-js/ts/src/app/hero.component.ts" region="metadata">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 + Decorators" path="ts-to-js/js-es6-decorators/src/app/hero.component.es6" region="metadata">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 JavaScript" path="ts-to-js/js-es6/src/app/hero.component.es6" region="metadata">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES5 JavaScript" path="ts-to-js/js/src/app/hero.component.js" region="metadata">
|
|
||||||
</code-pane>
|
|
||||||
</code-tabs>
|
|
||||||
|
|
||||||
## External template file
|
|
||||||
|
|
||||||
A large component template is often kept in a separate template file.
|
|
||||||
|
|
||||||
<code-example path="ts-to-js/ts/src/app/hero-title.component.html" title="src/app/hero-title.component.html" linenums="false">
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
The component, `HeroTitleComponent` in this case, then references the template file in its metadata `templateUrl` property:
|
|
||||||
|
|
||||||
<code-tabs>
|
|
||||||
<code-pane title="TypeScript" path="ts-to-js/ts/src/app/hero-title.component.ts" region="templateUrl">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 + Decorators" path="ts-to-js/js-es6-decorators/src/app/hero-title.component.es6" region="templateUrl">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 JavaScript" path="ts-to-js/js-es6/src/app/hero-title.component.es6" region="templateUrl">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES5 JavaScript" path="ts-to-js/js/src/app/hero-title.component.js" region="templateUrl">
|
|
||||||
</code-pane>
|
|
||||||
</code-tabs>
|
|
||||||
|
|
||||||
Note that both the _TypeScript_ and _ES6_ `templateUrl` properties identify the location of the template file _relative to the component module_.
|
|
||||||
|
|
||||||
{@a dsl}
|
|
||||||
|
|
||||||
## _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, for example, `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:
|
|
||||||
|
|
||||||
<code-tabs>
|
|
||||||
<code-pane title="ES5 JavaScript with DSL" path="ts-to-js/js/src/app/hero.component.js" region="dsl">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES5 JavaScript" path="ts-to-js/js/src/app/hero.component.js">
|
|
||||||
</code-pane>
|
|
||||||
</code-tabs>
|
|
||||||
|
|
||||||
{@a name-constructor}
|
|
||||||
|
|
||||||
<div class="callout is-helpful">
|
|
||||||
|
|
||||||
A **named** constructor displays clearly in the console log
|
|
||||||
if the component throws a runtime error.
|
|
||||||
An **unnamed** constructor displays as an anonymous function, for example, `class0`,
|
|
||||||
which is impossible to find in the source code.
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{@a getters-setters}
|
|
||||||
|
|
||||||
### 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:
|
|
||||||
|
|
||||||
<code-example path="ts-to-js/ts/src/app/hero-queries.component.ts" region="defined-property" title="ts/src/app/hero-queries.component.ts" linenums="false">
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
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"
|
|
||||||
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:
|
|
||||||
|
|
||||||
<code-example path="ts-to-js/js/src/app/hero-queries.component.js" region="defined-property" title="js/src/app/hero-queries.component.ts" linenums="false">
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
{@a dsl-other}
|
|
||||||
|
|
||||||
### 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({
|
|
||||||
...
|
|
||||||
});
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
and a pipe with `ng.core.Pipe`:
|
|
||||||
|
|
||||||
<code-example>
|
|
||||||
app.MyPipe = ng.core.Pipe({
|
|
||||||
name: 'myPipe'
|
|
||||||
}).Class({
|
|
||||||
...
|
|
||||||
});
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
{@a interfaces}
|
|
||||||
|
|
||||||
## Interfaces
|
|
||||||
|
|
||||||
A _TypeScript_ interface helps ensure that a class implements the interface's members correctly.
|
|
||||||
Always try to use 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.
|
|
||||||
|
|
||||||
<code-tabs>
|
|
||||||
<code-pane title="TypeScript" path="ts-to-js/ts/src/app/hero-lifecycle.component.ts">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 + Decorators" path="ts-to-js/js-es6-decorators/src/app/hero-lifecycle.component.es6">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 JavaScript" path="ts-to-js/js-es6/src/app/hero-lifecycle.component.es6">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES5 JavaScript" path="ts-to-js/js/src/app/hero-lifecycle.component.js">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES5 JavaScript with DSL" path="ts-to-js/js/src/app/hero-lifecycle.component.js" region="dsl">
|
|
||||||
</code-pane>
|
|
||||||
</code-tabs>
|
|
||||||
|
|
||||||
{@a io-decorators}
|
|
||||||
|
|
||||||
## 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#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_.
|
|
||||||
|
|
||||||
<code-tabs>
|
|
||||||
<code-pane title="TypeScript" path="ts-to-js/ts/src/app/confirm.component.ts">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 + Decorators" path="ts-to-js/js-es6-decorators/src/app/confirm.component.es6">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 JavaScript" path="ts-to-js/js-es6/src/app/confirm.component.es6">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES5 JavaScript" path="ts-to-js/js/src/app/confirm.component.js">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES5 JavaScript with DSL" path="ts-to-js/js/src/app/confirm.component.js" region="dsl">
|
|
||||||
</code-pane>
|
|
||||||
</code-tabs>
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
{@a dependency-injection}
|
|
||||||
|
|
||||||
## Dependency injection
|
|
||||||
Angular relies heavily on [Dependency Injection](guide/dependency-injection) 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.
|
|
||||||
|
|
||||||
{@a injection-class-type}
|
|
||||||
|
|
||||||
### 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 AngularJS developers.
|
|
||||||
|
|
||||||
<code-tabs>
|
|
||||||
<code-pane title="TypeScript" path="ts-to-js/ts/src/app/hero-di.component.ts">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 + Decorators" path="ts-to-js/js-es6-decorators/src/app/hero-di.component.es6">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 JavaScript" path="ts-to-js/js-es6/src/app/hero-di.component.es6">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES5 JavaScript" path="ts-to-js/js/src/app/hero-di.component.js">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES5 JavaScript with DSL" path="ts-to-js/js/src/app/hero-di.component.js" region="dsl">
|
|
||||||
</code-pane>
|
|
||||||
</code-tabs>
|
|
||||||
|
|
||||||
### 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 dialects add a `parameters` array to the class constructor function.
|
|
||||||
Each item contains a new instance of `Inject`:
|
|
||||||
|
|
||||||
* _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 instance of `ng.core.Inject(token)` for each parameter.
|
|
||||||
|
|
||||||
<code-tabs>
|
|
||||||
<code-pane title="TypeScript" path="ts-to-js/ts/src/app/hero-di-inject.component.ts">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 + Decorators" path="ts-to-js/js-es6-decorators/src/app/hero-di-inject.component.es6">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 JavaScript" path="ts-to-js/js-es6/src/app/hero-di-inject.component.es6">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES5 JavaScript" path="ts-to-js/js/src/app/hero-di-inject.component.js">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES5 JavaScript with DSL" path="ts-to-js/js/src/app/hero-di-inject.component.js" region="dsl">
|
|
||||||
</code-pane>
|
|
||||||
</code-tabs>
|
|
||||||
|
|
||||||
### 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/Optional) sets the parameter to `null` if the service is missing.
|
|
||||||
* [`@Attribute`](api/core/Attribute) to inject a host element attribute value.
|
|
||||||
* [`@ContentChild`](api/core/ContentChild) to inject a content child.
|
|
||||||
* [`@ViewChild`](api/core/ViewChild) to inject a view child.
|
|
||||||
* [`@Host`](api/core/Host) to inject a service in this component or its host.
|
|
||||||
* [`@SkipSelf`](api/core/SkipSelf) 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.
|
|
||||||
|
|
||||||
<code-tabs>
|
|
||||||
<code-pane title="TypeScript" path="ts-to-js/ts/src/app/hero-title.component.ts">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 + Decorators" path="ts-to-js/js-es6-decorators/src/app/hero-title.component.es6">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 JavaScript" path="ts-to-js/js-es6/src/app/hero-title.component.es6">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES5 JavaScript" path="ts-to-js/js/src/app/hero-title.component.js">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES5 JavaScript with DSL" path="ts-to-js/js/src/app/hero-title.component.js" region="dsl">
|
|
||||||
</code-pane>
|
|
||||||
</code-tabs>
|
|
||||||
|
|
||||||
<div class="l-sub-section">
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{@a host-binding}
|
|
||||||
|
|
||||||
## 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/HostBinding) decorator
|
|
||||||
binds host element properties to component data properties.
|
|
||||||
The [`@HostListener`](api/core/HostListener) 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.
|
|
||||||
|
|
||||||
<code-tabs>
|
|
||||||
<code-pane title="TypeScript" path="ts-to-js/ts/src/app/hero-host.component.ts">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 + Decorators" path="ts-to-js/js-es6-decorators/src/app/hero-host.component.es6">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 JavaScript" path="ts-to-js/js-es6/src/app/hero-host.component.es6">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES5 JavaScript" path="ts-to-js/js/src/app/hero-host.component.js">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES5 JavaScript with DSL" path="ts-to-js/js/src/app/hero-host.component.js" region="dsl">
|
|
||||||
</code-pane>
|
|
||||||
</code-tabs>
|
|
||||||
|
|
||||||
### 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` shows 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.
|
|
||||||
|
|
||||||
<code-tabs>
|
|
||||||
<code-pane title="TypeScript" path="ts-to-js/ts/src/app/hero-host-meta.component.ts">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 + Decorators" path="ts-to-js/js-es6-decorators/src/app/hero-host-meta.component.es6">
|
|
||||||
</code-pane>
|
|
||||||
</code-tabs>
|
|
||||||
|
|
||||||
{@a view-child-decorators}
|
|
||||||
|
|
||||||
### View and Child Decorators
|
|
||||||
|
|
||||||
Several _property_ decorators query a component's nested view and content components.
|
|
||||||
|
|
||||||
<div class="l-sub-section">
|
|
||||||
|
|
||||||
_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.
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
The [`@ViewChild`](api/core/ViewChild) and
|
|
||||||
[`@ViewChildren`](api/core/ViewChildren) 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`.
|
|
||||||
|
|
||||||
<code-tabs>
|
|
||||||
<code-pane title="TypeScript" path="ts-to-js/ts/src/app/hero-queries.component.ts" region="view">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 + Decorators" path="ts-to-js/js-es6-decorators/src/app/hero-queries.component.es6" region="view">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 JavaScript" path="ts-to-js/js-es6/src/app/hero-queries.component.es6" region="view">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES5 JavaScript with DSL" path="ts-to-js/js/src/app/hero-queries.component.js" region="view">
|
|
||||||
</code-pane>
|
|
||||||
</code-tabs>
|
|
||||||
|
|
||||||
The [`@ContentChild`](api/core/ContentChild) and
|
|
||||||
[`@ContentChildren`](api/core/ContentChildren) 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/ViewChild) and
|
|
||||||
[`@ViewChildren`](api/core/ViewChildren).
|
|
||||||
|
|
||||||
<code-tabs>
|
|
||||||
<code-pane title="TypeScript" path="ts-to-js/ts/src/app/hero-queries.component.ts" region="content">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 + Decorators" path="ts-to-js/js-es6-decorators/src/app/hero-queries.component.es6" region="content">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES6 JavaScript" path="ts-to-js/js-es6/src/app/hero-queries.component.es6" region="content">
|
|
||||||
</code-pane>
|
|
||||||
<code-pane title="ES5 JavaScript with DSL" path="ts-to-js/js/src/app/hero-queries.component.js" region="content">
|
|
||||||
</code-pane>
|
|
||||||
</code-tabs>
|
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
|
||||||
|
|
||||||
In _TypeScript_ and _ES6-with-decorators_ you can also use the `queries` metadata
|
|
||||||
instead of the `@ViewChild` and `@ContentChild` property decorators.
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{@a aot}
|
|
||||||
|
|
||||||
## AOT Compilation in _TypeScript_ only
|
|
||||||
|
|
||||||
Angular offers two modes of template compilation, JIT (_just-in-time_) and
|
|
||||||
[AOT (_ahead-of-time_)](guide/aot-compiler).
|
|
||||||
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.
|
|
|
@ -298,11 +298,6 @@
|
||||||
"title": "Security",
|
"title": "Security",
|
||||||
"tooltip": "Developing for content security in Angular applications."
|
"tooltip": "Developing for content security in Angular applications."
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"url": "guide/ts-to-js",
|
|
||||||
"title": "TypeScript to JavaScript",
|
|
||||||
"tooltip": "Convert Angular TypeScript examples into ES6 and ES5 JavaScript."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"title": "Setup & Deployment",
|
"title": "Setup & Deployment",
|
||||||
"tooltip": "Setup and Deployment",
|
"tooltip": "Setup and Deployment",
|
||||||
|
|
|
@ -22,8 +22,8 @@ const defaultLineNumsCount = 10; // by default, show linenums over this number
|
||||||
* [code]="variableContainingCode"
|
* [code]="variableContainingCode"
|
||||||
* [language]="ts"
|
* [language]="ts"
|
||||||
* [linenums]="true"
|
* [linenums]="true"
|
||||||
* [path]="ts-to-js/ts/src/app/app.module.ts"
|
* [path]="router/src/app/app.module.ts"
|
||||||
* [region]="ng2import">
|
* [region]="animations-module">
|
||||||
* </aio-code>
|
* </aio-code>
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue