From 33313ad1f5897095a54ebb7b5856859859ac709f Mon Sep 17 00:00:00 2001 From: Marc Laval Date: Mon, 28 Aug 2017 16:07:52 +0200 Subject: [PATCH] fix(core): complete EventEmitter in QueryList on component destroy Fixes #18741 --- packages/core/src/linker/query_list.ts | 6 ++++++ packages/core/src/view/view.ts | 2 ++ packages/core/test/linker/query_integration_spec.ts | 12 ++++++++++++ 3 files changed, 20 insertions(+) diff --git a/packages/core/src/linker/query_list.ts b/packages/core/src/linker/query_list.ts index 9abd01b6fed88b..8dae2c824f1e0b 100644 --- a/packages/core/src/linker/query_list.ts +++ b/packages/core/src/linker/query_list.ts @@ -108,6 +108,12 @@ export class QueryList/* implements Iterable */ { /** internal */ get dirty() { return this._dirty; } + + /** internal */ + destroy(): void { + this._emitter.complete(); + this._emitter.unsubscribe(); + } } function flatten(list: Array): T[] { diff --git a/packages/core/src/view/view.ts b/packages/core/src/view/view.ts index 7572791207075b..fc14227773aaf4 100644 --- a/packages/core/src/view/view.ts +++ b/packages/core/src/view/view.ts @@ -530,6 +530,8 @@ function destroyViewNodes(view: ViewData) { view.renderer.destroyNode !(asElementData(view, i).renderElement); } else if (def.flags & NodeFlags.TypeText) { view.renderer.destroyNode !(asTextData(view, i).renderText); + } else if (def.flags & NodeFlags.TypeContentQuery || def.flags & NodeFlags.TypeViewQuery) { + asQueryList(view, i).destroy(); } } } diff --git a/packages/core/test/linker/query_integration_spec.ts b/packages/core/test/linker/query_integration_spec.ts index d3b5cc8b193c55..8c8b5d6a436030 100644 --- a/packages/core/test/linker/query_integration_spec.ts +++ b/packages/core/test/linker/query_integration_spec.ts @@ -10,6 +10,8 @@ import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, import {ComponentFixture, TestBed, async} from '@angular/core/testing'; import {expect} from '@angular/platform-browser/testing/src/matchers'; +import {Subject} from 'rxjs/Subject'; + import {stringify} from '../../src/util'; export function main() { @@ -348,16 +350,26 @@ export function main() { view.componentInstance.shouldShow = true; view.detectChanges(); + let isQueryListCompleted = false; + const q: NeedsQuery = view.debugElement.children[0].references !['q']; + const changes = >q.query.changes; expect(q.query.length).toEqual(1); + expect(changes.closed).toBeFalsy(); + changes.subscribe(() => {}, () => {}, () => { isQueryListCompleted = true; }); view.componentInstance.shouldShow = false; view.detectChanges(); + expect(changes.closed).toBeTruthy(); + expect(isQueryListCompleted).toBeTruthy(); + view.componentInstance.shouldShow = true; view.detectChanges(); const q2: NeedsQuery = view.debugElement.children[0].references !['q']; expect(q2.query.length).toEqual(1); + expect(changes.closed).toBeTruthy(); + expect((>q2.query.changes).closed).toBeFalsy(); }); });