From a65925996257ce9c3c0ead6ae18f2f77badfa622 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mis=CC=8Cko=20Hevery?= Date: Tue, 13 Dec 2016 16:26:22 -0800 Subject: [PATCH] fix(core): detectChanges() doesn't work on detached instance Closes #13426 Closes #13472 --- .../src/view_compiler/view_builder.ts | 2 +- modules/@angular/core/src/linker/view.ts | 9 +++++-- .../change_detection_integration_spec.ts | 26 +++++++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/modules/@angular/compiler/src/view_compiler/view_builder.ts b/modules/@angular/compiler/src/view_compiler/view_builder.ts index 740f0f9649..a66434eec4 100644 --- a/modules/@angular/compiler/src/view_compiler/view_builder.ts +++ b/modules/@angular/compiler/src/view_compiler/view_builder.ts @@ -576,7 +576,7 @@ function generateDetectChangesMethod(view: CompileView): o.Statement[] { } stmts.push(...view.detectChangesRenderPropertiesMethod.finish()); view.viewChildren.forEach((viewChild) => { - stmts.push(viewChild.callMethod('detectChanges', [DetectChangesVars.throwOnChange]).toStmt()); + stmts.push(viewChild.callMethod('internalDetectChanges', [DetectChangesVars.throwOnChange]).toStmt()); }); const afterViewStmts = view.updateViewQueriesMethod.finish().concat(view.afterViewLifecycleCallbacksMethod.finish()); diff --git a/modules/@angular/core/src/linker/view.ts b/modules/@angular/core/src/linker/view.ts index 68fa533884..cf2d677b47 100644 --- a/modules/@angular/core/src/linker/view.ts +++ b/modules/@angular/core/src/linker/view.ts @@ -312,11 +312,16 @@ export abstract class AppView { */ dirtyParentQueriesInternal(): void {} + internalDetectChanges(throwOnChange: boolean): void { + if (this.cdMode !== ChangeDetectorStatus.Detached) { + this.detectChanges(throwOnChange); + } + } + detectChanges(throwOnChange: boolean): void { const s = _scope_check(this.clazz); if (this.cdMode === ChangeDetectorStatus.Checked || - this.cdMode === ChangeDetectorStatus.Errored || - this.cdMode === ChangeDetectorStatus.Detached) + this.cdMode === ChangeDetectorStatus.Errored) return; if (this.cdMode === ChangeDetectorStatus.Destroyed) { this.throwDestroyedError('detectChanges'); diff --git a/modules/@angular/core/test/linker/change_detection_integration_spec.ts b/modules/@angular/core/test/linker/change_detection_integration_spec.ts index 8dafcd53e7..efcc7f0ab1 100644 --- a/modules/@angular/core/test/linker/change_detection_integration_spec.ts +++ b/modules/@angular/core/test/linker/change_detection_integration_spec.ts @@ -82,6 +82,7 @@ export function main() { AnotherComponent, TestLocals, CompWithRef, + WrapCompWithRef, EmitterDirective, PushComp, OnDestroyDirective, @@ -1133,6 +1134,23 @@ export function main() { expect(renderLog.log).toEqual([]); })); + it('Detached view can be checked locally', fakeAsync(() => { + const ctx = createCompFixture(''); + const cmp: CompWithRef = queryDirs(ctx.debugElement, CompWithRef)[0]; + cmp.value = 'hello'; + cmp.changeDetectorRef.detach(); + expect(renderLog.log).toEqual([]); + + ctx.detectChanges(); + + expect(renderLog.log).toEqual([]); + + cmp.changeDetectorRef.detectChanges(); + + expect(renderLog.log).toEqual(['{{hello}}']); + })); + + it('Reattaches', fakeAsync(() => { const ctx = createCompFixture(''); const cmp: CompWithRef = queryDirs(ctx.debugElement, CompWithRef)[0]; @@ -1346,6 +1364,14 @@ class CompWithRef { noop() {} } +@Component({ + selector: 'wrap-comp-with-ref', + template: '' +}) +class WrapCompWithRef { + constructor(public changeDetectorRef: ChangeDetectorRef) {} +} + @Component({ selector: 'push-cmp', template: '
{{value}}{{renderIncrement}}',