docs(cb-ts-to-js): add cookbook about applying TypeScript examples to ES5
closes #893
This commit is contained in:
parent
1184b57740
commit
7f11a6ce05
|
@ -0,0 +1,73 @@
|
|||
describe('TypeScript to Javascript tests', function () {
|
||||
|
||||
beforeAll(function () {
|
||||
browser.get('');
|
||||
});
|
||||
|
||||
it('should display the basic component example', function () {
|
||||
testTag('hero-view', 'Hero: 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 () {
|
||||
var app = element(by.css('hero-di-inject-additional'));
|
||||
var h1 = app.element(by.css('h1'));
|
||||
var okMsg = app.element(by.css('.ok-msg'));
|
||||
|
||||
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 () {
|
||||
var app = element(by.css('hero-io'));
|
||||
var confirmComponent = app.element(by.css('my-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() {
|
||||
var app = element(by.css('heroes-bindings'));
|
||||
var h1 = app.element(by.css('h1'));
|
||||
|
||||
expect(app.getAttribute('class')).toBe('heading');
|
||||
expect(app.getAttribute('title')).toBe('Tooltip content');
|
||||
|
||||
h1.click();
|
||||
expect(h1.getAttribute('class')).toBe('active');
|
||||
|
||||
h1.click();
|
||||
browser.actions().doubleClick(h1).perform();
|
||||
expect(h1.getAttribute('class')).toBe('active');
|
||||
});
|
||||
|
||||
it('should support content and view queries', function() {
|
||||
var app = element(by.css('heroes-queries'));
|
||||
var windstorm = app.element(by.css('hero:first-child'));
|
||||
|
||||
app.element(by.buttonText('Activate')).click();
|
||||
expect(windstorm.element(by.css('h2')).getAttribute('class')).toBe('active');
|
||||
expect(windstorm.element(by.css('active-label')).getText()).toBe('Active');
|
||||
});
|
||||
|
||||
function testTag(selector, expectedText) {
|
||||
var component = element(by.css(selector));
|
||||
expect(component.getText()).toBe(expectedText);
|
||||
}
|
||||
|
||||
});
|
|
@ -0,0 +1,13 @@
|
|||
(function(app) {
|
||||
|
||||
function DataService() {
|
||||
}
|
||||
DataService.annotations = [
|
||||
new ng.core.Injectable()
|
||||
];
|
||||
DataService.prototype.getHeroName = function() {
|
||||
return 'Windstorm';
|
||||
};
|
||||
app.DataService = DataService;
|
||||
|
||||
})(window.app = window.app || {});
|
|
@ -0,0 +1,47 @@
|
|||
(function(app) {
|
||||
|
||||
// #docregion
|
||||
var TitleComponent = ng.core.Component({
|
||||
selector: 'hero-title',
|
||||
template:
|
||||
'<h1>{{titlePrefix}} {{title}}</h1>' +
|
||||
'<button (click)="ok()">OK</button>' +
|
||||
'<ng-content></ng-content>'
|
||||
}).Class({
|
||||
constructor: [
|
||||
[
|
||||
new ng.core.Optional(),
|
||||
new ng.core.Inject('titlePrefix')
|
||||
],
|
||||
new ng.core.Attribute('title'),
|
||||
[
|
||||
new ng.core.Query('okMsg'),
|
||||
ng.core.ElementRef
|
||||
],
|
||||
function(titlePrefix, title, msg) {
|
||||
this.titlePrefix = titlePrefix;
|
||||
this.title = title;
|
||||
this.msg = msg;
|
||||
}
|
||||
],
|
||||
ok: function() {
|
||||
var msgEl =
|
||||
this.msg.first.nativeElement;
|
||||
msgEl.textContent = 'OK!';
|
||||
}
|
||||
});
|
||||
// #enddocregion
|
||||
|
||||
var AppComponent = ng.core.Component({
|
||||
selector: 'hero-di-inject-additional',
|
||||
template: '<hero-title title="Tour of Heroes">' +
|
||||
'<span #okMsg class="ok-msg"></span>' +
|
||||
'</hero-title>',
|
||||
directives: [TitleComponent]
|
||||
}).Class({
|
||||
constructor: function() { }
|
||||
});
|
||||
|
||||
app.HeroDIInjectAdditionalComponent = AppComponent;
|
||||
|
||||
})(window.app = window.app || {});
|
|
@ -0,0 +1,39 @@
|
|||
(function(app) {
|
||||
|
||||
// #docregion parameters
|
||||
function HeroComponent(name) {
|
||||
this.name = name;
|
||||
}
|
||||
HeroComponent.parameters = [
|
||||
'heroName'
|
||||
];
|
||||
HeroComponent.annotations = [
|
||||
new ng.core.Component({
|
||||
selector: 'hero-di-inject',
|
||||
template: '<h1>Hero: {{name}}</h1>'
|
||||
})
|
||||
];
|
||||
// #enddocregion parameters
|
||||
|
||||
app.HeroDIInjectComponent = HeroComponent;
|
||||
|
||||
})(window.app = window.app || {});
|
||||
|
||||
(function(app) {
|
||||
// #docregion ctor
|
||||
var HeroComponent = ng.core.Component({
|
||||
selector: 'hero-di-inline2',
|
||||
template: '<h1>Hero: {{name}}</h1>'
|
||||
})
|
||||
.Class({
|
||||
constructor:
|
||||
[new ng.core.Inject('heroName'),
|
||||
function(name) {
|
||||
this.name = name;
|
||||
}]
|
||||
});
|
||||
// #enddocregion ctor
|
||||
|
||||
app.HeroDIInjectComponent2 = HeroComponent;
|
||||
|
||||
})(window.app = window.app || {});
|
|
@ -0,0 +1,16 @@
|
|||
(function(app) {
|
||||
// #docregion
|
||||
var HeroComponent = ng.core.Component({
|
||||
selector: 'hero-di-inline',
|
||||
template: '<h1>Hero: {{name}}</h1>'
|
||||
})
|
||||
.Class({
|
||||
constructor:
|
||||
[app.DataService,
|
||||
function(service) {
|
||||
this.name = service.getHeroName();
|
||||
}]
|
||||
});
|
||||
// #enddocregion
|
||||
app.HeroDIInlineComponent = HeroComponent;
|
||||
})(window.app = window.app || {});
|
|
@ -0,0 +1,20 @@
|
|||
(function(app) {
|
||||
|
||||
// #docregion
|
||||
app.HeroDIComponent = HeroComponent;
|
||||
|
||||
function HeroComponent(dataService) {
|
||||
this.name = dataService.getHeroName();
|
||||
}
|
||||
HeroComponent.parameters = [
|
||||
app.DataService
|
||||
];
|
||||
HeroComponent.annotations = [
|
||||
new ng.core.Component({
|
||||
selector: 'hero-di',
|
||||
template: '<h1>Hero: {{name}}</h1>'
|
||||
})
|
||||
];
|
||||
// #enddocregion
|
||||
|
||||
})(window.app = window.app || {});
|
|
@ -0,0 +1,23 @@
|
|||
// #docplaster
|
||||
// #docregion appexport
|
||||
(function(app) {
|
||||
|
||||
// #docregion component
|
||||
var HeroComponent = ng.core.Component({
|
||||
selector: 'hero-view-2',
|
||||
template:
|
||||
'<h1>Name: {{getName()}}</h1>',
|
||||
})
|
||||
.Class({
|
||||
constructor: function() {
|
||||
},
|
||||
getName: function() {
|
||||
return 'Windstorm';
|
||||
}
|
||||
});
|
||||
// #enddocregion component
|
||||
|
||||
app.HeroComponentDsl = HeroComponent;
|
||||
|
||||
})(window.app = window.app || {});
|
||||
// #enddocregion appexport
|
|
@ -0,0 +1,57 @@
|
|||
(function(app) {
|
||||
// #docregion
|
||||
var ConfirmComponent = ng.core.Component({
|
||||
selector: 'my-confirm',
|
||||
inputs: [
|
||||
'okMsg',
|
||||
'notOkMsg: cancelMsg'
|
||||
],
|
||||
outputs: [
|
||||
'ok',
|
||||
'notOk: cancel'
|
||||
],
|
||||
template:
|
||||
'<button (click)="onOkClick()">' +
|
||||
'{{okMsg}}' +
|
||||
'</button>' +
|
||||
'<button (click)="onNotOkClick()">' +
|
||||
'{{notOkMsg}}' +
|
||||
'</button>'
|
||||
}).Class({
|
||||
constructor: function() {
|
||||
this.ok = new ng.core.EventEmitter();
|
||||
this.notOk = new ng.core.EventEmitter();
|
||||
},
|
||||
onOkClick: function() {
|
||||
this.ok.next(true);
|
||||
},
|
||||
onNotOkClick: function() {
|
||||
this.notOk.next(true);
|
||||
}
|
||||
});
|
||||
// #enddocregion
|
||||
|
||||
function AppComponent() {
|
||||
}
|
||||
AppComponent.annotations = [
|
||||
new ng.core.Component({
|
||||
selector: 'hero-io',
|
||||
template: '<my-confirm [okMsg]="\'OK\'"' +
|
||||
'[cancelMsg]="\'Cancel\'"' +
|
||||
'(ok)="onOk()"' +
|
||||
'(cancel)="onCancel()">' +
|
||||
'</my-confirm>' +
|
||||
'<span *ngIf="okClicked">OK clicked</span>' +
|
||||
'<span *ngIf="cancelClicked">Cancel clicked</span>',
|
||||
directives: [ConfirmComponent]
|
||||
})
|
||||
];
|
||||
AppComponent.prototype.onOk = function() {
|
||||
this.okClicked = true;
|
||||
}
|
||||
AppComponent.prototype.onCancel = function() {
|
||||
this.cancelClicked = true;
|
||||
}
|
||||
app.HeroIOComponent = AppComponent;
|
||||
|
||||
})(window.app = window.app || {});
|
|
@ -0,0 +1,21 @@
|
|||
// #docplaster
|
||||
(function(app) {
|
||||
// #docregion
|
||||
function HeroComponent() {}
|
||||
// #enddocregion
|
||||
HeroComponent.annotations = [
|
||||
new ng.core.Component({
|
||||
selector: 'hero-lifecycle',
|
||||
template: '<h1>Hero: {{name}}</h1>'
|
||||
})
|
||||
];
|
||||
// #docregion
|
||||
HeroComponent.prototype.ngOnInit =
|
||||
function() {
|
||||
this.name = 'Windstorm';
|
||||
};
|
||||
// #enddocregion
|
||||
|
||||
app.HeroLifecycleComponent = HeroComponent;
|
||||
|
||||
})(window.app = window.app || {});
|
|
@ -0,0 +1,32 @@
|
|||
// #docplaster
|
||||
// #docregion appexport
|
||||
(function(app) {
|
||||
// #enddocregion appexport
|
||||
|
||||
// #docregion metadata
|
||||
// #docregion appexport
|
||||
// #docregion constructorproto
|
||||
function HeroComponent() {
|
||||
this.title = "Hero Detail";
|
||||
}
|
||||
|
||||
// #enddocregion constructorproto
|
||||
// #enddocregion appexport
|
||||
HeroComponent.annotations = [
|
||||
new ng.core.Component({
|
||||
selector: 'hero-view',
|
||||
template:
|
||||
'<h1>Hero: {{getName()}}</h1>'
|
||||
})
|
||||
];
|
||||
// #docregion constructorproto
|
||||
HeroComponent.prototype.getName =
|
||||
function() {return 'Windstorm';};
|
||||
// #enddocregion constructorproto
|
||||
// #enddocregion metadata
|
||||
|
||||
// #docregion appexport
|
||||
app.HeroComponent = HeroComponent;
|
||||
|
||||
})(window.app = window.app || {});
|
||||
// #enddocregion appexport
|
|
@ -0,0 +1,30 @@
|
|||
(function(app) {
|
||||
|
||||
// #docregion
|
||||
var HeroesComponent = ng.core.Component({
|
||||
selector: 'heroes-bindings',
|
||||
template: '<h1 [class.active]="active">' +
|
||||
'Tour of Heroes' +
|
||||
'</h1>',
|
||||
host: {
|
||||
'[title]': 'title',
|
||||
'[class.heading]': 'hClass',
|
||||
'(click)': 'clicked()',
|
||||
'(dblclick)': 'doubleClicked($event)'
|
||||
}
|
||||
}).Class({
|
||||
constructor: function() {
|
||||
this.title = 'Tooltip content';
|
||||
this.hClass = true;
|
||||
},
|
||||
clicked: function() {
|
||||
this.active = !this.active;
|
||||
},
|
||||
doubleClicked: function(evt) {
|
||||
this.active = true;
|
||||
}
|
||||
});
|
||||
// #enddocregion
|
||||
app.HeroesHostBindingsComponent = HeroesComponent;
|
||||
|
||||
})(window.app = window.app || {});
|
|
@ -0,0 +1,73 @@
|
|||
(function(app) {
|
||||
|
||||
var ActiveLabelComponent = ng.core.Component({
|
||||
selector: 'active-label',
|
||||
template: '<span class="active-label"' +
|
||||
'*ngIf="active">' +
|
||||
'Active' +
|
||||
'</span>'
|
||||
}).Class({
|
||||
constructor: function() { },
|
||||
activate: function() {
|
||||
this.active = true;
|
||||
}
|
||||
});
|
||||
|
||||
// #docregion content
|
||||
var HeroComponent = ng.core.Component({
|
||||
selector: 'hero',
|
||||
template: '<h2 [class.active]=active>' +
|
||||
'{{hero.name}} ' +
|
||||
'<ng-content></ng-content>' +
|
||||
'</h2>',
|
||||
inputs: ['hero'],
|
||||
queries: {
|
||||
label: new ng.core.ContentChild(
|
||||
ActiveLabelComponent)
|
||||
}
|
||||
}).Class({
|
||||
constructor: function() { },
|
||||
activate: function() {
|
||||
this.active = true;
|
||||
this.label.activate();
|
||||
}
|
||||
});
|
||||
// #enddocregion content
|
||||
|
||||
// #docregion view
|
||||
var AppComponent = ng.core.Component({
|
||||
selector: 'heroes-queries',
|
||||
template:
|
||||
'<hero *ngFor="#hero of heroData"' +
|
||||
'[hero]="hero">' +
|
||||
'<active-label></active-label>' +
|
||||
'</hero>' +
|
||||
'<button (click)="activate()">' +
|
||||
'Activate' +
|
||||
'</button>',
|
||||
directives: [
|
||||
HeroComponent,
|
||||
ActiveLabelComponent
|
||||
],
|
||||
queries: {
|
||||
heroCmps: new ng.core.ViewChildren(
|
||||
HeroComponent)
|
||||
}
|
||||
}).Class({
|
||||
constructor: function() {
|
||||
this.heroData = [
|
||||
{id: 1, name: 'Windstorm'},
|
||||
{id: 2, name: 'Superman'}
|
||||
];
|
||||
},
|
||||
activate: function() {
|
||||
this.heroCmps.forEach(function(cmp) {
|
||||
cmp.activate();
|
||||
});
|
||||
}
|
||||
});
|
||||
// #enddocregion view
|
||||
|
||||
app.HeroesQueriesComponent = AppComponent;
|
||||
|
||||
})(window.app = window.app || {});
|
|
@ -0,0 +1,41 @@
|
|||
// #docplaster
|
||||
// #docregion appimport
|
||||
(function(app) {
|
||||
// #enddocregion appimport
|
||||
|
||||
// #docregion ng2import
|
||||
var provide =
|
||||
ng.core.provide;
|
||||
var bootstrap =
|
||||
ng.platform.browser.bootstrap;
|
||||
var LocationStrategy =
|
||||
ng.router.LocationStrategy;
|
||||
var HashLocationStrategy =
|
||||
ng.router.HashLocationStrategy;
|
||||
// #enddocregion ng2import
|
||||
|
||||
// #docregion appimport
|
||||
var HeroComponent = app.HeroComponent;
|
||||
// #enddocregion appimport
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
bootstrap(HeroComponent);
|
||||
bootstrap(app.HeroComponentDsl);
|
||||
bootstrap(app.HeroLifecycleComponent);
|
||||
bootstrap(app.HeroDIComponent, [app.DataService]);
|
||||
bootstrap(app.HeroDIInlineComponent, [app.DataService]);
|
||||
bootstrap(app.HeroDIInjectComponent, [
|
||||
ng.core.provide('heroName', {useValue: 'Windstorm'})
|
||||
]);
|
||||
bootstrap(app.HeroDIInjectComponent2, [
|
||||
ng.core.provide('heroName', {useValue: 'Bombasto'})
|
||||
]);
|
||||
bootstrap(app.HeroDIInjectAdditionalComponent);
|
||||
bootstrap(app.HeroIOComponent);
|
||||
bootstrap(app.HeroesHostBindingsComponent);
|
||||
bootstrap(app.HeroesQueriesComponent);
|
||||
});
|
||||
|
||||
// #docregion appimport
|
||||
})(window.app = window.app || {});
|
||||
// #enddocregion appimport
|
|
@ -0,0 +1,62 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<base href="/">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
|
||||
<!-- IE required polyfills, in this exact order -->
|
||||
<script src="node_modules/es6-shim/es6-shim.min.js"></script>
|
||||
<script src="node_modules/systemjs/dist/system-polyfills.js"></script>
|
||||
<script src="node_modules/angular2/es6/dev/src/testing/shims_for_IE.js"></script>
|
||||
|
||||
<script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
|
||||
<script src="node_modules/rxjs/bundles/Rx.umd.js"></script>
|
||||
<script src="node_modules/angular2/bundles/angular2-all.umd.dev.js"></script>
|
||||
<script src="app/data.service.js"></script>
|
||||
<script src="app/hero.component.js"></script>
|
||||
<script src="app/hero-dsl.component.js"></script>
|
||||
<script src="app/hero-lifecycle.component.js"></script>
|
||||
<script src="app/hero-io.component.js"></script>
|
||||
<script src="app/hero-di.component.js"></script>
|
||||
<script src="app/hero-di-inline.component.js"></script>
|
||||
<script src="app/hero-di-inject.component.js"></script>
|
||||
<script src="app/hero-di-inject-additional.component.js"></script>
|
||||
<script src="app/heroes-bindings.component.js"></script>
|
||||
<script src="app/heroes-queries.component.js"></script>
|
||||
<script src="app/main.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<a id="toc"></a>
|
||||
<h1>TypeScript to JavaScript</h1>
|
||||
<a href="#class-metadata">Classes and Class Metadata</a><br>
|
||||
<a href="#property-metadata">Input and Output Metadata</a><br>
|
||||
<a href="#dependency-injection">Dependency Injection</a><br>
|
||||
<a href="#other-property-metadata">Host and Query Metadata</a><br>
|
||||
|
||||
<hr>
|
||||
<h4 id="class-metadata">Classes and Class Metadata</h4>
|
||||
<hero-view>Loading hero-view...</hero-view>
|
||||
<hero-view-2>Loading hero-view2...</hero-view-2>
|
||||
<hero-lifecycle>Loading hero-lifecycle...</hero-lifecycle>
|
||||
|
||||
<hr>
|
||||
<h4 id="property-metadata">Input and Output Metadata</h4>
|
||||
<hero-io>Loading hero-io...</hero-io>
|
||||
|
||||
<hr>
|
||||
<h4 id="dependency-injection">Dependency Injection</h4>
|
||||
<hero-di>Loading hero-di...</hero-di>
|
||||
<hero-di-inline>Loading hero-di-inline...</hero-di-inline>
|
||||
<hero-di-inline2>Loading hero-di-inline2...</hero-di-inline2>
|
||||
<hero-di-inject>Loading hero-di-inject...</hero-di-inject>
|
||||
<hero-di-inject-additional>Loading hero-di-inject-additional...</hero-di-inject-additional>
|
||||
|
||||
<hr>
|
||||
<h4 id="other-property-metadata">Host and Query Metadata</h4>
|
||||
<heroes-bindings>Loading heroes-bindings...</heroes-bindings>
|
||||
<heroes-queries>Loading heroes-queries...</heroes-queries>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"description": "TypeScript to JavaScript",
|
||||
"files":[
|
||||
"!**/karma*.*"
|
||||
],
|
||||
"tags":["cookbook"]
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
**/*.js
|
|
@ -0,0 +1,10 @@
|
|||
import {Injectable} from 'angular2/core';
|
||||
|
||||
@Injectable()
|
||||
export class DataService {
|
||||
constructor() {
|
||||
}
|
||||
getHeroName() {
|
||||
return 'Windstorm';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
import {
|
||||
Attribute,
|
||||
Component,
|
||||
ElementRef,
|
||||
Inject,
|
||||
Optional,
|
||||
Query,
|
||||
QueryList
|
||||
} from 'angular2/core';
|
||||
|
||||
// #docregion
|
||||
@Component({
|
||||
selector: 'hero-title',
|
||||
template: `
|
||||
<h1>{{titlePrefix}} {{title}}</h1>
|
||||
<button (click)="ok()">OK</button>
|
||||
<ng-content></ng-content>
|
||||
`
|
||||
})
|
||||
export class TitleComponent {
|
||||
constructor(
|
||||
@Inject('titlePrefix')
|
||||
@Optional()
|
||||
private titlePrefix:string,
|
||||
@Attribute('title')
|
||||
private title:string,
|
||||
@Query('okMsg')
|
||||
private msg:QueryList<ElementRef>) {
|
||||
}
|
||||
|
||||
ok() {
|
||||
let msgEl =
|
||||
this.msg.first.nativeElement;
|
||||
msgEl.textContent = 'OK!';
|
||||
}
|
||||
}
|
||||
// #enddocregion
|
||||
|
||||
@Component({
|
||||
selector: 'hero-di-inject-additional',
|
||||
template: `<hero-title title="Tour of Heroes">
|
||||
<span #okMsg class="ok-msg"></span>
|
||||
</hero-title>`,
|
||||
directives: [TitleComponent]
|
||||
})
|
||||
export class AppComponent {
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
import {Component, Inject} from 'angular2/core';
|
||||
|
||||
// #docregion
|
||||
@Component({
|
||||
selector: 'hero-di-inject',
|
||||
template: `<h1>Hero: {{name}}</h1>`
|
||||
})
|
||||
export class HeroComponent {
|
||||
constructor(
|
||||
@Inject('heroName')
|
||||
private name:string) {
|
||||
}
|
||||
}
|
||||
// #enddocregion
|
|
@ -0,0 +1,15 @@
|
|||
import {Component} from 'angular2/core';
|
||||
import {DataService} from './data.service';
|
||||
|
||||
// #docregion
|
||||
@Component({
|
||||
selector: 'hero-di',
|
||||
template: `<h1>Hero: {{name}}</h1>`
|
||||
})
|
||||
export class HeroComponent {
|
||||
name:string;
|
||||
constructor(dataService:DataService) {
|
||||
this.name = dataService.getHeroName();
|
||||
}
|
||||
}
|
||||
// #enddocregion
|
|
@ -0,0 +1,56 @@
|
|||
import {Component, EventEmitter, Input, Output} from 'angular2/core';
|
||||
|
||||
// #docregion
|
||||
@Component({
|
||||
selector: 'my-confirm',
|
||||
template: `
|
||||
<button (click)="onOkClick()">
|
||||
{{okMsg}}
|
||||
</button>
|
||||
<button (click)="onNotOkClick()">
|
||||
{{notOkMsg}}
|
||||
</button>
|
||||
`
|
||||
})
|
||||
export class ConfirmComponent {
|
||||
@Input() okMsg:string;
|
||||
@Input('cancelMsg') notOkMsg:string;
|
||||
@Output() ok =
|
||||
new EventEmitter();
|
||||
@Output('cancel') notOk =
|
||||
new EventEmitter();
|
||||
|
||||
onOkClick() {
|
||||
this.ok.next(true);
|
||||
}
|
||||
onNotOkClick() {
|
||||
this.notOk.next(true);
|
||||
}
|
||||
}
|
||||
// #enddocregion
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'hero-io',
|
||||
template: `
|
||||
<my-confirm [okMsg]="'OK'"
|
||||
[cancelMsg]="'Cancel'"
|
||||
(ok)="onOk()"
|
||||
(cancel)="onCancel()">
|
||||
</my-confirm>
|
||||
<span *ngIf="okClicked">OK clicked</span>
|
||||
<span *ngIf="cancelClicked">Cancel clicked</span>
|
||||
`,
|
||||
directives: [ConfirmComponent]
|
||||
})
|
||||
export class AppComponent {
|
||||
okClicked:boolean;
|
||||
cancelClicked:boolean;
|
||||
|
||||
onOk() {
|
||||
this.okClicked = true;
|
||||
}
|
||||
onCancel() {
|
||||
this.cancelClicked = true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
import {Component, OnInit}
|
||||
from 'angular2/core';
|
||||
// #enddocregion
|
||||
|
||||
@Component({
|
||||
selector: 'hero-lifecycle',
|
||||
template: `<h1>Hero: {{name}}</h1>`
|
||||
})
|
||||
// #docregion
|
||||
export class HeroComponent
|
||||
implements OnInit {
|
||||
name:string;
|
||||
ngOnInit() {
|
||||
this.name = 'Windstorm';
|
||||
}
|
||||
}
|
||||
// #enddocregion
|
|
@ -0,0 +1,18 @@
|
|||
// #docplaster
|
||||
// #docregion metadata
|
||||
import {Component} from 'angular2/core';
|
||||
|
||||
@Component({
|
||||
selector: 'hero-view',
|
||||
template:
|
||||
'<h1>Hero: {{getName()}}</h1>'
|
||||
})
|
||||
// #docregion appexport
|
||||
// #docregion class
|
||||
export class HeroComponent {
|
||||
title = 'Hero Detail';
|
||||
getName() {return 'Windstorm';}
|
||||
}
|
||||
// #enddocregion class
|
||||
// #enddocregion appexport
|
||||
// #enddocregion metadata
|
|
@ -0,0 +1,28 @@
|
|||
import {Component, HostBinding, HostListener} from 'angular2/core';
|
||||
|
||||
// #docregion
|
||||
@Component({
|
||||
selector: 'heroes-bindings',
|
||||
template: `<h1 [class.active]="active">
|
||||
Tour of Heroes
|
||||
</h1>`
|
||||
})
|
||||
export class HeroesComponent {
|
||||
@HostBinding() title = 'Tooltip content';
|
||||
@HostBinding('class.heading')
|
||||
hClass = true
|
||||
active:boolean;
|
||||
|
||||
constructor() {}
|
||||
|
||||
@HostListener('click')
|
||||
clicked() {
|
||||
this.active = !this.active;
|
||||
}
|
||||
|
||||
@HostListener('dblclick', ['$event'])
|
||||
doubleClicked(evt:Event) {
|
||||
this.active = true;
|
||||
}
|
||||
}
|
||||
// #enddocregion
|
|
@ -0,0 +1,79 @@
|
|||
import {
|
||||
Component,
|
||||
ViewChildren,
|
||||
ContentChild,
|
||||
QueryList,
|
||||
Input
|
||||
} from 'angular2/core';
|
||||
|
||||
@Component({
|
||||
selector: 'active-label',
|
||||
template: `<span class="active-label"
|
||||
*ngIf="active">
|
||||
Active
|
||||
</span>`
|
||||
})
|
||||
class ActiveLabelComponent {
|
||||
active:boolean;
|
||||
|
||||
activate() {
|
||||
this.active = true;
|
||||
}
|
||||
}
|
||||
|
||||
// #docregion content
|
||||
@Component({
|
||||
selector: 'hero',
|
||||
template: `<h2 [class.active]=active>
|
||||
{{hero.name}}
|
||||
<ng-content></ng-content>
|
||||
</h2>`
|
||||
})
|
||||
class HeroComponent {
|
||||
@Input() hero:any;
|
||||
active:boolean;
|
||||
|
||||
@ContentChild(ActiveLabelComponent)
|
||||
label:ActiveLabelComponent
|
||||
|
||||
activate() {
|
||||
this.active = true;
|
||||
this.label.activate();
|
||||
}
|
||||
}
|
||||
// #enddocregion content
|
||||
|
||||
|
||||
// #docregion view
|
||||
@Component({
|
||||
selector: 'heroes-queries',
|
||||
template: `
|
||||
<hero *ngFor="#hero of heroData"
|
||||
[hero]="hero">
|
||||
<active-label></active-label>
|
||||
</hero>
|
||||
<button (click)="activate()">
|
||||
Activate
|
||||
</button>
|
||||
`,
|
||||
directives: [
|
||||
HeroComponent,
|
||||
ActiveLabelComponent
|
||||
]
|
||||
})
|
||||
export class HeroesQueriesComponent {
|
||||
heroData = [
|
||||
{id: 1, name: 'Windstorm'},
|
||||
{id: 2, name: 'Superman'}
|
||||
];
|
||||
|
||||
@ViewChildren(HeroComponent)
|
||||
heroCmps:QueryList<HeroComponent>;
|
||||
|
||||
activate() {
|
||||
this.heroCmps.forEach(
|
||||
(cmp) => cmp.activate()
|
||||
);
|
||||
}
|
||||
}
|
||||
// #enddocregion view
|
|
@ -0,0 +1,35 @@
|
|||
// #docregion ng2import
|
||||
import {provide}
|
||||
from 'angular2/core';
|
||||
import {bootstrap}
|
||||
from 'angular2/platform/browser';
|
||||
import {
|
||||
LocationStrategy,
|
||||
HashLocationStrategy
|
||||
} from 'angular2/router';
|
||||
// #enddocregion ng2import
|
||||
|
||||
// #docregion appimport
|
||||
import {HeroComponent}
|
||||
from './hero.component';
|
||||
// #enddocregion appimport
|
||||
import {HeroComponent as HeroLifecycleComponent} from './hero-lifecycle.component';
|
||||
import {HeroComponent as HeroDIComponent} from './hero-di.component';
|
||||
import {HeroComponent as HeroDIInjectComponent} from './hero-di-inject.component';
|
||||
import {AppComponent as AppDIInjectAdditionalComponent} from './hero-di-inject-additional.component';
|
||||
import {AppComponent as AppIOComponent} from './hero-io.component';
|
||||
import {HeroesComponent as HeroesHostBindingsComponent} from './heroes-bindings.component';
|
||||
import {HeroesQueriesComponent} from './heroes-queries.component';
|
||||
|
||||
import {DataService} from './data.service';
|
||||
|
||||
bootstrap(HeroComponent);
|
||||
bootstrap(HeroLifecycleComponent);
|
||||
bootstrap(HeroDIComponent, [DataService]);
|
||||
bootstrap(HeroDIInjectComponent, [
|
||||
provide('heroName', {useValue: 'Windstorm'})
|
||||
]);
|
||||
bootstrap(AppDIInjectAdditionalComponent);
|
||||
bootstrap(AppIOComponent);
|
||||
bootstrap(HeroesHostBindingsComponent);
|
||||
bootstrap(HeroesQueriesComponent);
|
|
@ -0,0 +1,61 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<base href="/">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
|
||||
<!-- IE required polyfills, in this exact order -->
|
||||
<script src="node_modules/es6-shim/es6-shim.min.js"></script>
|
||||
<script src="node_modules/systemjs/dist/system-polyfills.js"></script>
|
||||
<script src="node_modules/angular2/es6/dev/src/testing/shims_for_IE.js"></script>
|
||||
|
||||
<script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
|
||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||
<script src="node_modules/rxjs/bundles/Rx.js"></script>
|
||||
<script src="node_modules/angular2/bundles/angular2.dev.js"></script>
|
||||
<script src="node_modules/angular2/bundles/router.dev.js"></script>
|
||||
<script>
|
||||
System.config({
|
||||
packages: {
|
||||
app: {
|
||||
format: 'register',
|
||||
defaultExtension: 'js'
|
||||
}
|
||||
}
|
||||
});
|
||||
System.import('app/main')
|
||||
.then(null, console.error.bind(console));
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<a id="toc"></a>
|
||||
<h1>TypeScript to JavaScript</h1>
|
||||
<a href="#class-metadata">Classes and Class Metadata</a><br>
|
||||
<a href="#property-metadata">Input and Output Metadata</a><br>
|
||||
<a href="#dependency-injection">Dependency Injection</a><br>
|
||||
<a href="#other-property-metadata">Host and Query Metadata</a><br>
|
||||
|
||||
<hr>
|
||||
<h4 id="class-metadata">Classes and Class Metadata</h4>
|
||||
<hero-view id="class-metadata">Loading hero-view...</hero-view>
|
||||
<hero-lifecycle>Loading hero-lifecycle...</hero-lifecycle>
|
||||
|
||||
<hr>
|
||||
<h4 id="property-metadata">Input and Output Metadata</h4>
|
||||
<hero-io>Loading hero-io...</hero-io>
|
||||
|
||||
<hr>
|
||||
<h4 id="dependency-injection">Dependency Injection</h4>
|
||||
<hero-di>Loading hero-di...</hero-di>
|
||||
<hero-di-inject>Loading hero-di-inject...</hero-di-inject>
|
||||
<hero-di-inject-additional>Loading hero-di-inject-additional...</hero-di-inject-additional>
|
||||
|
||||
<hr>
|
||||
<h4 id="other-property-metadata">Host and Query Metadata</h4>
|
||||
<heroes-bindings>Loading heroes-bindings...</heroes-bindings>
|
||||
<heroes-queries id="other-property-metadata">Loading heroes-queries...</heroes-queries>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"description": "TypeScript to JavaScript",
|
||||
"files":[
|
||||
"!**/*.d.ts",
|
||||
"!**/*.js"
|
||||
],
|
||||
"tags":["cookbook"]
|
||||
}
|
|
@ -2,18 +2,30 @@
|
|||
"index": {
|
||||
"title": "Cookbook",
|
||||
"navTitle": "Overview",
|
||||
"description": "A collection of recipes for common Angular application scenarios"
|
||||
"intro": "A collection of recipes for common Angular application scenarios"
|
||||
},
|
||||
|
||||
"a1-a2-quick-reference": {
|
||||
"title": "Angular 1 to 2 Quick Reference",
|
||||
"navTitle": "Angular 1 to 2 Quick Ref",
|
||||
"description": "Learn how Angular 1 concepts and techniques map to Angular 2",
|
||||
"intro": "Learn how Angular 1 concepts and techniques map to Angular 2",
|
||||
"hide": true
|
||||
},
|
||||
|
||||
"component-communication": {
|
||||
"title": "Component Interaction",
|
||||
"description": "Share information between different directives and components"
|
||||
"intro": "Share information between different directives and components"
|
||||
},
|
||||
|
||||
"dynamic-form": {
|
||||
"title": "Dynamic Form",
|
||||
"intro": "Render dynamic forms with NgFormModel",
|
||||
"hide": true
|
||||
},
|
||||
|
||||
"ts-to-js": {
|
||||
"title": "TypeScript to JavaScript",
|
||||
"intro": "Convert Angular 2 TypeScript examples into ES5 JavaScript",
|
||||
"hide": true
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
!= partial("../../../_includes/_ts-temp")
|
|
@ -0,0 +1 @@
|
|||
!= partial("../../../_includes/_ts-temp")
|
|
@ -35,7 +35,7 @@
|
|||
"title": "API Preview",
|
||||
"reference": true
|
||||
},
|
||||
|
||||
|
||||
"cheatsheet": {
|
||||
"title": "Angular Cheat Sheet",
|
||||
"intro": "A quick quide to Angular syntax.",
|
||||
|
@ -47,7 +47,7 @@
|
|||
"intro": "Brief definitions of the most important words in the Angular 2 vocabulary",
|
||||
"reference": true
|
||||
},
|
||||
|
||||
|
||||
"resources": {
|
||||
"icon": "play-circle-fill",
|
||||
"title": "Angular Resources",
|
||||
|
@ -60,7 +60,7 @@
|
|||
"title": "Help & Support",
|
||||
"resources": true
|
||||
},
|
||||
|
||||
|
||||
"styleguide": {
|
||||
"title": "Docs Style Guide",
|
||||
"intro": "Design & Layout Patterns For Documentation"
|
||||
|
|
|
@ -2,17 +2,29 @@
|
|||
"index": {
|
||||
"title": "Cookbook",
|
||||
"navTitle": "Overview",
|
||||
"description": "A collection of recipes for common Angular application scenarios"
|
||||
"intro": "A collection of recipes for common Angular application scenarios"
|
||||
},
|
||||
|
||||
|
||||
"a1-a2-quick-reference": {
|
||||
"title": "Angular 1 to 2 Quick Reference",
|
||||
"navTitle": "Angular 1 to 2 Quick Ref",
|
||||
"description": "Learn how Angular 1 concepts and techniques map to Angular 2"
|
||||
"intro": "Learn how Angular 1 concepts and techniques map to Angular 2"
|
||||
},
|
||||
|
||||
|
||||
"component-communication": {
|
||||
"title": "Component Interaction",
|
||||
"description": "Share information between different directives and components"
|
||||
"intro": "Share information between different directives and components"
|
||||
},
|
||||
|
||||
"dynamic-form": {
|
||||
"title": "Dynamic Form",
|
||||
"intro": "Render dynamic forms with NgFormModel",
|
||||
"hide": true
|
||||
},
|
||||
|
||||
"ts-to-js": {
|
||||
"title": "TypeScript to JavaScript",
|
||||
"intro": "Convert Angular 2 TypeScript examples into ES5 JavaScript"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
!= partial("../../../_includes/_ts-temp")
|
|
@ -1 +1,3 @@
|
|||
!= partial("../../../_includes/_ts-temp")
|
||||
include ../../../../_includes/_util-fns
|
||||
|
||||
+includeShared('../../../ts/latest/cookbook/index.jade', 'cookbook')
|
||||
|
|
|
@ -0,0 +1,471 @@
|
|||
include ../../../../_includes/_util-fns
|
||||
|
||||
:marked
|
||||
Everything that we can do in Angular 2 in TypeScript, we can also do
|
||||
in JavaScript. Translating from one language to the other is mostly a
|
||||
matter of changing the way we organize our code and the way we access
|
||||
Angular 2 APIs.
|
||||
|
||||
Since TypeScript is a popular language option in Angular 2, many of the
|
||||
code examples you see on the Internet as well as on this site are written
|
||||
in TypeScript. This cookbook contains recipes for translating these kinds of
|
||||
code examples to ES5, so that they can be applied to Angular 2 JavaScript
|
||||
applications.
|
||||
|
||||
<a id="toc"></a>
|
||||
:marked
|
||||
## Table of contents
|
||||
|
||||
[Modularity: imports and exports](#modularity)
|
||||
|
||||
[Classes and Class Metadata](#class-metadata)
|
||||
|
||||
[Input and Output Metadata](#property-metadata)
|
||||
|
||||
[Dependency Injection](#dependency-injection)
|
||||
|
||||
[Host and Query Metadata](#other-property-metadata)
|
||||
|
||||
**Run and compare the live [TypeScript](/resources/live-examples/cb-ts-to-js/ts/plnkr.html) and
|
||||
[JavaScript](/resources/live-examples/cb-ts-to-js/js/plnkr.html) code shown in this cookbook.**
|
||||
|
||||
a(id="modularity")
|
||||
.l-main-section
|
||||
:marked
|
||||
## Importing and Exporting
|
||||
|
||||
- var top="vertical-align:top"
|
||||
table(width="100%")
|
||||
col(width="50%")
|
||||
col(width="50%")
|
||||
tr
|
||||
th TypeScript
|
||||
th ES5 JavaScript
|
||||
tr(style=top)
|
||||
td
|
||||
:marked
|
||||
### Importing Angular 2 Code
|
||||
|
||||
In TypeScript code, Angular 2 classes, functions, and other members
|
||||
are imported with TypeScript `import` statements:
|
||||
|
||||
+makeExample('cb-ts-to-js/ts/app/main.ts', 'ng2import')(format="." )
|
||||
|
||||
td
|
||||
:marked
|
||||
### Accessing Angular 2 Code through the ng global
|
||||
|
||||
In JavaScript code, when using
|
||||
[the Angular 2 UMD bundles](https://github.com/angular/angular/blob/master/modules/angular2/docs/bundles/overview.md),
|
||||
we can access Angular code through the global `ng` object. In the
|
||||
nested members of this object we'll find everything we would import
|
||||
from `angular2` in TypeScript:
|
||||
|
||||
+makeExample('cb-ts-to-js/js/app/main.js', 'ng2import')(format="." )
|
||||
|
||||
tr(style=top)
|
||||
td
|
||||
:marked
|
||||
### Importing and Exporting Application Code
|
||||
|
||||
Each file in an Angular 2 TypeScript application constitutes a
|
||||
TypeScript module. When we want to make something from a module available
|
||||
to other modules, we `export` it.
|
||||
|
||||
+makeExample('cb-ts-to-js/ts/app/hero.component.ts', 'appexport')(format="." )
|
||||
|
||||
:marked
|
||||
In other modules we can then `import` things that have been exported
|
||||
elsewhere.
|
||||
|
||||
+makeExample('cb-ts-to-js/ts/app/main.ts', 'appimport')(format="." )
|
||||
|
||||
td
|
||||
:marked
|
||||
### Sharing Application Code
|
||||
|
||||
In an Angular 2 JavaScript application, we load each file to the page
|
||||
using a `<script>` tag. Each file can make things available to other
|
||||
files via the shared global `window` scope.
|
||||
|
||||
We often introduce an application namespace
|
||||
object (such as `"app"`) onto `window` and attach everything we need
|
||||
to share to that namespace object.
|
||||
We also wrap our code in an
|
||||
[Immediately Invoked Function Expression (IIFE)](https://en.wikipedia.org/wiki/Immediately-invoked_function_expression).
|
||||
These practices together prevent our code from
|
||||
polluting the global scope.
|
||||
|
||||
+makeExample('cb-ts-to-js/js/app/hero.component.js', 'appexport')(format="." )
|
||||
|
||||
:marked
|
||||
We can then access anything from this shared namespace in
|
||||
other files.
|
||||
|
||||
+makeExample('cb-ts-to-js/js/app/main.js', 'appimport')(format="." )
|
||||
|
||||
:marked
|
||||
Note that the order of `<script>` tags on the page is significant.
|
||||
We must load a file that defines a shared member before
|
||||
a file that uses that member.
|
||||
|
||||
.alert.is-helpful
|
||||
:marked
|
||||
Alternatively, we can use a module loader such as Webpack or
|
||||
Browserify in an Angular 2 JavaScript project. In such a project, we would
|
||||
use CommonJS modules and the `require` function to load Angular 2 framework code.
|
||||
We would then use `module.exports` and `require` to export and import application
|
||||
code.
|
||||
|
||||
|
||||
a(id="class-metadata")
|
||||
.l-main-section
|
||||
:marked
|
||||
## Classes and Class Metadata
|
||||
|
||||
- var top="vertical-align:top"
|
||||
table(width="100%")
|
||||
col(width="50%")
|
||||
col(width="50%")
|
||||
tr
|
||||
th TypeScript
|
||||
th ES5 JavaScript
|
||||
tr(style=top)
|
||||
td
|
||||
:marked
|
||||
### Classes
|
||||
|
||||
We put most of our Angular 2 TypeScript code into TypeScript classes.
|
||||
|
||||
+makeExample('cb-ts-to-js/ts/app/hero.component.ts', 'class')(format="." )
|
||||
|
||||
td
|
||||
:marked
|
||||
### Constructors and Prototypes
|
||||
|
||||
ES5 JavaScript has no classes. We use the constructor
|
||||
pattern instead which works with Angular 2 as well as classes do.
|
||||
|
||||
+makeExample('cb-ts-to-js/js/app/hero.component.js', 'constructorproto')(format="." )
|
||||
|
||||
tr(style=top)
|
||||
td
|
||||
:marked
|
||||
### Metadata with Decorators
|
||||
|
||||
Most Angular 2 classes have one or more TypeScript *decorators*
|
||||
attached to provide configuration and metadata. For example,
|
||||
a component must have a [`@Component`](../api/core/Component-decorator.html) decorator.
|
||||
|
||||
+makeExample('cb-ts-to-js/ts/app/hero.component.ts', 'metadata')(format="." )
|
||||
|
||||
td
|
||||
:marked
|
||||
### Metadata with the Annotations Array
|
||||
|
||||
In JavaScript, we can attach an `annotations` array to a constructor
|
||||
to provide metadata.
|
||||
Each item in the array corresponds to a TypeScript decorator.
|
||||
|
||||
In the following example, we create a new instance of `Component` that corresponds
|
||||
to the [`@Component`](../api/core/Component-decorator.html) TypeScript decorator.
|
||||
|
||||
+makeExample('cb-ts-to-js/js/app/hero.component.js', 'metadata')(format="." )
|
||||
|
||||
:marked
|
||||
### Metadata with The Class Convenience API
|
||||
|
||||
The pattern of creating a constructor and decorating it with metadata
|
||||
is so common that Angular provides an alternative convenience API for it.
|
||||
This API lets us define everything in a single expression.
|
||||
|
||||
With this API we first call the `ng.core.Component` function,
|
||||
followed by a chained `Class` method call. The argument to `Class`
|
||||
is an object that defines the constructor and the instance methods
|
||||
of the component:
|
||||
|
||||
+makeExample('cb-ts-to-js/js/app/hero-dsl.component.js', 'component')(format="." )
|
||||
|
||||
:marked
|
||||
Similar APIs are also available for other decorators. You can define a
|
||||
directive:
|
||||
|
||||
code-example.
|
||||
var MyDirective = ng.core.Directive({
|
||||
...
|
||||
}).Class({
|
||||
...
|
||||
});
|
||||
|
||||
:marked
|
||||
Or a pipe:
|
||||
|
||||
code-example.
|
||||
var MyPipe = ng.core.Pipe({
|
||||
name: 'myPipe'
|
||||
}).Class({
|
||||
...
|
||||
});
|
||||
|
||||
tr(style=top)
|
||||
td
|
||||
:marked
|
||||
### Interfaces
|
||||
|
||||
When defining classes that need to implement a certain method, it
|
||||
is common to use TypeScript interfaces that enforce that the
|
||||
method signature is correct. Component lifecycle methods like `ngOnInit`
|
||||
are one example of this pattern. `ngOnInit` is defined in the `OnInit`
|
||||
interface.
|
||||
|
||||
+makeExample('cb-ts-to-js/ts/app/hero-lifecycle.component.ts')(format="." )
|
||||
|
||||
td
|
||||
:marked
|
||||
### Implementing Methods without Interfaces
|
||||
|
||||
TypeScript interfaces are purely for developer convenience
|
||||
and are not used by Angular 2 at runtime. This means that in JavaScript
|
||||
code we don't need to substitute anything for interfaces. We can just
|
||||
implement the methods.
|
||||
|
||||
+makeExample('cb-ts-to-js/js/app/hero-lifecycle.component.js')(format="." )
|
||||
|
||||
a(id="property-metadata")
|
||||
.l-main-section
|
||||
:marked
|
||||
## Input and Output Metadata
|
||||
|
||||
- var top="vertical-align:top"
|
||||
table(width="100%")
|
||||
col(width="50%")
|
||||
col(width="50%")
|
||||
tr
|
||||
th TypeScript
|
||||
th ES5 JavaScript
|
||||
tr(style=top)
|
||||
td
|
||||
:marked
|
||||
### Input and Output Decorators
|
||||
|
||||
In TypeScript, property decorators are often used to provide additional metadata
|
||||
for components and directives.
|
||||
|
||||
For [inputs and outputs](../guide/template-syntax.html#inputs-outputs),
|
||||
we use [`@Input`](../api/core/Input-var.html)
|
||||
and [`@Output`](../api/core/Output-var.html) property decorators.
|
||||
They may optionally specify input and output binding names if we want them to be
|
||||
different from the class property names.
|
||||
|
||||
+makeExample('cb-ts-to-js/ts/app/hero-io.component.ts')(format="." )
|
||||
|
||||
.alert.is-helpful
|
||||
:marked
|
||||
In TypeScript we can also use the `inputs` and `outputs` array metadata
|
||||
instead of the `@Input` and `@Output` property decorators.
|
||||
td
|
||||
:marked
|
||||
### Inputs and Outputs in Component Metadata
|
||||
|
||||
There is no equivalent of a property decorator in ES5 JavaScript. Instead,
|
||||
we add comparable information to the `Component` (or `Directive`) metadata.
|
||||
|
||||
In this example, we add `inputs` and `outputs` array attributes
|
||||
containing the input and output property names.
|
||||
If we need a binding name that is different from the
|
||||
property itself, we use the `propertyName: bindingName` syntax.
|
||||
|
||||
+makeExample('cb-ts-to-js/js/app/hero-io.component.js')(format="." )
|
||||
|
||||
|
||||
.l-main-section
|
||||
:marked
|
||||
## Dependency Injection
|
||||
|
||||
- var top="vertical-align:top"
|
||||
table(width="100%")
|
||||
col(width="50%")
|
||||
col(width="50%")
|
||||
tr
|
||||
th TypeScript
|
||||
th ES5 JavaScript
|
||||
tr(style=top)
|
||||
td
|
||||
:marked
|
||||
### Injection by Type
|
||||
|
||||
Angular 2 can often use TypeScript type information to
|
||||
determine what needs to be injected.
|
||||
|
||||
+makeExample('cb-ts-to-js/ts/app/hero-di.component.ts')(format="." )
|
||||
|
||||
td
|
||||
:marked
|
||||
### Injection with Parameter Tokens
|
||||
|
||||
Since no type information is available in ES5 JavaScript,
|
||||
we must identify "injectables" in some other way.
|
||||
|
||||
We attach a `parameters` array to the constructor function.
|
||||
Each array item is the dependency injection token that identifies the thing to be injected.
|
||||
Often the token is the constructor function for the class-like dependency.
|
||||
|
||||
+makeExample('cb-ts-to-js/js/app/hero-di.component.js')(format="." )
|
||||
|
||||
:marked
|
||||
When using the class convenience API, we can also supply the parameter
|
||||
tokens by wrapping the constructor in an array.
|
||||
|
||||
+makeExample('cb-ts-to-js/js/app/hero-di-inline.component.js')(format="." )
|
||||
|
||||
tr(style=top)
|
||||
td
|
||||
:marked
|
||||
### Injection with the @Inject decorator
|
||||
|
||||
When the thing being injected doesn't correspond directly to a type,
|
||||
we use the `@Inject()` decorator to supply the injection token.
|
||||
|
||||
In this example, we're injecting a string identified by the "heroName" token.
|
||||
|
||||
+makeExample('cb-ts-to-js/ts/app/hero-di-inject.component.ts')(format="." )
|
||||
|
||||
td
|
||||
:marked
|
||||
### Injection with plain string tokens
|
||||
|
||||
In JavaScript we add the token string to the injection parameters array.
|
||||
|
||||
+makeExample('cb-ts-to-js/js/app/hero-di-inject.component.js','parameters')(format="." )
|
||||
|
||||
:marked
|
||||
Alternatively, we can create a token with the `Inject` method and
|
||||
add that to the constructor array in the annotations like this:
|
||||
|
||||
+makeExample('cb-ts-to-js/js/app/hero-di-inject.component.js','ctor')(format="." )
|
||||
|
||||
tr(style=top)
|
||||
td
|
||||
:marked
|
||||
### Additional Injection Decorators
|
||||
|
||||
We can attach additional decorators to constructor parameters
|
||||
to qualify the injection behavior. We can mark
|
||||
optional dependencies with the [`@Optional`](../api/core/Optional-var.html),
|
||||
inject host element attributes with [`@Attribute`](../api/core/Attribute-var.html),
|
||||
inject content child queries with [`@Query`](../api/core/Query-var.html)
|
||||
and inject view child queries with [`@ViewQuery`](../api/core/ViewQuery-var.html)).
|
||||
|
||||
+makeExample('cb-ts-to-js/ts/app/hero-di-inject-additional.component.ts')(format="." )
|
||||
|
||||
td
|
||||
:marked
|
||||
### Additional Injection Metadata with Nested Arrays
|
||||
|
||||
To achieve the same effect in JavaScript, use the constructor array notation
|
||||
in which the injection information precedes the constructor function itself.
|
||||
|
||||
Use the injection support functions `Attribute`, `Host`, `Optional`, `Self`, `SkipSelf`,
|
||||
`Query` and `ViewQuery` to qualify dependency injection behavior.
|
||||
|
||||
Use a nested array to combine injection functions.
|
||||
|
||||
+makeExample('cb-ts-to-js/js/app/hero-di-inject-additional.component.js')(format="." )
|
||||
|
||||
:marked
|
||||
We can apply other additional parameter decorators such as
|
||||
[`@Host`](../api/core/Host-var.html) and
|
||||
[`@SkipSelf`](../api/core/SkipSelf-var.html) in the same way -
|
||||
by adding `new ng.core.Host()` or `ng.core.SkipSelf()` in the
|
||||
parameters array.
|
||||
|
||||
|
||||
a(id="other-property-metadata")
|
||||
.l-main-section
|
||||
:marked
|
||||
## Host and Query Metadata
|
||||
|
||||
- var top="vertical-align:top"
|
||||
table(width="100%")
|
||||
col(width="50%")
|
||||
col(width="50%")
|
||||
tr
|
||||
th TypeScript
|
||||
th ES5 JavaScript
|
||||
tr(style=top)
|
||||
|
||||
td
|
||||
:marked
|
||||
### Host Decorators
|
||||
|
||||
We can use host property decorators to bind a host element to a component or directive.
|
||||
The [`@HostBinding`](../api/core/HostBinding-var.html) decorator
|
||||
binds host element properties to component data properties.
|
||||
The [`@HostListener`](../api/core/HostListener-var.html) decorator bimds
|
||||
host element events to component event handlers.
|
||||
|
||||
+makeExample('cb-ts-to-js/ts/app/heroes-bindings.component.ts')(format="." )
|
||||
|
||||
.alert.is-helpful
|
||||
:marked
|
||||
In TypeScript we can also use `host` metadata
|
||||
instead of the `@HostBinding` and `@HostListener` property decorators.
|
||||
td
|
||||
:marked
|
||||
### Host Metadata
|
||||
|
||||
We add a `host` attribute to the component metadata to achieve the
|
||||
same effect as `@HostBinding` and `@HostListener`.
|
||||
|
||||
The `host` value is an object whose properties are host property and listener bindings:
|
||||
|
||||
* Each key follows regular Angular 2 binding syntax: `[property]` for host bindings
|
||||
or `(event)` for host listeners.
|
||||
* Each value identifies the corresponding component property or method.
|
||||
|
||||
+makeExample('cb-ts-to-js/js/app/heroes-bindings.component.js')(format="." )
|
||||
|
||||
tr(style=top)
|
||||
td
|
||||
:marked
|
||||
### Query Decorators
|
||||
|
||||
There are several property decorators for querying the descendants of
|
||||
a component or directive.
|
||||
|
||||
The [`@ViewChild`](../api/core/ViewChild-var.html) and
|
||||
[`@ViewChildren`](../api/core/ViewChildren-var.html) property decorators
|
||||
allow a component to query instances of other components that are used in
|
||||
its view.
|
||||
|
||||
+makeExample('cb-ts-to-js/ts/app/heroes-queries.component.ts', 'view')(format="." )
|
||||
|
||||
:marked
|
||||
The [`@ContentChild`](../api/core/ContentChild-var.html) and
|
||||
[`@ContentChildren`](../api/core/ContentChildren-var.html) property decorators
|
||||
allow a component to query instances of other components that have been projected
|
||||
into its view from elsewhere.
|
||||
|
||||
+makeExample('cb-ts-to-js/ts/app/heroes-queries.component.ts', 'content')(format="." )
|
||||
|
||||
.alert.is-helpful
|
||||
:marked
|
||||
In TypeScript we can also use the `queries` metadata
|
||||
instead of the `@ViewChild` and `@ContentChild` property decorators.
|
||||
td
|
||||
:marked
|
||||
### Query Metadata
|
||||
|
||||
We access a component's view children by adding a `queries` attribute to
|
||||
the component metadata. It should be an object where:
|
||||
|
||||
* Each key is the name of a component property that will hold the view children
|
||||
* Each value is an instance of either `ViewChild` or `ViewChildren`.
|
||||
|
||||
+makeExample('cb-ts-to-js/js/app/heroes-queries.component.js', 'view')(format="." )
|
||||
|
||||
:marked
|
||||
We add *content* child queries to the same `queries` attribute
|
||||
in the same manner, using instances of `ContentChild` or `ContentChildren`:
|
||||
|
||||
+makeExample('cb-ts-to-js/js/app/heroes-queries.component.js', 'content')(format="." )
|
|
@ -8,16 +8,21 @@
|
|||
"a1-a2-quick-reference": {
|
||||
"title": "Angular 1 to 2 Quick Reference",
|
||||
"navTitle": "Angular 1 to 2 Quick Ref",
|
||||
"description": "Learn how Angular 1 concepts and techniques map to Angular 2"
|
||||
"intro": "Learn how Angular 1 concepts and techniques map to Angular 2"
|
||||
},
|
||||
|
||||
"component-communication": {
|
||||
"title": "Component Interaction",
|
||||
"description": "Share information between different directives and components"
|
||||
"intro": "Share information between different directives and components"
|
||||
},
|
||||
|
||||
"dynamic-form": {
|
||||
"title": "Dynamic Form",
|
||||
"description": "Render dynamic forms with NgFormModel"
|
||||
"intro": "Render dynamic forms with NgFormModel"
|
||||
},
|
||||
|
||||
"ts-to-js": {
|
||||
"title": "TypeScript to JavaScript",
|
||||
"intro": "Convert Angular 2 TypeScript examples into ES5 JavaScrip"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
include ../_util-fns
|
||||
|
||||
// #docregion cookbook
|
||||
:marked
|
||||
# Angular 2 Cookbook
|
||||
|
||||
|
@ -27,3 +28,4 @@ include ../_util-fns
|
|||
[angular.io](https://github.com/angular/angular.io) github repository.
|
||||
|
||||
Post issues with *Angular 2 itself* to the [angular](https://github.com/angular/angular) github repository.
|
||||
// #enddocregion cookbook
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
!= partial("../../../js/latest/cookbook/ts-to-js")
|
|
@ -42,6 +42,11 @@ var _rxData = [
|
|||
from: 'node_modules/angular2/bundles/angular2.dev.js',
|
||||
to: 'https://code.angularjs.org/2.0.0-beta.12/angular2.dev.js'
|
||||
},
|
||||
{
|
||||
pattern: 'script',
|
||||
from: 'node_modules/angular2/bundles/angular2-all.umd.dev.js',
|
||||
to: 'https://code.angularjs.org/2.0.0-beta.12/angular2-all.umd.dev.js'
|
||||
},
|
||||
{
|
||||
pattern: 'script',
|
||||
from: 'node_modules/angular2/bundles/angular2-all.umd.js',
|
||||
|
|
Loading…
Reference in New Issue