diff --git a/packages/compiler-cli/test/compliance/r3_view_compiler_template_spec.ts b/packages/compiler-cli/test/compliance/r3_view_compiler_template_spec.ts
index 75e2a2c000..5af1113bca 100644
--- a/packages/compiler-cli/test/compliance/r3_view_compiler_template_spec.ts
+++ b/packages/compiler-cli/test/compliance/r3_view_compiler_template_spec.ts
@@ -558,4 +558,48 @@ describe('compiler compliance: template', () => {
expect(allListenerFunctionsNames.length).toBe(3);
expect(allListenerFunctionsNames).toEqual(uniqueListenerFunctionNames);
});
+
+ it('should support pipes in template bindings', () => {
+ const files = {
+ app: {
+ 'spec.ts': `
+ import {Component, NgModule} from '@angular/core';
+
+ @Component({
+ selector: 'my-component',
+ template: \`
+
\`
+ })
+ export class MyComponent {}
+
+ @NgModule({declarations: [MyComponent]})
+ export class MyModule {}
+ `
+ }
+ };
+
+ const template = `
+ const $c0$ = [${AttributeMarker.SelectOnly}, "ngIf"];
+
+ function MyComponent_div_0_Template(rf, ctx) {
+ if (rf & 1) {
+ $i0$.ɵelement(0, "div");
+ }
+ }
+
+ // ...
+
+ template: function MyComponent_Template(rf, ctx) {
+ if (rf & 1) {
+ $i0$.ɵtemplate(0, MyComponent_div_0_Template, 1, 0, "div", $c0$);
+ $i0$.ɵpipe(1, "pipe");
+ } if (rf & 2) {
+ $i0$.ɵelementProperty(0, "ngIf", $i0$.ɵbind($i0$.ɵpipeBind1(1, 1, ctx.val)));
+ }
+ }`;
+
+ const result = compile(files, angularFiles);
+
+ expectEmit(result.source, template, 'Incorrect template');
+ });
});
diff --git a/packages/compiler/src/render3/view/template.ts b/packages/compiler/src/render3/view/template.ts
index 8bb9c6aa99..cd0f9474ce 100644
--- a/packages/compiler/src/render3/view/template.ts
+++ b/packages/compiler/src/render3/view/template.ts
@@ -803,19 +803,6 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver
parameters.push(o.importExpr(R3.templateRefExtractor));
}
- // handle property bindings e.g. p(1, 'ngForOf', ɵbind(ctx.items));
- const context = o.variable(CONTEXT_NAME);
- template.inputs.forEach(input => {
- const value = input.value.visit(this._valueConverter);
- this.allocateBindingSlots(value);
- this.updateInstruction(template.sourceSpan, R3.elementProperty, () => {
- return [
- o.literal(templateIndex), o.literal(input.name),
- this.convertPropertyBinding(context, value)
- ];
- });
- });
-
// Create the template function
const templateVisitor = new TemplateDefinitionBuilder(
this.constantPool, this._bindingScope, this.level + 1, contextName, this.i18n,
@@ -845,6 +832,19 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver
return trimTrailingNulls(parameters);
});
+ // handle property bindings e.g. ɵelementProperty(1, 'ngForOf', ɵbind(ctx.items));
+ const context = o.variable(CONTEXT_NAME);
+ template.inputs.forEach(input => {
+ const value = input.value.visit(this._valueConverter);
+ this.allocateBindingSlots(value);
+ this.updateInstruction(template.sourceSpan, R3.elementProperty, () => {
+ return [
+ o.literal(templateIndex), o.literal(input.name),
+ this.convertPropertyBinding(context, value)
+ ];
+ });
+ });
+
// Generate listeners for directive output
template.outputs.forEach((outputAst: t.BoundEvent) => {
this.creationInstruction(
diff --git a/packages/core/src/render3/view_engine_compatibility.ts b/packages/core/src/render3/view_engine_compatibility.ts
index 3f6fb55a9d..a2a5f604dc 100644
--- a/packages/core/src/render3/view_engine_compatibility.ts
+++ b/packages/core/src/render3/view_engine_compatibility.ts
@@ -345,7 +345,7 @@ export function createViewRef(
const componentIndex = hostTNode.directiveStart;
const componentView = getComponentViewByIndex(hostTNode.index, hostView);
return new ViewRef(componentView, context, componentIndex);
- } else if (hostTNode.type === TNodeType.Element) {
+ } else if (hostTNode.type === TNodeType.Element || hostTNode.type === TNodeType.Container) {
const hostComponentView = findComponentView(hostView);
return new ViewRef(hostComponentView, hostComponentView[CONTEXT], -1);
}
diff --git a/packages/core/test/acceptance/di_spec.ts b/packages/core/test/acceptance/di_spec.ts
new file mode 100644
index 0000000000..7be5795430
--- /dev/null
+++ b/packages/core/test/acceptance/di_spec.ts
@@ -0,0 +1,42 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * Use of this source code is governed by an MIT-style license that can be
+ * found in the LICENSE file at https://angular.io/license
+ */
+
+import {CommonModule} from '@angular/common';
+import {ChangeDetectorRef, Component, Pipe, PipeTransform} from '@angular/core';
+import {ViewRef} from '@angular/core/src/render3/view_ref';
+import {TestBed} from '@angular/core/testing';
+
+describe('di', () => {
+ describe('ChangeDetectorRef', () => {
+ it('should inject host component ChangeDetectorRef into directives on templates', () => {
+ let pipeInstance: MyPipe;
+
+ @Pipe({name: 'pipe'})
+ class MyPipe implements PipeTransform {
+ constructor(public cdr: ChangeDetectorRef) { pipeInstance = this; }
+
+ transform(value: any): any { return value; }
+ }
+
+ @Component({
+ selector: 'my-app',
+ template: `Visible
`,
+ })
+ class MyApp {
+ showing = true;
+
+ constructor(public cdr: ChangeDetectorRef) {}
+ }
+
+ TestBed.configureTestingModule({declarations: [MyApp, MyPipe], imports: [CommonModule]});
+ const fixture = TestBed.createComponent(MyApp);
+ fixture.detectChanges();
+ expect((pipeInstance !.cdr as ViewRef).context).toBe(fixture.componentInstance);
+ });
+ });
+});