fix(core): detectChanges() doesn't work on detached instance

Closes #13426
Closes #13472
This commit is contained in:
Miško Hevery 2016-12-13 16:26:22 -08:00 committed by Victor Berchet
parent b56474d067
commit a659259962
3 changed files with 34 additions and 3 deletions

View File

@ -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());

View File

@ -312,11 +312,16 @@ export abstract class AppView<T> {
*/
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');

View File

@ -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('<wrap-comp-with-ref></wrap-comp-with-ref>');
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('<comp-with-ref></comp-with-ref>');
const cmp: CompWithRef = queryDirs(ctx.debugElement, CompWithRef)[0];
@ -1346,6 +1364,14 @@ class CompWithRef {
noop() {}
}
@Component({
selector: 'wrap-comp-with-ref',
template: '<comp-with-ref></comp-with-ref>'
})
class WrapCompWithRef {
constructor(public changeDetectorRef: ChangeDetectorRef) {}
}
@Component({
selector: 'push-cmp',
template: '<div (event)="noop()" emitterDirective></div>{{value}}{{renderIncrement}}',