Permalink
Browse files

feat(compiler): set `enableLegacyTemplate` to false by default (#18756)

BREAKING CHANGE: the compiler option `enableLegacyTemplate` is now disabled by default as the `<template>` element has been deprecated since v4. Use `<ng-template>` instead. The option `enableLegacyTemplate` and the `<template>` element will both be removed in Angular v6.
PR Close #18756
  • Loading branch information...
ocombe authored and jasonaden committed Aug 17, 2017
1 parent fcadeb2 commit 56238fe94e5022f2a4c450ba9a23022bfff81eb9
@@ -92,22 +92,22 @@ <h4>#3 &lt;ng-container&gt; and &lt;p&gt;</h4>
</div>
<div>
The <code>hero.id</code> in the &lt;template *ngIf&gt; disappears:
The <code>hero.id</code> in the &lt;ng-template *ngIf&gt; disappears:
<p>
<template *ngIf="showId">
<ng-template *ngIf="showId">
Id: ({{hero.id}})
</template>
</ng-template>
Name: {{hero.name}}
</p>
</div>
<div>
The <code>hero.id</code> in the &lt;template [ngIf]&gt;
The <code>hero.id</code> in the &lt;ng-template [ngIf]&gt;
is unaffected by the <span>p-span</span> CSS:
<p>
<template [ngIf]="showId">
<ng-template [ngIf]="showId">
Id: ({{hero.id}})
</template>
</ng-template>
Name: {{hero.name}}
</p>
</div>
@@ -18,9 +18,9 @@ describe('Structural Directives', function () {
expect(allLis.get(0).getText()).toEqual('Mr. Nice');
});
it('ngSwitch have three <happy-hero> instances', function () {
it('ngSwitch have two <happy-hero> instances', function () {
const happyHeroEls = element.all(by.tagName('happy-hero'));
expect(happyHeroEls.count()).toEqual(3);
expect(happyHeroEls.count()).toEqual(2);
});
it('should toggle *ngIf="hero" with a button', function () {
@@ -55,11 +55,6 @@ <h4>NgIf with template</h4>
</ng-template>
<!-- #enddocregion ngif-template -->
<p>template attribute</p>
<!-- #docregion ngif-template-attr -->
<div template="ngIf hero">{{hero.name}}</div>
<!-- #enddocregion ngif-template-attr -->
<hr>
<h2 id="ng-container">&lt;ng-container&gt;</h2>
@@ -131,14 +126,7 @@ <h2 id="ngFor">NgFor</h2>
</div>
<!--#enddocregion inside-ngfor -->
<p class="code">&lt;div template="ngFor let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd"&gt;</p>
<!--#docregion inside-ngfor -->
<div template="ngFor let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd">
({{i}}) {{hero.name}}
</div>
<!--#enddocregion inside-ngfor -->
<p class="code">&lt;template ngFor let-hero [ngForOf]="heroes" let-i="index" let-odd="odd" [ngForTrackBy]="trackById"&gt;</p>
<p class="code">&lt;ng-template ngFor let-hero [ngForOf]="heroes" let-i="index" let-odd="odd" [ngForTrackBy]="trackById"/&gt;</p>
<!--#docregion inside-ngfor -->
<ng-template ngFor let-hero [ngForOf]="heroes" let-i="index" let-odd="odd" [ngForTrackBy]="trackById">
<div [class.odd]="odd">({{i}}) {{hero.name}}</div>
@@ -169,16 +157,6 @@ <h4>NgSwitch</h4>
</div>
<!-- #enddocregion built-in, ngswitch -->
<h4>NgSwitch with <i>template</i> attribute</h4>
<!-- #docregion ngswitch-template-attr -->
<div [ngSwitch]="hero?.emotion">
<happy-hero template="ngSwitchCase 'happy'" [hero]="hero"></happy-hero>
<sad-hero template="ngSwitchCase 'sad'" [hero]="hero"></sad-hero>
<confused-hero template="ngSwitchCase 'confused'" [hero]="hero"></confused-hero>
<unknown-hero template="ngSwitchDefault" [hero]="hero"></unknown-hero>
</div>
<!-- #enddocregion ngswitch-template-attr -->
<h4>NgSwitch with &lt;ng-template&gt;</h4>
<!-- #docregion ngswitch-template -->
<div [ngSwitch]="hero?.emotion">
@@ -199,7 +177,7 @@ <h4>NgSwitch with &lt;ng-template&gt;</h4>
<hr>
<h2>&lt;template&gt;</h2>
<h2>&lt;ng-template&gt;</h2>
<!-- #docregion template-tag -->
<p>Hip!</p>
<ng-template>
@@ -238,13 +216,13 @@ <h4>UnlessDirective with template</h4>
<p *myUnless="condition">Show this sentence unless the condition is true.</p>
<!-- #enddocregion myUnless-1 -->
<p template="myUnless condition" class="code unless">
(A) &lt;p template="myUnless condition" class="code unless"&gt;
<p *myUnless="condition" class="code unless">
(A) &lt;p *myUnless="condition" class="code unless"&gt;
</p>
<ng-template [myUnless]="condition">
<p class="code unless">
(A) &lt;template [myUnless]="condition"&gt;
(A) &lt;ng-template [myUnless]="condition"&gt;
</p>
</ng-template>
@@ -19,8 +19,7 @@ import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
* ### Syntax
*
* - `<div *myUnless="condition">...</div>`
* - `<div template="myUnless condition">...</div>`
* - `<template [myUnless]="condition"><div>...</div></template>`
* - `<ng-template [myUnless]="condition"><div>...</div></ng-template>`
*
// #docregion no-docs
*/
@@ -78,11 +78,11 @@ <h3>
<p>Template input variable expression context (let hero)</p>
<!-- template hides the following; plenty of examples later -->
<template>
<ng-template>
<!-- #docregion context-var -->
<div *ngFor="let hero of heroes">{{hero.name}}</div>
<!-- #enddocregion context-var -->
</template>
</ng-template>
<p>Template reference variable expression context (#heroInput)</p>
<div (keyup)="0" class="context">
@@ -208,17 +208,7 @@ Here is `*ngIf` displaying the hero's name if `hero` exists.
The asterisk is "syntactic sugar" for something a bit more complicated.
Internally, Angular desugars it in two stages.
First, it translates the `*ngIf="..."` into a template _attribute_, `template="ngIf ..."`,&nbsp; like this.
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngif-template-attr)" region="ngif-template-attr">
</code-example>
Then it translates the template _attribute_ into a `<ng-template>` _element_, wrapped around the host element, like this.
Internally, Angular translates the `*ngIf` _attribute_ into a `<ng-template>` _element_, wrapped around the host element, like this.
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngif-template)" region="ngif-template">
@@ -230,8 +220,7 @@ Then it translates the template _attribute_ into a `<ng-template>` _element_, wr
* The `*ngIf` directive moved to the `<ng-template>` element where it became a property binding,`[ngIf]`.
* The rest of the `<div>`, including its class attribute, moved inside the `<ng-template>` element.
None of these forms are actually rendered.
Only the finished product ends up in the DOM.
The first form is not actually rendered, only the finished product ends up in the DOM.
<figure>
@@ -252,10 +241,9 @@ The [`NgFor`](guide/structural-directives#ngFor) and [`NgSwitch...`](guide/struc
## Inside _*ngFor_
Angular transforms the `*ngFor` in similar fashion from asterisk (*) syntax through
template _attribute_ to `<ng-template>` _element_.
Angular transforms the `*ngFor` in similar fashion from asterisk (*) syntax to `<ng-template>` _element_.
Here's a full-featured application of `NgFor`, written all three ways:
Here's a full-featured application of `NgFor`, written both ways:
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (inside-ngfor)" region="inside-ngfor">
@@ -415,16 +403,7 @@ The `<unknown-hero>` is the host element for the `*ngSwitchDefault`.
As with other structural directives, the `NgSwitchCase` and `NgSwitchDefault`
can be desugared into the template _attribute_ form.
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngswitch-template-attr)" region="ngswitch-template-attr">
</code-example>
That, in turn, can be desugared into the `<ng-template>` element form.
can be desugared into the `<ng-template>` element form.
<code-example path="structural-directives/src/app/app.component.html" linenums="false" title="src/app/app.component.html (ngswitch-template)" region="ngswitch-template">
@@ -438,7 +417,7 @@ That, in turn, can be desugared into the `<ng-template>` element form.
## Prefer the asterisk (*) syntax.
The asterisk (*) syntax is more clear than the other desugared forms.
The asterisk (*) syntax is more clear than the desugared form.
Use [&lt;ng-container&gt;](guide/structural-directives#ng-container) when there's no single element
to host the directive.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
View
Binary file not shown.
@@ -79,7 +79,6 @@ export class NgForOfContext<T> {
* ### Syntax
*
* - `<li *ngFor="let item of items; index as i; trackBy: trackByFn">...</li>`
* - `<li template="ngFor let item of items; index as i; trackBy: trackByFn">...</li>`
*
* With `<ng-template>` element:
*
@@ -75,7 +75,6 @@ import {Directive, EmbeddedViewRef, Input, TemplateRef, ViewContainerRef} from '
*
* Simple form:
* - `<div *ngIf="condition">...</div>`
* - `<div template="ngIf condition">...</div>`
* - `<ng-template [ngIf]="condition"><div>...</div></ng-template>`
*
* Form with an else block:
@@ -101,7 +101,7 @@ export class CodeGenerator {
translations: transContent,
i18nFormat: cliOptions.i18nFormat || undefined,
locale: cliOptions.locale || undefined, missingTranslation,
enableLegacyTemplate: options.enableLegacyTemplate !== false,
enableLegacyTemplate: options.enableLegacyTemplate === true,
enableSummariesForJit: options.enableSummariesForJit !== false,
preserveWhitespaces: options.preserveWhitespaces,
});
@@ -90,7 +90,7 @@ export interface CompilerOptions extends ts.CompilerOptions {
// Print extra information while running the compiler
trace?: boolean;
// Whether to enable support for <template> and the template attribute (true by default)
// Whether to enable support for <template> and the template attribute (false by default)
enableLegacyTemplate?: boolean;
// Whether to enable lowering expressions lambdas and expressions in a reference value
@@ -65,7 +65,7 @@ export function createAotCompiler(compilerHost: AotCompilerHost, options: AotCom
const config = new CompilerConfig({
defaultEncapsulation: ViewEncapsulation.Emulated,
useJit: false,
enableLegacyTemplate: options.enableLegacyTemplate !== false,
enableLegacyTemplate: options.enableLegacyTemplate === true,
missingTranslation: options.missingTranslation,
preserveWhitespaces: options.preserveWhitespaces,
});
@@ -36,7 +36,7 @@ export class CompilerConfig {
this.useJit = !!useJit;
this.jitDevMode = !!jitDevMode;
this.missingTranslation = missingTranslation || null;
this.enableLegacyTemplate = enableLegacyTemplate !== false;
this.enableLegacyTemplate = enableLegacyTemplate === true;
this.preserveWhitespaces = preserveWhitespacesDefault(noUndefined(preserveWhitespaces));
}
}
@@ -121,16 +121,19 @@ export function main() {
schemas?: SchemaMetadata[], preserveWhitespaces?: boolean) => TemplateAst[];
let console: ArrayConsole;
function commonBeforeEach() {
function configureCompiler() {
console = new ArrayConsole();
beforeEach(() => {
console = new ArrayConsole();
TestBed.configureCompiler({
providers: [
{provide: Console, useValue: console},
{provide: CompilerConfig, useValue: new CompilerConfig({enableLegacyTemplate: true})}
],
});
});
}
function commonBeforeEach() {
beforeEach(inject([TemplateParser], (parser: TemplateParser) => {
const someAnimation = new CompileAnimationEntryMetadata('someAnimation', []);
const someTemplate = compileTemplateMetadata({animations: [someAnimation]});
@@ -286,6 +289,7 @@ export function main() {
});
});
configureCompiler();
commonBeforeEach();
describe('security context', () => {
@@ -318,6 +322,7 @@ export function main() {
TestBed.configureCompiler({providers: [TEST_COMPILER_PROVIDERS, MOCK_SCHEMA_REGISTRY]});
});
configureCompiler();
commonBeforeEach();
describe('parse', () => {
@@ -2129,13 +2134,13 @@ The pipe 'test' could not be found ("{{[ERROR ->]a | test}}"): TestComp@0:2`);
});
describe('Template Parser - opt-out `<template>` support', () => {
describe('Template Parser - `<template>` support disabled by default', () => {
beforeEach(() => {
TestBed.configureCompiler({
providers: [{
provide: CompilerConfig,
useValue: new CompilerConfig({enableLegacyTemplate: false}),
}],
providers: [
{provide: Console, useValue: console},
{provide: CompilerConfig, useValue: new CompilerConfig()}
],
});
});
@@ -7,6 +7,7 @@
*/
import {CommonModule} from '@angular/common';
import {CompilerConfig} from '@angular/compiler';
import {Compiler, ComponentFactory, ComponentRef, ErrorHandler, EventEmitter, Host, Inject, Injectable, InjectionToken, Injector, NO_ERRORS_SCHEMA, NgModule, NgModuleRef, OnDestroy, SkipSelf, ViewRef} from '@angular/core';
import {ChangeDetectionStrategy, ChangeDetectorRef, PipeTransform} from '@angular/core/src/change_detection/change_detection';
import {getDebugContext} from '@angular/core/src/errors';
@@ -37,7 +38,14 @@ export function main() {
function declareTests({useJit}: {useJit: boolean}) {
describe('integration tests', function() {
beforeEach(() => { TestBed.configureCompiler({useJit}); });
beforeEach(() => {
TestBed.configureCompiler({
useJit,
providers: [
{provide: CompilerConfig, useValue: new CompilerConfig({enableLegacyTemplate: true})}
]
});
});
describe('react to record changes', function() {
it('should consume text node changes', () => {
@@ -160,7 +160,7 @@ export class JitCompilerFactory implements CompilerFactory {
useJit: true,
defaultEncapsulation: ViewEncapsulation.Emulated,
missingTranslation: MissingTranslationStrategy.Warning,
enableLegacyTemplate: true,
enableLegacyTemplate: false,
};
this._defaultOptions = [compilerOptions, ...defaultOptions];
@@ -76,7 +76,7 @@ interface Options extends ts.CompilerOptions {
// Print extra information while running the compiler
trace?: boolean;
// Whether to enable support for <template> and the template attribute (true by default)
// Whether to enable support for <template> and the template attribute (false by default)
enableLegacyTemplate?: boolean;
// Whether to generate .ngsummary.ts files that allow to use AOTed artifacts

0 comments on commit 56238fe

Please sign in to comment.