diff --git a/packages/compiler-cli/test/ngc_spec.ts b/packages/compiler-cli/test/ngc_spec.ts
index 1a1d9984f2..eb80136e45 100644
--- a/packages/compiler-cli/test/ngc_spec.ts
+++ b/packages/compiler-cli/test/ngc_spec.ts
@@ -898,12 +898,12 @@ describe('ngc transformer command-line', () => {
export * from './util';
- // Note: the lamda will be lowered into an exported expression
+ // Note: the lambda will be lowered into an exported expression
@NgModule({providers: [{provide: 'aToken', useValue: () => 2}]})
export class MyModule {}
`);
write('util.ts', `
- // Note: The lamda will be lowered into an exported expression
+ // Note: The lambda will be lowered into an exported expression
const x = () => 2;
export const y = x;
@@ -1144,7 +1144,7 @@ describe('ngc transformer command-line', () => {
shouldExist('app/main.js');
});
- it('shoud be able to compile libraries with summaries and flat modules', () => {
+ it('should be able to compile libraries with summaries and flat modules', () => {
writeFiles();
compile();
@@ -1466,7 +1466,7 @@ describe('ngc transformer command-line', () => {
`);
}));
- it('should recomiple when the html file changes',
+ it('should recompile when the html file changes',
expectRecompile(() => { write('greet.html', '
Hello {{name}} again!
'); }));
it('should recompile when the css file changes',
diff --git a/packages/compiler/src/render3/r3_identifiers.ts b/packages/compiler/src/render3/r3_identifiers.ts
index 8c80c69c71..bdc4e71188 100644
--- a/packages/compiler/src/render3/r3_identifiers.ts
+++ b/packages/compiler/src/render3/r3_identifiers.ts
@@ -62,7 +62,6 @@ export class Identifiers {
static bind6: o.ExternalReference = {name: 'ɵb6', moduleName: CORE};
static bind7: o.ExternalReference = {name: 'ɵb7', moduleName: CORE};
static bind8: o.ExternalReference = {name: 'ɵb8', moduleName: CORE};
- static bind9: o.ExternalReference = {name: 'ɵb9', moduleName: CORE};
static bindV: o.ExternalReference = {name: 'ɵbV', moduleName: CORE};
static memory: o.ExternalReference = {name: 'ɵm', moduleName: CORE};
diff --git a/packages/compiler/src/render3/r3_view_compiler.ts b/packages/compiler/src/render3/r3_view_compiler.ts
index 63112d2c0a..ea3ff2e8a3 100644
--- a/packages/compiler/src/render3/r3_view_compiler.ts
+++ b/packages/compiler/src/render3/r3_view_compiler.ts
@@ -157,8 +157,6 @@ function interpolate(args: o.Expression[]): o.Expression {
return o.importExpr(R3.bind7).callFn(args);
case 17:
return o.importExpr(R3.bind8).callFn(args);
- case 19:
- return o.importExpr(R3.bind9).callFn(args);
}
(args.length > 19 && args.length % 2 == 1) ||
error(`Invalid interpolation argument length ${args.length}`);
diff --git a/packages/core/src/core_render3_private_export.ts b/packages/core/src/core_render3_private_export.ts
index eedf323afc..a1306fec04 100644
--- a/packages/core/src/core_render3_private_export.ts
+++ b/packages/core/src/core_render3_private_export.ts
@@ -11,6 +11,7 @@ export {
defineComponent as ɵdefineComponent,
detectChanges as ɵdetectChanges,
renderComponent as ɵrenderComponent,
+ ComponentType as ɵComponentType,
C as ɵC,
E as ɵE,
L as ɵL,
@@ -18,6 +19,14 @@ export {
V as ɵV,
b as ɵb,
b1 as ɵb1,
+ b2 as ɵb2,
+ b3 as ɵb3,
+ b4 as ɵb4,
+ b5 as ɵb5,
+ b6 as ɵb6,
+ b7 as ɵb7,
+ b8 as ɵb8,
+ bV as ɵbV,
cR as ɵcR,
cr as ɵcr,
e as ɵe,
diff --git a/packages/core/test/render3/compiler_canonical_spec.ts b/packages/core/test/render3/compiler_canonical_spec.ts
index f6a8fdad3a..37ef050769 100644
--- a/packages/core/test/render3/compiler_canonical_spec.ts
+++ b/packages/core/test/render3/compiler_canonical_spec.ts
@@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
-import {Component, Directive, Injectable, NgModule, Optional, TemplateRef, Type} from '../../src/core';
+import {Component, Directive, Injectable, Input, NgModule, Optional, SimpleChanges, TemplateRef, Type, ViewContainerRef} from '../../src/core';
import * as r3 from '../../src/render3/index';
import {containerEl, renderComponent, requestAnimationFrame, toHtml} from './render_util';
@@ -193,6 +193,193 @@ describe('compiler specification', () => {
});
});
+ describe('template variables', () => {
+
+ interface ForOfContext {
+ $implicit: any;
+ index: number;
+ even: boolean;
+ odd: boolean;
+ }
+
+ @Directive({selector: '[forOf]'})
+ class ForOfDirective {
+ private previous: any[];
+
+ constructor(private view: ViewContainerRef, private template: TemplateRef) {}
+
+ @Input() forOf: any[];
+
+ ngOnChanges(simpleChanges: SimpleChanges) {
+ if ('forOf' in simpleChanges) {
+ this.update();
+ }
+ }
+
+ ngDoCheck(): void {
+ const previous = this.previous;
+ const current = this.forOf;
+ if (!previous || previous.length != current.length ||
+ previous.some((value: any, index: number) => current[index] !== previous[index])) {
+ this.update();
+ }
+ }
+
+ private update() {
+ // TODO(chuckj): Not implemented yet
+ // this.view.clear();
+ if (this.forOf) {
+ const current = this.forOf;
+ for (let i = 0; i < current.length; i++) {
+ const context = {$implicit: current[i], index: i, even: i % 2 == 0, odd: i % 2 == 1};
+ // TODO(chuckj): Not implemented yet
+ // this.view.createEmbeddedView(this.template, context);
+ }
+ this.previous = [...this.forOf];
+ }
+ }
+
+ // NORMATIVE
+ static ngDirectiveDef = r3.defineDirective({
+ factory: function ForOfDirective_Factory() {
+ return new ForOfDirective(r3.injectViewContainerRef(), r3.injectTemplateRef());
+ },
+ // TODO(chuckj): Enable when ngForOf enabling lands.
+ // features: [NgOnChangesFeature(NgForOf)],
+ refresh: function ForOfDirective_Refresh(directiveIndex: number, elementIndex: number) {
+ r3.m(directiveIndex).ngDoCheck();
+ },
+ inputs: {forOf: 'forOf'}
+ });
+ // /NORMATIVE
+ }
+
+ it('should support a let variable and reference', () => {
+ interface Item {
+ name: string;
+ }
+
+ const c1_dirs = [ForOfDirective];
+
+ @Component({
+ selector: 'my-component',
+ template: ``
+ })
+ class MyComponent {
+ items = [{name: 'one'}, {name: 'two'}];
+
+ // NORMATIVE
+ static ngComponentDef = r3.defineComponent({
+ tag: 'my-component',
+ factory: function MyComponent_Factory() { return new MyComponent(); },
+ template: function MyComponentTemplate(ctx: MyComponent, cm: boolean) {
+ if (cm) {
+ r3.E(0, 'ul');
+ r3.C(1, c1_dirs, MyComponent_ForOfDirective_Template_1);
+ r3.e();
+ }
+ r3.p(1, 'forOf', r3.b(ctx.items));
+ r3.cR(1);
+ ForOfDirective.ngDirectiveDef.r(2, 1);
+ r3.cr();
+
+ function MyComponent_ForOfDirective_Template_1(ctx1: any, cm: boolean) {
+ if (cm) {
+ r3.E(0, 'li');
+ r3.T(1);
+ r3.e();
+ }
+ const l0_item = ctx1.$implicit;
+ r3.t(1, r3.b1('', l0_item.name, ''));
+ }
+ }
+ });
+ // /NORMATIVE
+ }
+
+ // TODO(chuckj): update when the changes to enable ngForOf lands.
+ expect(renderComp(MyComponent)).toEqual('');
+ });
+
+ it('should support accessing parent template variables', () => {
+ interface Info {
+ description: string;
+ }
+ interface Item {
+ name: string;
+ infos: Info[];
+ }
+
+ const c1_dirs = [ForOfDirective];
+
+ @Component({
+ selector: 'my-component',
+ template: `
+
+ -
+
{{item.name}}
+
+ -
+ {{item.name}}: {{info.description}}
+
+
+
+
`
+ })
+ class MyComponent {
+ items: Item[] = [
+ {name: 'one', infos: [{description: '11'}, {description: '12'}]},
+ {name: 'two', infos: [{description: '21'}, {description: '22'}]}
+ ];
+
+ // NORMATIVE
+ static ngComponentDef = r3.defineComponent({
+ tag: 'my-component',
+ factory: function MyComponent_Factory() { return new MyComponent(); },
+ template: function MyComponent_Template(ctx: MyComponent, cm: boolean) {
+ if (cm) {
+ r3.E(0, 'ul');
+ r3.C(1, c1_dirs, MyComponent_ForOfDirective_Template_1);
+ r3.e();
+ }
+ r3.p(1, 'forOf', r3.b(ctx.items));
+ r3.cR(1);
+ ForOfDirective.ngDirectiveDef.r(2, 1);
+ r3.cr();
+
+ function MyComponent_ForOfDirective_Template_1(ctx1: any, cm: boolean) {
+ if (cm) {
+ r3.E(0, 'div');
+ r3.T(1);
+ r3.e();
+ r3.E(2, 'ul');
+ r3.C(3, c1_dirs, MyComponent_ForOfDirective_ForOfDirective_Template_3);
+ r3.e();
+ }
+ const l0_item = ctx1.$implicit;
+ r3.t(1, r3.b1('', l0_item.name, ''));
+ r3.p(4, 'forOf', r3.b(ctx.items));
+ r3.cR(3);
+ ForOfDirective.ngDirectiveDef.r(4, 3);
+ r3.cr();
+
+ function MyComponent_ForOfDirective_ForOfDirective_Template_3(
+ ctx2: any, cm: boolean) {
+ if (cm) {
+ r3.E(0, 'li');
+ r3.T(1);
+ r3.e();
+ }
+ const l0_info = ctx2.info;
+ r3.t(1, r3.b2('', l0_item.name, ': ', l0_info.description, ''));
+ }
+ }
+ }
+ });
+ // /NORMATIVE
+ }
+ });
+ });
});
xdescribe('NgModule', () => {
@@ -236,7 +423,7 @@ xdescribe('NgModule', () => {
static ngInjectorDef = defineInjector({
factory: () => new MyModule(inject(Toast)),
provider: [
- {provide: Toast, deps: [String]}, // If Toast has matadata generate this line
+ {provide: Toast, deps: [String]}, // If Toast has metadata generate this line
Toast, // If toast has not metadata generate this line.
{provide: String, useValue: 'Hello'}
],