forked from angular/angular.io
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathts-to-js.jade
669 lines (546 loc) · 26.5 KB
/
ts-to-js.jade
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
include ../../../../_includes/_util-fns
:marked
Anything you can do with Angular in _TypeScript_, you can also do
in JavaScript. Translating from one language to the other is mostly a
matter of changing the way you organize your code and access Angular APIs.
_TypeScript_ is a popular language option for Angular development.
Most code examples on the Internet as well as on this site are written in _TypeScript_.
This cookbook contains recipes for translating _TypeScript_
code examples to _ES6_ and to _ES5_ so that JavaScript developers
can read and write Angular apps in their preferred dialect.
a#toc
:marked
## Table of contents
[_TypeScript_ to _ES6_ to _ES5_](#from-ts)<br>
[Modularity: imports and exports](#modularity)<br>
[Classes and Class Metadata](#class-metadata)<br>
[_ES5_ DSL](#dsl)<br>
[Interfaces](#interfaces)<br>
[Input and Output Metadata](#io-decorators)<br>
[Dependency Injection](#dependency-injection)<br>
[Host Binding](#host-binding)<br>
[View and Child Decorators](#view-child-decorators)<br>
[AoT compilation in _TypeScript_ Only](#aot)<br>
**Run and compare the live <live-example name="cb-ts-to-js">_TypeScript_</live-example> and <live-example name="cb-ts-to-js" lang="js">JavaScript</live-example>
code shown in this cookbook.**
a#from-ts
.l-main-section
:marked
## _TypeScript_ to _ES6_ to _ES5_
_TypeScript_
<a href="https://www.typescriptlang.org" target="_blank" title='"TypeScript is a typed, superset of JavaScript"'>is a typed superset of _ES6 JavaScript_</a>.
_ES6 JavaScript_ is a superset of _ES5 JavaScript_. _ES5_ is the kind of JavaScript that runs natively in all modern browsers.
The transformation of _TypeScript_ code all the way down to _ES5_ code can be seen as "shedding" features.
The downgrade progression is
* _TypeScript_ to _ES6-with-decorators_
* _ES6-with-decorators_ to _ES6-without-decorators_ ("_plain ES6_")
* _ES6-without-decorators_ to _ES5_
When translating from _TypeScript_ to _ES6-with-decorators_, remove
[class property access modifiers](http://www.typescriptlang.org/docs/handbook/classes.html#public-private-and-protected-modifiers)
such as `public` and `private`.
Remove most of the
[type declarations](https://www.typescriptlang.org/docs/handbook/basic-types.html),
such as `:string` and `:boolean`
but **keep the constructor parameter types which are used for dependency injection**.
From _ES6-with-decorators_ to _plain ES6_, remove all
[decorators](https://www.typescriptlang.org/docs/handbook/decorators.html)
and the remaining types.
You must declare properties in the class constructor (`this.title = '...'`) rather than in the body of the class.
Finally, from _plain ES6_ to _ES5_, the main missing features are `import`
statements and `class` declarations.
For _plain ES6_ transpilation you can _start_ with a setup similar to the
[_TypeScript_ quickstart](https://github.com/angular/quickstart) and adjust the application code accordingly.
Transpile with [Babel](https://babeljs.io/) using the `es2015` preset.
To use decorators and annotations with Babel, install the
[`angular2`](https://github.com/shuhei/babel-plugin-angular2-annotations) preset as well.
a#modularity
.l-main-section
:marked
## Importing and Exporting
### Importing Angular Code
In both _TypeScript_ and _ES6_, you import Angular classes, functions, and other members with _ES6_ `import` statements.
In _ES5_, you access the Angular entities of the [the Angular packages](../glossary.html#scoped-package)
through the global `ng` object.
Anything you can import from `@angular` is a nested member of this `ng` object:
+makeTabs(`
cb-ts-to-js/ts/app/app.module.ts,
cb-ts-to-js/js-es6-decorators/app/app.module.es6,
cb-ts-to-js/js-es6/app/app.module.es6,
cb-ts-to-js/js/app/app.module.js
`,
'ng2import,ng2import,ng2import,ng2import',
` TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)(format='.')
:marked
### Exporting Application Code
Each file in a _TypeScript_ or _ES6_ Angular application constitutes an _ES6_ module.
When you want to make something available to other modules, you `export` it.
_ES5_ lacks native support for modules.
In an Angular _ES5_ application, you load each file manually by adding a `<script>` tag to `index.html`.
.alert.is-important
:marked
The order of `<script>` tags is often significant.
You must load a file that defines a public JavaScript entity before a file that references that entity.
:marked
The best practice in _ES5_ is to create a form of modularity that avoids polluting the global scope.
Add one application namespace object such as `app` to the global `document`.
Then each code file "exports" public entities by attaching them to that namespace object, e.g., `app.HeroComponent`.
You could factor a large application into several sub-namespaces
which leads to "exports" along the lines of `app.heroQueries.HeroComponent`.
Every _ES5_ file should wrap code in an
[Immediately Invoked Function Expression (IIFE)](https://en.wikipedia.org/wiki/Immediately-invoked_function_expression)
to limit unintentional leaking of private symbols into the global scope.
Here is a `HeroComponent` as it might be defined and "exported" in each of the four language variants.
+makeTabs(`
cb-ts-to-js/ts/app/hero.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero.component.es6,
cb-ts-to-js/js-es6/app/hero.component.es6,
cb-ts-to-js/js/app/hero.component.js
`,
'appexport,appexport,appexport,appexport',
` TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
:marked
### Importing Application Code
In _TypeScript_ and _ES6_ apps, you `import` things that have been exported from other modules.
In _ES5_ you use the shared namespace object to access "exported" entities from other files.
+makeTabs(`
cb-ts-to-js/ts/app/app.module.ts,
cb-ts-to-js/js-es6-decorators/app/app.module.es6,
cb-ts-to-js/js-es6/app/app.module.es6,
cb-ts-to-js/js/app/app.module.js
`,
'appimport,appimport,appimport,appimport',
` TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)(format='.')
.alert.is-helpful
:marked
Alternatively, you can use a module loader such as Webpack or
Browserify in an Angular JavaScript project. In such a project, you would
use _CommonJS_ modules and the `require` function to load Angular framework code.
Then use `module.exports` and `require` to export and import application code.
a#class-metadata
.l-main-section
:marked
## Classes and Class Metadata
### Classes
Most Angular _TypeScript_ and _ES6_ code is written as classes.
Properties and method parameters of _TypeScript_ classes may be marked with the access modifiers
`private`, `internal`, and `public`.
Remove these modifiers when translating to JavaScript.
Most type declarations (e.g, `:string` and `:boolean`) should be removed when translating to JavaScript.
When translating to _ES6-with-decorators_, ***do not remove types from constructor parameters!***
Look for types in _TypeScript_ property declarations.
In general it is better to initialize such properties with default values because
many browser JavaScript engines can generate more performant code.
When _TypeScript_ code follows this same advice, it can infer the property types
and there is nothing to remove during translation.
In _ES6-without-decorators_, properties of classes must be assigned inside the constructor.
_ES5_ JavaScript has no classes.
Use the constructor function pattern instead, adding methods to the prototype.
+makeTabs(`
cb-ts-to-js/ts/app/hero.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero.component.es6,
cb-ts-to-js/js-es6/app/hero.component.es6,
cb-ts-to-js/js/app/hero.component.js
`,
'class,class,class,constructorproto',
` TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
:marked
### Metadata
When writing in _TypeScript_ or _ES6-with-decorators_,
provide configuration and metadata by adorning a class with one or more *decorators*.
For example, you supply metadata to a component class by preceding its definition with a
[`@Component`](../api/core/index/Component-decorator.html) decorator function whose
argument is an object literal with metadata properties.
In _plain ES6_, you provide metadata by attaching an `annotations` array to the _class_.
Each item in the array is a new instance of a metadata decorator created with a similar metadata object literal.
In _ES5_, you also provide an `annotations` array but you attach it to the _constructor function_ rather than to a class.
See these variations side-by-side:
+makeTabs(`
cb-ts-to-js/ts/app/hero.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero.component.es6,
cb-ts-to-js/js-es6/app/hero.component.es6,
cb-ts-to-js/js/app/hero.component.js
`,
'metadata,metadata,metadata,metadata',
` TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)
:marked
***External Template file***
A large component template is often kept in a separate template file.
+makeExample('cb-ts-to-js/ts/app/hero-title.component.html', '', 'app/hero-title.component.html')(format='.')
:marked
The component (`HeroTitleComponent` in this case) then references the template file in its metadata `templateUrl` property:
+makeTabs(`
cb-ts-to-js/ts/app/hero-title.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero-title.component.es6,
cb-ts-to-js/js-es6/app/hero-title.component.es6,
cb-ts-to-js/js/app/hero-title.component.js`,
'templateUrl, templateUrl, templateUrl, templateUrl',
`TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript
`)(format='.')
:marked
Note that the _TypeScript_ and both _ES6_ `templateUrl` properties identify the location of the template file _relative to the component module_.
All three metadata configurations specify the `moduleId` property
so that Angular can calculate the proper module address.
The _ES5_ approach shown here does not support modules and therefore there is no way to calculate a _module-relative URL_.
The `templateUrl` for the _ES5_ code must specify the _path from the project root_ and
omits the irrelevant `moduleId` property.
.l-sub-section
:marked
With the right tooling, the `moduleId` may not be needed in the other JavaScript dialects either.
But it's safest to provide it anyway.
a#dsl
.l-main-section
:marked
## _ES5_ DSL
This _ES5_ pattern of creating a constructor and annotating it with metadata is so common that Angular
provides a convenience API to make it a little more compact and locates the metadata above the constructor,
as you would if you wrote in _TypeScript_ or _ES6-with-decorators_.
This _API_ (_Application Programming Interface_) is commonly known as the _ES5 DSL_ (_Domain Specific Language_).
Set an application namespace property (e.g., `app.HeroDslComponent`) to the result of an `ng.core.Component` function call.
Pass the same metadata object to `ng.core.Component` as you did before.
Then chain a call to the `Class` method which takes an object defining the class constructor and instance methods.
Here is an example of the `HeroComponent`, re-written with the DSL,
next to the original _ES5_ version for comparison:
+makeTabs(`
cb-ts-to-js/js/app/hero.component.js,
cb-ts-to-js/js/app/hero.component.js
`,
'dsl,',
`
ES5 JavaScript with DSL,
ES5 JavaScript
`)
.callout.is-helpful
header Name the constructor
:marked
A **named** constructor displays clearly in the console log
if the component throws a runtime error.
An **unnamed** constructor displays as an anonymous function (e.g., `class0`)
which is impossible to find in the source code.
:marked
### Properties with getters and setters
_TypeScript_ and _ES6_ support with getters and setters.
Here's an example of a read-only _TypeScript_ property with a getter
that prepares a toggle-button label for the next clicked state:
+makeExample('cb-ts-to-js/ts/app/hero-queries.component.ts', 'defined-property', 'ts/app/hero-queries.component.ts')(format='.')
:marked
This _TypeScript_ "getter" property is transpiled to an _ES5_
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty"
target="_blank" title="Defined Properties">defined property</a>.
The _ES5 DSL_ does not support _defined properties_ directly
but you can still create them by extracting the "class" prototype and
adding the _defined property_ in raw JavaScript like this:
+makeExample('cb-ts-to-js/js/app/hero-queries.component.js', 'defined-property','js/app/hero-queries.component.ts')(format='.')
:marked
### DSL for other classes
There are similar DSLs for other decorated classes.
You can define a directive with `ng.core.Directive`:
code-example.
app.MyDirective = ng.core.Directive({
selector: '[myDirective]'
}).Class({
...
});
:marked
and a pipe with `ng.core.Pipe`:
code-example.
app.MyPipe = ng.core.Pipe({
name: 'myPipe'
}).Class({
...
});
a#interfaces
.l-main-section
:marked
## Interfaces
A _TypeScript_ interface helps ensure that a class implements the interface's members correctly.
We strongly recommend Angular interfaces where appropriate.
For example, the component class that implements the `ngOnInit` lifecycle hook method
should implement the `OnInit` interface.
_TypeScript_ interfaces exist for developer convenience and are not used by Angular at runtime.
They have no physical manifestation in the generated JavaScript code.
Just implement the methods and ignore interfaces when translating code samples from _TypeScript_ to JavaScript.
+makeTabs(`
cb-ts-to-js/ts/app/hero-lifecycle.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero-lifecycle.component.es6,
cb-ts-to-js/js-es6/app/hero-lifecycle.component.es6,
cb-ts-to-js/js/app/hero-lifecycle.component.js,
cb-ts-to-js/js/app/hero-lifecycle.component.js
`,
',,,,dsl',
` TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript,
ES5 JavaScript with DSL
`)
a#io-decorators
.l-main-section
:marked
## Input and Output Metadata
### Input and Output Decorators
In _TypeScript_ and _ES6-with-decorators_, you often add metadata to class _properties_ with _property decorators_.
For example, you apply [`@Input` and `@Output` property decorators](../guide/template-syntax.html#inputs-outputs)
to public class properties that will be the target of data binding expressions in parent components.
There is no equivalent of a property decorator in _ES5_ or _plain ES6_.
Fortunately, every property decorator has an equivalent representation in a class decorator metadata property.
A _TypeScript_ `@Input` property decorator can be represented by an item in the `Component` metadata's `inputs` array.
You already know how to add `Component` or `Directive` class metadata in _any_ JavaScript dialect so
there's nothing fundamentally new about adding another property.
But note that what would have been _separate_ `@Input` and `@Output` property decorators for each class property are
combined in the metadata `inputs` and `outputs` _arrays_.
+makeTabs(`
cb-ts-to-js/ts/app/confirm.component.ts,
cb-ts-to-js/js-es6-decorators/app/confirm.component.es6,
cb-ts-to-js/js-es6/app/confirm.component.es6,
cb-ts-to-js/js/app/confirm.component.js,
cb-ts-to-js/js/app/confirm.component.js
`,
',,,,dsl',
` TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript,
ES5 JavaScript with DSL
`)
:marked
In the previous example, one of the public-facing binding names (`cancelMsg`)
differs from the corresponding class property name (`notOkMsg`).
That's OK but you must tell Angular about it so that it can map an external binding of `cancelMsg`
to the component's `notOkMsg` property.
In _TypeScript_ and _ES6-with-decorators_,
you specify the special binding name in the argument to the property decorator.
In _ES5_ and _plain ES6_ code, convey this pairing with the `propertyName: bindingName` syntax in the class metadata.
.l-main-section
:marked
## Dependency Injection
Angular relies heavily on [Dependency Injection](../guide/dependency-injection.html) to provide services to the objects it creates.
When Angular creates a new component, directive, pipe or another service,
it sets the class constructor parameters to instances of services provided by an _Injector_.
The developer must tell Angular what to inject into each parameter.
### Injection by Class Type
The easiest and most popular technique in _TypeScript_ and _ES6-with-decorators_ is to set the constructor parameter type
to the class associated with the service to inject.
The _TypeScript_ transpiler writes parameter type information into the generated JavaScript.
Angular reads that information at runtime and locates the corresponding service in the appropriate _Injector_..
The _ES6-with-decorators_ transpiler does essentially the same thing using the same parameter-typing syntax.
_ES5_ and _plain ES6_ lack types so you must identify "injectables" by attaching a **`parameters`** array to the constructor function.
Each item in the array specifies the service's injection token.
As with _TypeScript_ the most popular token is a class,
or rather a _constructor function_ that represents a class in _ES5_ and _plain ES6_.
The format of the `parameters` array varies:
* _plain ES6_ — nest each constructor function in a sub-array.
* _ES5_ — simply list the constructor functions.
When writing with _ES5 DSL_, set the `Class.constructor` property to
an array whose first parameters are the injectable constructor functions and whose
last parameter is the class constructor itself.
This format should be familiar to Angular 1 developers.
+makeTabs(`
cb-ts-to-js/ts/app/hero-di.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero-di.component.es6,
cb-ts-to-js/js-es6/app/hero-di.component.es6,
cb-ts-to-js/js/app/hero-di.component.js,
cb-ts-to-js/js/app/hero-di.component.js
`,
',,,,dsl',
` TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript,
ES5 JavaScript with DSL
`)
:marked
### Injection with the @Inject decorator
Sometimes the dependency injection token isn't a class or constructor function.
In _TypeScript_ and _ES6-with-decorators_, you precede the class constructor parameter
by calling the `@Inject()` decorator with the injection token.
In the following example, the token is the string `'heroName'`.
The other JavaScript dialogs add a `parameters` array to the class contructor function.
Each item constains a new instance of `Inject('heroName')`:
* _plain ES6_ — each item is a new instance of `Inject(token)` in a sub-array.
* _ES5_ — simply list the string tokens.
When writing with _ES5 DSL_, set the `Class.constructor` property to a function definition
array as before. Create a `new ng.core.Inject(token)` for each parameter.
+makeTabs(`
cb-ts-to-js/ts/app/hero-di-inject.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero-di-inject.component.es6,
cb-ts-to-js/js-es6/app/hero-di-inject.component.es6,
cb-ts-to-js/js/app/hero-di-inject.component.js,
cb-ts-to-js/js/app/hero-di-inject.component.js
`,
',,,,dsl',
` TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript,
ES5 JavaScript with DSL
`)
:marked
### Additional Injection Decorators
You can qualify injection behavior with injection decorators from `@angular/core`.
In _TypeScript_ and _ES6-with-decorators_,
you precede the constructor parameters with injection qualifiers such as:
* [`@Optional`](../api/core/index/Optional-decorator.html) sets the parameter to `null` if the service is missing
* [`@Attribute`](../api/core/index/Attribute-interface.html) to inject a host element attribute value
* [`@ContentChild`](../api/core/index/ContentChild-decorator.html) to inject a content child
* [`@ViewChild`](../api/core/index/ViewChild-decorator.html) to inject a view child
* [`@Host`](../api/core/index/Host-decorator.html) to inject a service in this component or its host
* [`@SkipSelf`](../api/core/index/SkipSelf-decorator.html) to inject a service provided in an ancestor of this component
In _plain ES6_ and _ES5_, create an instance of the equivalent injection qualifier in a nested array within the `parameters` array.
For example, you'd write `new Optional()` in _plain ES6_ and `new ng.core.Optional()` in _ES5_.
When writing with _ES5 DSL_, set the `Class.constructor` property to a function definition
array as before. Use a nested array to define a parameter's complete injection specification.
+makeTabs(`
cb-ts-to-js/ts/app/hero-title.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero-title.component.es6,
cb-ts-to-js/js-es6/app/hero-title.component.es6,
cb-ts-to-js/js/app/hero-title.component.js,
cb-ts-to-js/js/app/hero-title.component.js
`,
',,,,dsl',
` TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript,
ES5 JavaScript with DSL
`)
.l-sub-section
:marked
In the example above, there is no provider for the `'titlePrefix'` token.
Without `Optional`, Angular would raise an error.
With `Optional`, Angular sets the constructor parameter to `null`
and the component displays the title without a prefix.
a#host-binding
.l-main-section
:marked
## Host Binding
Angular supports bindings to properties and events of the _host element_ which is the
element whose tag matches the component selector.
### Host Decorators
In _TypeScript_ and _ES6-with-decorators_, you can use host property decorators to bind a host
element to a component or directive.
The [`@HostBinding`](../api/core/index/HostBinding-interface.html) decorator
binds host element properties to component data properties.
The [`@HostListener`](../api/core/index/HostListener-interface.html) decorator binds
host element events to component event handlers.
In _plain ES6_ or _ES5_, add a `host` attribute to the component metadata to achieve the
same effect as `@HostBinding` and `@HostListener`.
The `host` value is an object whose properties are host property and listener bindings:
* Each key follows regular Angular binding syntax: `[property]` for host bindings
or `(event)` for host listeners.
* Each value identifies the corresponding component property or method.
+makeTabs(`
cb-ts-to-js/ts/app/hero-host.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero-host.component.es6,
cb-ts-to-js/js-es6/app/hero-host.component.es6,
cb-ts-to-js/js/app/hero-host.component.js,
cb-ts-to-js/js/app/hero-host.component.js
`,
',,,,dsl',
` TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript,
ES5 JavaScript with DSL
`)
:marked
### Host Metadata
Some developers prefer to specify host properties and listeners
in the component metadata.
They'd _rather_ do it the way you _must_ do it _ES5_ and _plain ES6_.
The following re-implementation of the `HeroComponent` reminds us that _any property metadata decorator_
can be expressed as component or directive metadata in both _TypeScript_ and _ES6-with-decorators_.
These particular _TypeScript_ and _ES6_ code snippets happen to be identical.
+makeTabs(`
cb-ts-to-js/ts/app/hero-host-meta.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero-host-meta.component.es6
`,
'',
` TypeScript,
ES6 JavaScript with decorators
`)
a#view-child-decorators
.l-main-section
:marked
### View and Child Decorators
Several _property_ decorators query a component's nested view and content components.
.l-sub-section
:marked
_View_ children are associated with element tags that appear _within_ the component's template.
_Content_ children are associated with elements that appear _between_ the component's element tags;
they are projected into an `<ng-content>` slot in the component's template.
:marked
The [`@ViewChild`](../api/core/index/ViewChild-decorator.html) and
[`@ViewChildren`](../api/core/index/ViewChildren-decorator.html) property decorators
allow a component to query instances of other components that are used in
its view.
In _ES5_ and _ES6_, you access a component's view children by adding a `queries` property to the component metadata.
The `queries` property value is a hash map.
* each _key_ is the name of a component property that will hold the view child or children.
* each _value_ is a new instance of either `ViewChild` or `ViewChildren`.
+makeTabs(`
cb-ts-to-js/ts/app/hero-queries.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero-queries.component.es6,
cb-ts-to-js/js-es6/app/hero-queries.component.es6,
cb-ts-to-js/js/app/hero-queries.component.js
`,
'view, view, view, view',
` TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript with DSL
`)
:marked
The [`@ContentChild`](../api/core/index/ContentChild-decorator.html) and
[`@ContentChildren`](../api/core/index/ContentChildren-decorator.html) property decorators
allow a component to query instances of other components that have been projected
into its view from elsewhere.
They can be added in the same way as [`@ViewChild`](../api/core/index/ViewChild-decorator.html) and
[`@ViewChildren`](../api/core/index/ViewChildren-decorator.html).
+makeTabs(`
cb-ts-to-js/ts/app/hero-queries.component.ts,
cb-ts-to-js/js-es6-decorators/app/hero-queries.component.es6,
cb-ts-to-js/js-es6/app/hero-queries.component.es6,
cb-ts-to-js/js/app/hero-queries.component.js
`,
'content, content, content, content',
` TypeScript,
ES6 JavaScript with decorators,
ES6 JavaScript,
ES5 JavaScript with DSL
`)
.alert.is-helpful
:marked
In _TypeScript_ and _ES6-with-decorators_ you can also use the `queries` metadata
instead of the `@ViewChild` and `@ContentChild` property decorators.
a#aot
.l-main-section
:marked
## AoT Compilation in _TypeScript_ only
Angular offers two modes of template compilation, JiT (_Just-in-Time_) and
[AoT (_Ahead-of-Time_)](aot-compiler.html).
Currently the AoT compiler only works with _TypeScript_ applications because, in part, it generates
_TypeScript_ files as an intermediate result.
**AoT is not an option for pure JavaScript applications** at this time.