diff --git a/e2e/tests-app-ng/app/app.routes.ts b/e2e/tests-app-ng/app/app.routes.ts
index d68882440..486328ba2 100644
--- a/e2e/tests-app-ng/app/app.routes.ts
+++ b/e2e/tests-app-ng/app/app.routes.ts
@@ -17,6 +17,7 @@ import { ListViewComponent } from "./list-view/list-view-page.component";
import { ListViewControlComponent } from "./list-view/list-view-item-template.component";
import { ListViewAsyncPipeComponent } from "./list-view/async-pipe-template.component";
import { ListViewMainPageComponent } from "./list-view/list-view-main-page.component";
+import { ListViewSegmentedBarPageComponent } from "./list-view/list-view-nested-segmented-bar-page.component";
import { ListViewWithNestedTemplateComponent } from "./list-view/list-view-nested-template.component";
import { ListViewMultipleTemplatesComponent } from "./list-view/multiple-templates.component";
@@ -68,6 +69,7 @@ export const routableComponents = [
ListViewComponent,
ListViewControlComponent,
ListViewAsyncPipeComponent,
+ ListViewSegmentedBarPageComponent,
ListViewWithNestedTemplateComponent,
ListViewMultipleTemplatesComponent,
@@ -131,6 +133,10 @@ export const routes = [
{ path: "ListViewExamples/commonTemplate", component: ListViewComponent, data: { title: "commonTemplate" } },
{ path: "ListViewExamples/customTemplate", component: ListViewControlComponent, data: { title: "customTemplate" } },
{ path: "listView/asyncPipeTemplate", component: ListViewAsyncPipeComponent, data: { title: "asyncPipeTemplate" } },
+ {
+ path: "ListViewExamples/segmentedBarTemplate",
+ component: ListViewSegmentedBarPageComponent,
+ data: { title: "segmentedBarTemplate" } },
{
path: "listView/nestedTemplate",
component: ListViewWithNestedTemplateComponent,
diff --git a/e2e/tests-app-ng/app/list-view/list-view-main-page.component.ts b/e2e/tests-app-ng/app/list-view/list-view-main-page.component.ts
index d08c565ba..3b7e95756 100644
--- a/e2e/tests-app-ng/app/list-view/list-view-main-page.component.ts
+++ b/e2e/tests-app-ng/app/list-view/list-view-main-page.component.ts
@@ -7,6 +7,7 @@ import { Component } from "@angular/core";
+
diff --git a/e2e/tests-app-ng/app/list-view/list-view-nested-segmented-bar-page.component.ts b/e2e/tests-app-ng/app/list-view/list-view-nested-segmented-bar-page.component.ts
new file mode 100644
index 000000000..ec0d9d963
--- /dev/null
+++ b/e2e/tests-app-ng/app/list-view/list-view-nested-segmented-bar-page.component.ts
@@ -0,0 +1,127 @@
+import { Component, ViewChild, ElementRef, OnInit } from "@angular/core";
+import { SegmentedBarItem, SegmentedBar } from "tns-core-modules/ui/segmented-bar/segmented-bar";
+import { ListView } from "tns-core-modules/ui/list-view/list-view";
+import { EventData } from "tns-core-modules/ui/page/page";
+
+interface DataItem {
+ id: number;
+ name: string;
+ type: string;
+}
+
+@Component({
+ moduleId: module.id,
+ selector: "segmented-bar-list-test",
+ template: `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `,
+})
+export class ListViewSegmentedBarPageComponent implements OnInit {
+ public displayedItems: Array = [];
+ public items: Array;
+ public segmentedBarItems: SegmentedBarItem[] = this.createSegmentedBarItems();
+
+ @ViewChild("listViewTest", { static: false })
+ private listViewTest?: ElementRef;
+
+ constructor() {
+ this.items = [];
+
+ for (let i = 0; i < 20; i++) {
+ const type = "dataItemTemplate";
+
+ this.items.push({
+ id: i,
+ name: `data item ${i}`,
+ type: type,
+ });
+ }
+ }
+
+ public ngOnInit() {
+ this.displayedItems = this.updateItems(true);
+ }
+
+ public onButtonPress() {
+ // tslint:disable-next-line: no-unused-expression
+ new Promise((resolve) => {
+ setTimeout(() => {
+ if (this.listViewTest) {
+ console.log("Scrolling to the top of the list...");
+ const listView = this.listViewTest.nativeElement as ListView;
+ listView.scrollToIndex(0);
+ }
+ resolve();
+ }, 150);
+ });
+
+ this.displayedItems = this.updateItems(false);
+ }
+
+ public onSegmentedBarPress(args: EventData) {
+ if (args && args.object) {
+ const segmentBar = args.object as SegmentedBar;
+ const selectedOdd = segmentBar.selectedIndex === 0;
+ this.displayedItems = this.updateItems(selectedOdd);
+ }
+ }
+
+ public createSegmentedBarItems() {
+ const itemOdd = new SegmentedBarItem();
+ itemOdd.title = "Odd Items";
+ const itemEven = new SegmentedBarItem();
+ itemEven.title = "Even Items";
+ return [itemOdd, itemEven];
+ }
+
+ public templateSelector(item: DataItem): string {
+ return item.type;
+ }
+
+ private updateItems(odd: boolean) {
+ const items = [
+ {
+ id: -1,
+ name: "Segmented Bar",
+ type: "segmentedBarTemplate",
+ },
+ ...(odd
+ ? this.items.filter((item) => item.id % 2 === 1)
+ : this.items.filter((item) => item.id % 2 === 0)),
+ {
+ id: 999,
+ name: "Refresh test",
+ type: "buttonTemplate",
+ },
+ ];
+ return items;
+ }
+}
diff --git a/nativescript-angular/view-util.ts b/nativescript-angular/view-util.ts
index c16794e6c..5d0e4a9db 100644
--- a/nativescript-angular/view-util.ts
+++ b/nativescript-angular/view-util.ts
@@ -260,6 +260,10 @@ export class ViewUtil {
}
private removeLayoutChild(parent: NgLayoutBase, child: NgView): void {
+ if (isLogEnabled()) {
+ traceLog(`ViewUtil.removeLayoutChild parent: ${parent} child: ${child}`);
+ }
+
const index = parent.getChildIndex(child);
if (index !== -1) {
@@ -371,6 +375,12 @@ export class ViewUtil {
const propMap = this.getProperties(view);
const propertyName = propMap.get(attributeName);
+
+ // Ensure the children of a collection currently have no parent set.
+ if (Array.isArray(value)) {
+ this.removeParentReferencesFromItems(value);
+ }
+
if (propertyName) {
// We have a lower-upper case mapped property.
view[propertyName] = value;
@@ -381,6 +391,18 @@ export class ViewUtil {
view[attributeName] = value;
}
+ private removeParentReferencesFromItems(items: any[]): void {
+ for (const item of items) {
+ if (item.parent && item.parentNode) {
+ if (isLogEnabled()) {
+ traceLog(`Unassigning parent ${item.parentNode} on value: ${item}`);
+ }
+ item.parent = undefined;
+ item.parentNode = undefined;
+ }
+ }
+ }
+
private getProperties(instance: any): Map {
const type = instance && instance.constructor;
if (!type) {