From 392d584572f91c9ad33700d39145aa05ffa6c24a Mon Sep 17 00:00:00 2001 From: Tobias Bosch Date: Thu, 27 Apr 2017 16:13:47 -0700 Subject: [PATCH] =?UTF-8?q?fix(core):=20allow=20directives=20to=20inject?= =?UTF-8?q?=20the=20component=E2=80=99s=20`ChangeDetectorRef`.=20(#16394)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a directive lives on the same element as a component (e.g. ``), the directive was not able to get hold of the `ChangeDetectorRef` of the component on that element. However, as directives are supposed to decorate components, this is incorrect. This commit enables this use case. Closes #12816 --- packages/core/src/view/provider.ts | 6 +++ .../linker/view_injector_integration_spec.ts | 40 +++++++++++++++++++ 2 files changed, 46 insertions(+) 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('
');