diff --git a/packages/core/src/view/provider.ts b/packages/core/src/view/provider.ts index 831d76a498..87c4b25df1 100644 --- a/packages/core/src/view/provider.ts +++ b/packages/core/src/view/provider.ts @@ -355,6 +355,12 @@ export function resolveDep( } const tokenKey = depDef.tokenKey; + if (tokenKey === ChangeDetectorRefTokenKey) { + // directives on the same element as a component should be able to control the change detector + // of that component as well. + allowPrivateServices = !!(elDef && elDef.element !.componentView); + } + if (elDef && (depDef.flags & DepFlags.SkipSelf)) { allowPrivateServices = false; elDef = elDef.parent !; diff --git a/packages/core/test/linker/view_injector_integration_spec.ts b/packages/core/test/linker/view_injector_integration_spec.ts index 77359bc2c9..76900b100c 100644 --- a/packages/core/test/linker/view_injector_integration_spec.ts +++ b/packages/core/test/linker/view_injector_integration_spec.ts @@ -652,6 +652,46 @@ export function main() { expect(compEl.nativeElement).toHaveText('1'); }); + it('should inject ChangeDetectorRef of a same element component into a directive', () => { + TestBed.configureTestingModule( + {declarations: [PushComponentNeedsChangeDetectorRef, DirectiveNeedsChangeDetectorRef]}); + const cf = createComponentFixture( + '
'); + cf.detectChanges(); + const compEl = cf.debugElement.children[0]; + const comp = compEl.injector.get(PushComponentNeedsChangeDetectorRef); + const dir = compEl.injector.get(DirectiveNeedsChangeDetectorRef); + comp.counter = 1; + cf.detectChanges(); + expect(compEl.nativeElement).toHaveText('0'); + dir.changeDetectorRef.markForCheck(); + cf.detectChanges(); + expect(compEl.nativeElement).toHaveText('1'); + }); + + it(`should not inject ChangeDetectorRef of a parent element's component into a directive`, () => { + TestBed + .configureTestingModule({ + declarations: [PushComponentNeedsChangeDetectorRef, DirectiveNeedsChangeDetectorRef] + }) + .overrideComponent( + PushComponentNeedsChangeDetectorRef, + {set: {template: '{{counter}}'}}); + const cf = createComponentFixture( + '
'); + cf.detectChanges(); + const compEl = cf.debugElement.children[0]; + const comp = compEl.injector.get(PushComponentNeedsChangeDetectorRef); + const dirEl = compEl.children[0]; + const dir = dirEl.injector.get(DirectiveNeedsChangeDetectorRef); + comp.counter = 1; + cf.detectChanges(); + expect(compEl.nativeElement).toHaveText('0'); + dir.changeDetectorRef.markForCheck(); + cf.detectChanges(); + expect(compEl.nativeElement).toHaveText('0'); + }); + it('should inject ViewContainerRef', () => { TestBed.configureTestingModule({declarations: [NeedsViewContainerRef]}); const el = createComponent('
');