docs(ts-to-js): ward's edits (incomplete)

This commit is contained in:
Ward Bell 2016-11-03 01:37:55 -07:00
parent 12eb19fa3c
commit 33b61977b2
11 changed files with 565 additions and 510 deletions

View File

@ -4,8 +4,7 @@ import { Component } from '@angular/core';
@Component({
selector: 'hero-view',
template:
'<h1>Hero: {{getName()}}</h1>'
template: '<h1>{{title}}: {{getName()}}</h1>'
})
// #docregion appexport
// #docregion class

View File

@ -5,7 +5,7 @@ import { Component } from '@angular/core';
// #docregion class
// #docregion appexport
export class HeroComponent {
construct() {
constructor() {
this.title = 'Hero Detail';
}
getName() {return 'Windstorm'; }
@ -16,7 +16,7 @@ export class HeroComponent {
HeroComponent.annotations = [
new Component({
selector: 'hero-view',
template: '<h1>Hero: {{getName()}}</h1>'
template: '<h1>{{title}}: {{getName()}}</h1>'
})
];
// #enddocregion metadata

View File

@ -5,14 +5,13 @@
// #docregion component
var HeroComponent = ng.core.Component({
selector: 'hero-view-2',
template: '<h1>Name: {{getName()}}</h1>',
template: '<h1>{{title}}: {{getName()}}</h1>',
})
.Class({
constructor: function() {
this.title = "Hero Detail";
},
getName: function() {
return 'Windstorm';
}
getName: function() { return 'Windstorm'; }
});
// #enddocregion component

View File

@ -9,19 +9,16 @@
function HeroComponent() {
this.title = "Hero Detail";
}
HeroComponent.prototype.getName = function() { return 'Windstorm'; };
// #enddocregion constructorproto
// #enddocregion appexport
HeroComponent.annotations = [
new ng.core.Component({
selector: 'hero-view',
template: '<h1>Hero: {{getName()}}</h1>'
template: '<h1>{{title}}: {{getName()}}</h1>'
})
];
// #docregion constructorproto
HeroComponent.prototype.getName = function() {return 'Windstorm';};
// #enddocregion constructorproto
// #enddocregion metadata
app.HeroesModule =

View File

@ -4,8 +4,7 @@ import { Component } from '@angular/core';
@Component({
selector: 'hero-view',
template:
'<h1>Hero: {{getName()}}</h1>'
template: '<h1>{{title}}: {{getName()}}</h1>'
})
// #docregion appexport
// #docregion class

View File

@ -60,7 +60,7 @@
"ts-to-js": {
"title": "TypeScript to JavaScript",
"intro": "Convert Angular TypeScript examples into ES5 JavaScript",
"intro": "Convert Angular TypeScript examples into ES6 and ES5 JavaScript",
"hide": true
},

View File

@ -55,7 +55,7 @@
"ts-to-js": {
"title": "TypeScript to JavaScript",
"intro": "Convert Angular TypeScript examples into ES5 JavaScript"
"intro": "Convert Angular TypeScript examples into ES6 and ES5 JavaScript"
},
"visual-studio-2015": {

View File

@ -1,490 +1 @@
include ../../../../_includes/_util-fns
:marked
Everything that we can do in Angular in TypeScript, we can also do
in JavaScript. Translating from one language to the other is mostly a
matter of changing the way we organize our code and the way we access
Angular APIs.
Since TypeScript is a popular language option in Angular, many of the
code examples you see on the Internet as well as on this site are written
in TypeScript. This cookbook contains recipes for translating these kinds of
code examples to ES5, so that they can be applied to Angular JavaScript
applications.
<a id="toc"></a>
:marked
## Table of contents
[From TS to ES6 to ES5](#from-ts)
[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](#host-query-metadata)
**Run and compare the live <live-example name="cb-ts-to-js">TypeScript</live-example> and <live-example name="cb-ts-to-js" lang="js">JavaScript</live-example>
code shown in this cookbook.**
a(id="from-ts")
.l-main-section
:marked
## From TS to ES6 to ES5
Since TypeScript is a superset of ES6 JavaScript, and ES6 itself is a superset of ES5, the
transformation of Typescript code all the way to ES5 javascript can be seen as "shedding"
features.
When going from TypeScript to ES6 with decorators, we mostly remove
[type annotations](https://www.typescriptlang.org/docs/handbook/basic-types.html)
, such as `string` or `boolean`, and
[class property modifiers](http://www.typescriptlang.org/docs/handbook/classes.html#public-private-and-protected-modifiers)
such as `public` and `private`.
The exception is type annotations used for dependency injection, which can be kept.
Going from ES6 with decorators to plain ES6 JavaScript we lose all
[decorators](https://www.typescriptlang.org/docs/handbook/decorators.html)
and the remaining type annotations.
We also lose class properties, which now have to be declared in the class constructor.
Finally, in the transition from ES6 to ES5 JavaScript the main missing features are `import`
statements and `class` declarations.
For ES6 transpilation we recommend using a similar setup as our TypeScript quickstart,
replacing TypeScript with [Babel](https://babeljs.io/) using the `es2015` preset.
To use decorators and annotations with Babel, install the
[`angular2`](https://github.com/shuhei/babel-plugin-angular2-annotations) preset as well.
a(id="modularity")
.l-main-section
:marked
## Importing and Exporting
### Importing Angular Code
In TypeScript and ES6 JavaScript, Angular classes, functions, and other members are imported
with ES6 `import` statements.
In ES5 JavaScript code, when using [the Angular packages](../glossary.html#!#scoped-package),
we can access Angular code through the global `ng` object. In the nested members of this
object we'll find everything we would import from `@angular` in TypeScript:
+makeTabs(`
cb-ts-to-js/ts/app/main.ts,
cb-ts-to-js/js-es6-decorators/app/main.es6,
cb-ts-to-js/js-es6/app/main.es6,
cb-ts-to-js/js/app/main.js
`,`
ng2import,
ng2import,
ng2import,
ng2import
`,`
Typescript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
:marked
### Importing and Exporting Application Code
Each file in an Angular TypeScript or ES6 JavaScript application constitutes a ES6 module.
When we want to make something from a module available to other modules, we `export` it.
In an Angular ES5 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.
+makeTabs(`
cb-ts-to-js/ts/app/hero.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero.component.es6,
cb-ts-to-js/js-es6/app/hero.component.es6,
cb-ts-to-js/js/app/hero.component.js
`,`
appexport,
appexport,
appexport,
appexport
`,`
Typescript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
:marked
Using Typescript or ES6 JavaScript, in other modules we can then `import` things that have been exported
elsewhere.
In ES5 JavaScript we can access anything using the shared namespace in other files.
Note that the order of `<script>` tags on the page is significant.
We must load a file that defines a shared member before a file that uses that member.
+makeTabs(`
cb-ts-to-js/ts/app/main.ts,
cb-ts-to-js/js-es6-decorators/app/main.es6,
cb-ts-to-js/js-es6/app/main.es6,
cb-ts-to-js/js/app/main.js
`,`
appimport,
appimport,
appimport,
appimport
`,`
Typescript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
.alert.is-helpful
:marked
Alternatively, we can use a module loader such as Webpack or
Browserify in an Angular JavaScript project. In such a project, we would
use CommonJS modules and the `require` function to load Angular framework code.
We would then use `module.exports` and `require` to export and import application
code.
a(id="class-metadata")
.l-main-section
:marked
## Classes and Class Metadata
### Classes
We put most of our Angular TypeScript or ES6 JavaScript code into classes. ES6 without decorators
also does not have support for class properties, so they must be assigned inside the constructor.
ES5 JavaScript has no classes. We use the constructor pattern instead which works with
Angular as well as classes do.
+makeTabs(`
cb-ts-to-js/ts/app/hero.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero.component.es6,
cb-ts-to-js/js-es6/app/hero.component.es6,
cb-ts-to-js/js/app/hero.component.js
`,`
class,
class,
class,
constructorproto
`,`
Typescript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
:marked
### Metadata
Using Typescript or ES6 with decorators, we have access to *decorators*.
Most Angular classes have one or more *decorators* attached to provide configuration
and metadata.
For example, a component must have a
[`@Component`](../api/core/index/Component-decorator.html) decorator.
In ES5/6 JavaScript we can instead attach an `annotations` array to a class/constructor
to provide metadata.
Each item in the array corresponds to a decorator.
The pattern of creating a constructor and decorating it with metadata is so common that Angular
provides an alternative ES5 convenience class API for it for ES5 JavaScript.
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.
Similar APIs are also available for other decorators. You can define a directive with
`ng.core.Directive` or a pipe with `ng.core.Pipe`.
+makeTabs(`
cb-ts-to-js/ts/app/hero.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero.component.es6,
cb-ts-to-js/js-es6/app/hero.component.es6,
cb-ts-to-js/js/app/hero.component.js,
cb-ts-to-js/js/app/hero-dsl.component.js
`,`
metadata,
metadata,
metadata,
metadata,
component
`,`
Typescript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript,
ES5 JavaScript with Class API
`)
: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.
TypeScript interfaces are purely for developer convenience and are not used by Angular at runtime.
This means that in ES5/6 JavaScript code we don't need to substitute anything for interfaces.
We can just implement the methods.
+makeTabs(`
cb-ts-to-js/ts/app/hero-lifecycle.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero-lifecycle.component.es6,
cb-ts-to-js/js-es6/app/hero-lifecycle.component.es6,
cb-ts-to-js/js/app/hero-lifecycle.component.js
`,`
`,`
Typescript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
a(id="property-metadata")
.l-main-section
:marked
## Input and Output Metadata
### Input and Output Decorators
In TypeScript and ES6 with decorators, property decorators are often used to provide additional
metadata for components and directives.
For [inputs and outputs](../guide/template-syntax.html#inputs-outputs), we use `@Input` and
`@Output` property decorators.
They may optionally specify input and output binding names if we want them to be different
from the class property names.
There is no equivalent of a property decorator in ES5/6 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.
+makeTabs(`
cb-ts-to-js/ts/app/hero-io.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero-io.component.es6,
cb-ts-to-js/js-es6/app/hero-io.component.es6,
cb-ts-to-js/js/app/hero-io.component.js
`,`
`,`
Typescript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
.l-main-section
:marked
## Dependency Injection
### Injection by Type
Angular can often use TypeScript type information to determine what needs to be injected.
ES6 with decorators can also make use of type information.
Since no type information is available in ES5/6 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.
In ES6 the decorators need to be inside a nested array.
When using the ES5 class convenience API, we can also supply the parameter tokens by wrapping
the constructor in an array.
+makeTabs(`
cb-ts-to-js/ts/app/hero-di.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero-di.component.es6,
cb-ts-to-js/js-es6/app/hero-di.component.es6,
cb-ts-to-js/js/app/hero-di.component.js,
cb-ts-to-js/js/app/hero-di-inline.component.js
`,`
`,`
Typescript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript,
ES5 JavaScript with Class API
`)
: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.
In ES5/6 JavaScript we add the token string to the injection parameters array.
Alternatively, when using the ES5 convenience class API we can create a token with the
`Inject` method and add that to the constructor array in the annotations.
+makeTabs(`
cb-ts-to-js/ts/app/hero-di-inject.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero-di-inject.component.es6,
cb-ts-to-js/js-es6/app/hero-di-inject.component.es6,
cb-ts-to-js/js/app/hero-di-inject.component.js,
cb-ts-to-js/js/app/hero-di-inject.component.js
`,`
,
,
,
parameters,
ctor
`,`
Typescript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript,
ES5 JavaScript with Class API
`)
:marked
### Additional Injection Decorators
We can attach additional decorators to constructor parameters to qualify the injection behavior.
We can mark optional dependencies with the [`@Optional`](../api/core/index/Optional-decorator.html),
inject host element attributes with [`@Attribute`](../api/core/index/Attribute-interface.html),
inject content child queries with [`@ContentChild`](../api/core/index/ContentChild-decorator.html)
and inject view child queries with [`@ViewChild`](../api/core/index/ViewChild-decorator.html)).
In ES6 JavaScript we just add the extra decorators to the nested injection parameters array.
To achieve the same effect in ES5 JavaScript, use a nested array with the constructor
array notation in which the injection information precedes the constructor function itself.
We can apply other additional parameter decorators such as
[`@Host`](../api/core/index/Host-decorator.html) and
[`@SkipSelf`](../api/core/index/SkipSelf-decorator.html) in the same way -
by adding `new ng.core.Host()` or `ng.core.SkipSelf()` in the
parameters array.
+makeTabs(`
cb-ts-to-js/ts/app/hero-di-inject-additional.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero-di-inject-additional.component.es6,
cb-ts-to-js/js-es6/app/hero-di-inject-additional.component.es6,
cb-ts-to-js/js/app/hero-di-inject-additional.component.js
`,`
`,`
Typescript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
a(id="host-query-metadata")
.l-main-section
:marked
## Host and Query Metadata
### Host Decorators
In Typescript and ES6 with decorators we can use host property decorators to bind a host
element to a component or directive.
The [`@HostBinding`](../api/core/index/HostBinding-interface.html) decorator
binds host element properties to component data properties.
The [`@HostListener`](../api/core/index/HostListener-interface.html) decorator binds
host element events to component event handlers.
When using ES5/6 we add a `host` attribute to the component metadata to achieve the
same effect as `@HostBinding` and `@HostListener`.
The `host` value is an object whose properties are host property and listener bindings:
* Each key follows regular Angular binding syntax: `[property]` for host bindings
or `(event)` for host listeners.
* Each value identifies the corresponding component property or method.
+makeTabs(`
cb-ts-to-js/ts/app/heroes-bindings.component.ts,
cb-ts-to-js/js-es6-decorators/app/heroes-bindings.component.es6,
cb-ts-to-js/js-es6/app/heroes-bindings.component.es6,
cb-ts-to-js/js/app/heroes-bindings.component.js
`,`
`,`
Typescript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
.alert.is-helpful
:marked
In TypeScript and ES6 with decorators we can also use the `queries` metadata
instead of the `@ViewChild` and `@ContentChild` property decorators.
:marked
### Query Decorators
There are several property decorators for querying the descendants of
a component or directive.
The [`@ViewChild`](../api/core/index/ViewChild-decorator.html) and
[`@ViewChildren`](../api/core/index/ViewChildren-decorator.html) property decorators
allow a component to query instances of other components that are used in
its view.
In ES5/6 JavaScript 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`.
+makeTabs(`
cb-ts-to-js/ts/app/heroes-queries.component.ts,
cb-ts-to-js/js-es6-decorators/app/heroes-queries.component.es6,
cb-ts-to-js/js-es6/app/heroes-queries.component.es6,
cb-ts-to-js/js/app/heroes-queries.component.js
`,`
view,
view,
view,
view
`,`
Typescript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
:marked
The [`@ContentChild`](../api/core/index/ContentChild-decorator.html) and
[`@ContentChildren`](../api/core/index/ContentChildren-decorator.html) property decorators
allow a component to query instances of other components that have been projected
into its view from elsewhere.
They can be added in the same way as [`@ViewChild`](../api/core/index/ViewChild-decorator.html) and
[`@ViewChildren`](../api/core/index/ViewChildren-decorator.html).
+makeTabs(`
cb-ts-to-js/ts/app/heroes-queries.component.ts,
cb-ts-to-js/js-es6-decorators/app/heroes-queries.component.es6,
cb-ts-to-js/js-es6/app/heroes-queries.component.es6,
cb-ts-to-js/js/app/heroes-queries.component.js
`,`
content,
content,
content,
content
`,`
Typescript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
include ../../../ts/latest/cookbook/ts-to-js

View File

@ -58,7 +58,7 @@
"ts-to-js": {
"title": "TypeScript to JavaScript",
"intro": "Convert Angular TypeScript examples into ES5 JavaScript"
"intro": "Convert Angular TypeScript examples into ES6 and ES5 JavaScript"
},
"visual-studio-2015": {

View File

@ -1 +1,545 @@
include ../../../js/latest/cookbook/ts-to-js
include ../../../../_includes/_util-fns
:marked
Anything you can do with Angular in _TypeScript_, you can also do
in JavaScript. Translating from one language to the other is mostly a
matter of changing the way you organize your code and access Angular APIs.
_TypeScript_ is a popular language option for Angular development.
Most code examples on the Internet as well as on this site are written in _TypeScript_.
This cookbook contains recipes for translating _TypeScript_
code examples to _ES6_ and to _ES5_ so that JavaScript developers
can read and write Angular apps in their preferred dialect.
a#toc
:marked
## Table of contents
[_TypeScript_ to _ES6_ to _ES5_](#from-ts)
[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](#host-query-metadata)
[AoT compilation in _TypeScript_ Only](#aot)
**Run and compare the live <live-example name="cb-ts-to-js">_TypeScript_</live-example> and <live-example name="cb-ts-to-js" lang="js">JavaScript</live-example>
code shown in this cookbook.**
a#from-ts
.l-main-section
:marked
## _TypeScript_ to _ES6_ to _ES5_
_TypeScript_
<a href="https://www._TypeScript_lang.org" target="_blank" title='"TypeScript is a typed, superset of JavaScript"'>is a typed superset of _ES6 JavaScript_</a>.
&nbsp; _ES6 JavaScript_ is a superset of _ES5 JavaScript_. &nbsp; _ES5_ is the kind of JavaScript that runs natively in all modern browsers.
The transformation of _TypeScript_ code all the way down to _ES5_ code can be seen as "shedding" features.
The downgrade progression is
* _TypeScript_ to _ES6-with-decorators_
* _ES6-with-decorators_ to _ES6-without-decorators_ ("_plain ES6_")
* _ES6-without-decorators_ to _ES5_
When translating from _TypeScript_ to _ES6-with-decorators_, remove
[class property access modifiers](http://www._TypeScript_lang.org/docs/handbook/classes.html#public-private-and-protected-modifiers)
such as `public` and `private`.
Remove most of the
[type annotations](https://www._TypeScript_lang.org/docs/handbook/basic-types.html),
such as `string` and `boolean`
but **keep type annotations used for dependency injection**.
From _ES6-with-decorators_ to _plain ES6_, remove all
[decorators](https://www._TypeScript_lang.org/docs/handbook/decorators.html)
and the remaining type annotations.
You must declare properties in the class constructor (`this.title = '...'`) rather than in the body of the class.
Finally, from _plain ES6_ to _ES5_, the main missing features are `import`
statements and `class` declarations.
For _plain ES6_ transpilation you can _start_ with a setup similar to the
[_TypeScript_ quickstart](https://github.com/angular/quickstart) and adjust the application code accordingly.
Transpile with [Babel](https://babeljs.io/) using the `es2015` preset.
To use decorators and annotations with Babel, install the
[`angular2`](https://github.com/shuhei/babel-plugin-angular2-annotations) preset as well.
a#modularity
.l-main-section
:marked
## Importing and Exporting
### Importing Angular Code
In both _TypeScript_ and _ES6_, you import Angular classes, functions, and other members with _ES6_ `import` statements.
In _ES5_, you access the Angular entities of the [the Angular packages](../glossary.html#!#scoped-package),
through the global `ng` object.
Everything you would have imported from `@angular` is a nested member of this `ng` object:
+makeTabs(`
cb-ts-to-js/ts/app/main.ts,
cb-ts-to-js/js-es6-decorators/app/main.es6,
cb-ts-to-js/js-es6/app/main.es6,
cb-ts-to-js/js/app/main.js
`,`
ng2import,
ng2import,
ng2import,
ng2import
`,`
TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
:marked
### Importing and 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 the host web page, `index.html`.
Each code file can make selected entities available to other files via the shared global `window` scope.
But this is widely thought to be a bad practice.
Instead, you should add one application namespace object (such as `app`) to `window`.
Then attach everything you need to share to that namespace object.
You should also wrap your code in an
[Immediately Invoked Function Expression (IIFE)](https://en.wikipedia.org/wiki/Immediately-invoked_function_expression).
These practices together help you avoid polluting the global scope.
+makeTabs(`
cb-ts-to-js/ts/app/hero.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero.component.es6,
cb-ts-to-js/js-es6/app/hero.component.es6,
cb-ts-to-js/js/app/hero.component.js
`,`
appexport,
appexport,
appexport,
appexport
`,`
TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
:marked
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 in other files.
Note that the order of `<script>` tags on the page is often significant.
You must load a file that defines a shared member before a file that uses that member.
+makeTabs(`
cb-ts-to-js/ts/app/main.ts,
cb-ts-to-js/js-es6-decorators/app/main.es6,
cb-ts-to-js/js-es6/app/main.es6,
cb-ts-to-js/js/app/main.js
`,`
appimport,
appimport,
appimport,
appimport
`,`
TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)(format='.')
.alert.is-helpful
:marked
Alternatively, you can use a module loader such as Webpack or
Browserify in an Angular JavaScript project. In such a project, you would
use _CommonJS_ modules and the `require` function to load Angular framework code.
Then use `module.exports` and `require` to export and import application code.
a#class-metadata
.l-main-section
:marked
## Classes and Class Metadata
### Classes
Most Angular _TypeScript_ and _ES6_ code is written as classes.
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.
This works with Angular as well as classes do.
+makeTabs(`
cb-ts-to-js/ts/app/hero.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero.component.es6,
cb-ts-to-js/js-es6/app/hero.component.es6,
cb-ts-to-js/js/app/hero.component.js
`,`
class,
class,
class,
constructorproto
`,`
TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
:marked
### Metadata
When writing in _TypeScript_ or _ES6-with-decorators_,
provide configuration and metadata by adorning a class with one or more *decorators*.
For example, you supply metadata to a component class by preceding its definition with a
[`@Component`](../api/core/index/Component-decorator.html) decorator.
In _plain ES6_, you provide metadata by attaching an `annotations` array to the _class_.
Each item in the array corresponds to a decorator property value.
In _ES5_, you also provide an `annotations` array but you attach it to the _constructor function_ rather than a class.
See these variations side-by-side:
+makeTabs(`
cb-ts-to-js/ts/app/hero.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero.component.es6,
cb-ts-to-js/js-es6/app/hero.component.es6,
cb-ts-to-js/js/app/hero.component.js
`,`
metadata,
metadata,
metadata,
metadata
`,`
TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
:marked
***Angular class API***
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 put the metadata first,
as it would be if you wrote in _TypeScript_ or _ES6-with-decorators_.
Set a component variable 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 component class API next to the annotated function version for comparison:
+makeTabs(`
cb-ts-to-js/js/app/hero-dsl.component.js,
cb-ts-to-js/js/app/hero.component.js
`,`
component,
metadata
`,`
ES5 JavaScript with Class API,
ES5 JavaScript
`)
:marked
There are similar APIs for other decorated classes.
You can define a directive with `ng.core.Directive`:
code-example.
var MyDirective = ng.core.Directive({
selector: '[myDirective]'
}).Class({
...
});
:marked
and a pipe with `ng.core.Pipe`:
code-example.
var MyPipe = ng.core.Pipe({
name: 'myPipe'
}).Class({
...
});
: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.
_TypeScript_ interfaces are purely for developer convenience and are not used by Angular at runtime.
This means that in _ES5_/_ES6_ JavaScript code you don't need to substitute anything for interfaces.
Just implement the methods.
+makeTabs(`
cb-ts-to-js/ts/app/hero-lifecycle.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero-lifecycle.component.es6,
cb-ts-to-js/js-es6/app/hero-lifecycle.component.es6,
cb-ts-to-js/js/app/hero-lifecycle.component.js
`,`
`,`
TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
a#property-metadata
.l-main-section
:marked
## Input and Output Metadata
### Input and Output Decorators
In _TypeScript_ and _ES6_ with decorators, property decorators are often used to provide additional
metadata for components and directives.
For [inputs and outputs](../guide/template-syntax.html#inputs-outputs), you use `@Input` and
`@Output` property decorators.
Specify input and output binding names if you want the public-facing names to differ
from the class property names.
There is no equivalent of a property decorator in _ES5_/_ES6_ JavaScript.
Instead, you add comparable information to the `Component` (or `Directive`) metadata.
In this example, you add `inputs` and `outputs` array attributes containing the input and
output property names.
If you need a binding name that is different from the property itself, use the
`propertyName: bindingName` syntax.
+makeTabs(`
cb-ts-to-js/ts/app/hero-io.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero-io.component.es6,
cb-ts-to-js/js-es6/app/hero-io.component.es6,
cb-ts-to-js/js/app/hero-io.component.js
`,`
`,`
TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
.l-main-section
:marked
## Dependency Injection
### Injection by Type
Angular can often use _TypeScript_ type information to determine what needs to be injected.
_ES6_ with decorators can also make use of type information.
Since no type information is available in _ES5_/_ES6_ JavaScript, you must identify "injectables" in
some other way.
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.
In _ES6_ the decorators need to be inside a nested array.
When writing in the _ES5_ class convenience API, you can supply the parameter tokens by wrapping
the constructor in an array.
+makeTabs(`
cb-ts-to-js/ts/app/hero-di.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero-di.component.es6,
cb-ts-to-js/js-es6/app/hero-di.component.es6,
cb-ts-to-js/js/app/hero-di.component.js,
cb-ts-to-js/js/app/hero-di-inline.component.js
`,`
`,`
TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript,
ES5 JavaScript with Class API
`)
:marked
### Injection with the @Inject decorator
When the thing being injected doesn't correspond directly to a type, you use the
`@Inject()` decorator to supply the injection token.
In this example, you are injecting a string identified by the "heroName" token.
In _ES5_/_ES6_ JavaScript you add the token string to the injection parameters array.
Alternatively, when using the _ES5_ convenience class API you can create a token with the
`Inject` method and add that to the constructor array in the annotations.
+makeTabs(`
cb-ts-to-js/ts/app/hero-di-inject.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero-di-inject.component.es6,
cb-ts-to-js/js-es6/app/hero-di-inject.component.es6,
cb-ts-to-js/js/app/hero-di-inject.component.js,
cb-ts-to-js/js/app/hero-di-inject.component.js
`,`
,
,
,
parameters,
ctor
`,`
TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript,
ES5 JavaScript with Class API
`)
:marked
### Additional Injection Decorators
You can attach additional decorators to constructor parameters to qualify the injection behavior.
You can mark optional dependencies with the [`@Optional`](../api/core/index/Optional-decorator.html),
inject host element attributes with [`@Attribute`](../api/core/index/Attribute-interface.html),
inject content child queries with [`@ContentChild`](../api/core/index/ContentChild-decorator.html)
and inject view child queries with [`@ViewChild`](../api/core/index/ViewChild-decorator.html)).
In ES6 JavaScript you just add the extra decorators to the nested injection parameters array.
To achieve the same effect in _ES5_ JavaScript, use a nested array with the constructor
array notation in which the injection information precedes the constructor function itself.
You can apply other additional parameter decorators such as
[`@Host`](../api/core/index/Host-decorator.html) and
[`@SkipSelf`](../api/core/index/SkipSelf-decorator.html) in the same way -
by adding `new ng.core.Host()` or `ng.core.SkipSelf()` in the
parameters array.
+makeTabs(`
cb-ts-to-js/ts/app/hero-di-inject-additional.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero-di-inject-additional.component.es6,
cb-ts-to-js/js-es6/app/hero-di-inject-additional.component.es6,
cb-ts-to-js/js/app/hero-di-inject-additional.component.js
`,`
`,`
TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
a#host-query-metadata
.l-main-section
:marked
## Host and Query Metadata
### Host Decorators
In _TypeScript_ and _ES6-with-decorators_ you can use host property decorators to bind a host
element to a component or directive.
The [`@HostBinding`](../api/core/index/HostBinding-interface.html) decorator
binds host element properties to component data properties.
The [`@HostListener`](../api/core/index/HostListener-interface.html) decorator binds
host element events to component event handlers.
When using _ES5_/_ES6_, add a `host` attribute to the component metadata to achieve the
same effect as `@HostBinding` and `@HostListener`.
The `host` value is an object whose properties are host property and listener bindings:
* Each key follows regular Angular binding syntax: `[property]` for host bindings
or `(event)` for host listeners.
* Each value identifies the corresponding component property or method.
+makeTabs(`
cb-ts-to-js/ts/app/heroes-bindings.component.ts,
cb-ts-to-js/js-es6-decorators/app/heroes-bindings.component.es6,
cb-ts-to-js/js-es6/app/heroes-bindings.component.es6,
cb-ts-to-js/js/app/heroes-bindings.component.js
`,`
`,`
TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
.alert.is-helpful
:marked
In _TypeScript_ and _ES6-with-decorators_ you can also use the `queries` metadata
instead of the `@ViewChild` and `@ContentChild` property decorators.
:marked
### Query Decorators
There are several property decorators for querying the descendants of
a component or directive.
The [`@ViewChild`](../api/core/index/ViewChild-decorator.html) and
[`@ViewChildren`](../api/core/index/ViewChildren-decorator.html) property decorators
allow a component to query instances of other components that are used in
its view.
In _ES5_/_ES6_ JavaScript you 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`.
+makeTabs(`
cb-ts-to-js/ts/app/heroes-queries.component.ts,
cb-ts-to-js/js-es6-decorators/app/heroes-queries.component.es6,
cb-ts-to-js/js-es6/app/heroes-queries.component.es6,
cb-ts-to-js/js/app/heroes-queries.component.js
`,`
view,
view,
view,
view
`,`
TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
:marked
The [`@ContentChild`](../api/core/index/ContentChild-decorator.html) and
[`@ContentChildren`](../api/core/index/ContentChildren-decorator.html) property decorators
allow a component to query instances of other components that have been projected
into its view from elsewhere.
They can be added in the same way as [`@ViewChild`](../api/core/index/ViewChild-decorator.html) and
[`@ViewChildren`](../api/core/index/ViewChildren-decorator.html).
+makeTabs(`
cb-ts-to-js/ts/app/heroes-queries.component.ts,
cb-ts-to-js/js-es6-decorators/app/heroes-queries.component.es6,
cb-ts-to-js/js-es6/app/heroes-queries.component.es6,
cb-ts-to-js/js/app/heroes-queries.component.js
`,`
content,
content,
content,
content
`,`
TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
a#aot
.l-main-section
:marked
## AoT Compilation in _TypeScript_ only
Angular offers two modes of template compilation, JiT (_Just-in-Time_) and
[AoT (_Ahead-of-Time_)](aot-compiler.html).
Currently the AoT compiler only works with _TypeScript_ applications because, in part, it generates
_TypeScript_ files as an intermediate result.
**AoT is not an option for pure JavaScript applications** at this time.

View File

@ -7,6 +7,12 @@ block includes
The Angular documentation is a living document with continuous improvements.
This log calls attention to recent significant changes.
## ES6 described in "TypeScript to JavaScript" (2016-11-03)
The updated "[TypeScript to JavaScript](../cookbook/ts-to-js.html)" cookbook
now explains how to write apps in ES6/7
by translating the common idioms in the TypeScript documentation examples
(and elsewhere on the web) to ES6/7 and ES5.
## Sync with Angular v.2.1.1 (2016-10-21)
Docs and code samples updated and tested with Angular v.2.1.0