Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 71301aa

Browse files
committed
fix(list-view): Destroy item views on unload
1 parent 0bd2ba5 commit 71301aa

File tree

2 files changed

+38
-11
lines changed

2 files changed

+38
-11
lines changed

‎nativescript-angular/directives/list-view-comp.ts‎

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ export class ListViewComponent implements DoCheck, OnDestroy, AfterContentInit {
137137
listViewLog("registerTemplate for key: " + key);
138138

139139
const viewRef = this.loader.createEmbeddedView(template, new ListItemContext(), 0);
140-
const resultView = getSingleViewFromViewRef(viewRef);
140+
const resultView = getItemViewRoot(viewRef);
141141
resultView[NG_VIEW] = viewRef;
142142

143143
return resultView;
@@ -170,7 +170,7 @@ export class ListViewComponent implements DoCheck, OnDestroy, AfterContentInit {
170170
} else {
171171
listViewLog("onItemLoading: " + index + " - Creating view from template");
172172
viewRef = this.loader.createEmbeddedView(this.itemTemplate, new ListItemContext(), 0);
173-
args.view = getSingleViewFromViewRef(viewRef);
173+
args.view = getItemViewRoot(viewRef);
174174
args.view[NG_VIEW] = viewRef;
175175
}
176176

@@ -215,7 +215,7 @@ export class ListViewComponent implements DoCheck, OnDestroy, AfterContentInit {
215215
}
216216
}
217217

218-
function getSingleViewRecursive(nodes: Array<any>, nestLevel: number) {
218+
function getSingleViewRecursive(nodes: Array<any>, nestLevel: number): View {
219219
const actualNodes = nodes.filter((n) => !!n && n.nodeName !== "#text");
220220

221221
if (actualNodes.length === 0) {
@@ -235,8 +235,18 @@ function getSingleViewRecursive(nodes: Array<any>, nestLevel: number) {
235235
}
236236
}
237237

238-
function getSingleViewFromViewRef(viewRef: EmbeddedViewRef<any>): View {
239-
return getSingleViewRecursive(viewRef.rootNodes, 0);
238+
export interface ComponentView {
239+
rootNodes: Array<any>;
240+
destroy(): void;
241+
};
242+
export type RootLocator = (nodes: Array<any>, nestLevel: number) => View;
243+
244+
export function getItemViewRoot(viewRef: ComponentView, rootLocator: RootLocator = getSingleViewRecursive): View {
245+
const rootView = rootLocator(viewRef.rootNodes, 0);
246+
rootView.on("unloaded", () => {
247+
viewRef.destroy();
248+
});
249+
return rootView;
240250
}
241251

242252
@Directive({ selector: "[nsTemplateKey]" })

‎tests/app/tests/list-view-tests.ts‎

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { assert } from "./test-config";
2-
import { Component, Input, AfterViewInit } from '@angular/core';
2+
import { Component, Input, AfterViewInit } from "@angular/core";
33
import { TestApp } from "./test-app";
4+
import { RootLocator, ComponentView, getItemViewRoot } from "nativescript-angular/directives/list-view-comp";
5+
import { ProxyViewContainer } from "tns-core-modules/ui/proxy-view-container";
46

57
// import trace = require("trace");
68
// trace.setCategories("ns-list-view, " + trace.categories.Navigation);
@@ -20,7 +22,7 @@ const ITEMS = [
2022
let testTemplates: { first: number, second: number };
2123

2224
@Component({
23-
selector: 'list-view-setupItemView',
25+
selector: "list-view-setupItemView",
2426
template: `
2527
<GridLayout>
2628
<ListView [items]="myItems" (setupItemView)="onSetupItemView($event)">
@@ -61,7 +63,6 @@ export class ItemTemplateComponent {
6163
<template nsTemplateKey="first">
6264
<item-component templateName="first"></item-component>
6365
</template>
64-
6566
<template nsTemplateKey="second" let-item="item">
6667
<item-component templateName="second"></item-component>
6768
</template>
@@ -77,7 +78,7 @@ export class TestListViewSelectorComponent {
7778
constructor() { testTemplates = { first: 0, second: 0 }; }
7879
}
7980

80-
describe('ListView-tests', () => {
81+
describe("ListView-tests", () => {
8182
let testApp: TestApp = null;
8283

8384
before(() => {
@@ -94,7 +95,7 @@ describe('ListView-tests', () => {
9495
testApp.disposeComponents();
9596
});
9697

97-
it('setupItemView is called for every item', (done) => {
98+
it("setupItemView is called for every item", (done) => {
9899
return testApp.loadComponent(TestListViewComponent).then((componentRef) => {
99100
const component = componentRef.instance;
100101
setTimeout(() => {
@@ -106,7 +107,7 @@ describe('ListView-tests', () => {
106107
});
107108

108109

109-
it('itemTemplateSelector selects templates', (done) => {
110+
it("itemTemplateSelector selects templates", (done) => {
110111
return testApp.loadComponent(TestListViewSelectorComponent).then((componentRef) => {
111112
setTimeout(() => {
112113
assert.deepEqual(testTemplates, { first: 2, second: 1 });
@@ -116,3 +117,19 @@ describe('ListView-tests', () => {
116117
.catch(done);
117118
});
118119
});
120+
121+
describe("ListView item templates", () => {
122+
it("destroy child ng views on unload", () => {
123+
const childRoot = new ProxyViewContainer();
124+
let viewDestroyed = false;
125+
const view: ComponentView = {
126+
rootNodes: [],
127+
destroy: () => {
128+
viewDestroyed = true;
129+
}
130+
};
131+
const itemRoot = getItemViewRoot(view, (_rootNodes, _level) => childRoot);
132+
itemRoot.notify({eventName: "unloaded", object: itemRoot});
133+
assert.isTrue(viewDestroyed, "ng view not destroyed");
134+
});
135+
});

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /