622 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			622 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| # 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.
 |