fix(core): allow directives to inject the component’s `ChangeDetectorRef`. (#16394)
When a directive lives on the same element as a component (e.g. `<my-comp myDir>`), 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
This commit is contained in:
parent
900a88b15d
commit
392d584572
|
@ -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 !;
|
||||
|
|
|
@ -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(
|
||||
'<div componentNeedsChangeDetectorRef directiveNeedsChangeDetectorRef></div>');
|
||||
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: '<ng-content></ng-content>{{counter}}'}});
|
||||
const cf = createComponentFixture(
|
||||
'<div componentNeedsChangeDetectorRef><div directiveNeedsChangeDetectorRef></div></div>');
|
||||
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('<div needsViewContainerRef></div>');
|
||||
|
|
Loading…
Reference in New Issue