From aa8bba4865b4101f43bb5b6b78bf3697c578a7f8 Mon Sep 17 00:00:00 2001 From: Tobias Bosch Date: Thu, 27 Apr 2017 16:15:10 -0700 Subject: [PATCH] fix(core): allow to detach `OnPush` components (#16394) Fixes #9720 --- packages/core/src/view/refs.ts | 4 ++-- packages/core/src/view/types.ts | 9 ++++++--- packages/core/src/view/view.ts | 6 +++--- .../linker/change_detection_integration_spec.ts | 16 +++++++++++++++- 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/packages/core/src/view/refs.ts b/packages/core/src/view/refs.ts index 54127c8e64..e77d0ea2f3 100644 --- a/packages/core/src/view/refs.ts +++ b/packages/core/src/view/refs.ts @@ -236,11 +236,11 @@ export class ViewRef_ implements EmbeddedViewRef, InternalViewRef { get destroyed(): boolean { return (this._view.state & ViewState.Destroyed) !== 0; } markForCheck(): void { markParentViewsForCheck(this._view); } - detach(): void { this._view.state &= ~ViewState.ChecksEnabled; } + detach(): void { this._view.state &= ~ViewState.Attached; } detectChanges(): void { Services.checkAndUpdateView(this._view); } checkNoChanges(): void { Services.checkNoChangesView(this._view); } - reattach(): void { this._view.state |= ViewState.ChecksEnabled; } + reattach(): void { this._view.state |= ViewState.Attached; } onDestroy(callback: Function) { if (!this._view.disposables) { this._view.disposables = []; diff --git a/packages/core/src/view/types.ts b/packages/core/src/view/types.ts index 325f75faad..104f3c7c9d 100644 --- a/packages/core/src/view/types.ts +++ b/packages/core/src/view/types.ts @@ -324,9 +324,12 @@ export interface ViewData { */ export const enum ViewState { FirstCheck = 1 << 0, - ChecksEnabled = 1 << 1, - Errored = 1 << 2, - Destroyed = 1 << 3 + Attached = 1 << 1, + ChecksEnabled = 1 << 2, + Errored = 1 << 3, + Destroyed = 1 << 4, + + CatDetectChanges = Attached | ChecksEnabled, } export interface DisposableFn { (): void; } diff --git a/packages/core/src/view/view.ts b/packages/core/src/view/view.ts index 4150c29be3..44f36d6190 100644 --- a/packages/core/src/view/view.ts +++ b/packages/core/src/view/view.ts @@ -211,7 +211,7 @@ function createView( viewContainerParent: null, parentNodeDef, context: null, component: null, nodes, - state: ViewState.FirstCheck | ViewState.ChecksEnabled, root, renderer, + state: ViewState.FirstCheck | ViewState.CatDetectChanges, root, renderer, oldValues: new Array(def.bindingCount), disposables }; return view; @@ -542,13 +542,13 @@ function callViewAction(view: ViewData, action: ViewAction) { const viewState = view.state; switch (action) { case ViewAction.CheckNoChanges: - if ((viewState & ViewState.ChecksEnabled) && + if ((viewState & ViewState.CatDetectChanges) === ViewState.CatDetectChanges && (viewState & (ViewState.Errored | ViewState.Destroyed)) === 0) { checkNoChangesView(view); } break; case ViewAction.CheckAndUpdate: - if ((viewState & ViewState.ChecksEnabled) && + if ((viewState & ViewState.CatDetectChanges) === ViewState.CatDetectChanges && (viewState & (ViewState.Errored | ViewState.Destroyed)) === 0) { checkAndUpdateView(view); } diff --git a/packages/core/test/linker/change_detection_integration_spec.ts b/packages/core/test/linker/change_detection_integration_spec.ts index 8a1839c037..fe6444071c 100644 --- a/packages/core/test/linker/change_detection_integration_spec.ts +++ b/packages/core/test/linker/change_detection_integration_spec.ts @@ -1175,6 +1175,21 @@ export function main() { expect(renderLog.log).toEqual([]); })); + it('Detached should disable OnPush', fakeAsync(() => { + const ctx = createCompFixture(''); + ctx.componentInstance.value = 0; + ctx.detectChanges(); + renderLog.clear(); + + const cmp: CompWithRef = queryDirs(ctx.debugElement, PushComp)[0]; + cmp.changeDetectorRef.detach(); + + ctx.componentInstance.value = 1; + ctx.detectChanges(); + + expect(renderLog.log).toEqual([]); + })); + it('Detached view can be checked locally', fakeAsync(() => { const ctx = createCompFixture(''); const cmp: CompWithRef = queryDirs(ctx.debugElement, CompWithRef)[0]; @@ -1225,7 +1240,6 @@ export function main() { ctx.detectChanges(); expect(cmp.renderCount).toBe(count); - })); });