diff --git a/apps/tests/ui/proxy-view-container/proxy-view-container-tests.ts b/apps/tests/ui/proxy-view-container/proxy-view-container-tests.ts index 5ef727832..d140d3dcb 100644 --- a/apps/tests/ui/proxy-view-container/proxy-view-container-tests.ts +++ b/apps/tests/ui/proxy-view-container/proxy-view-container-tests.ts @@ -8,6 +8,7 @@ import {LayoutBase} from "ui/layouts/layout-base" import {StackLayout} from "ui/layouts/stack-layout" import {GridLayout} from "ui/layouts/grid-layout" import {ProxyViewContainer} from "ui/proxy-view-container"; +import {ListView} from "ui/list-view"; export function test_add_children_to_attached_proxy() { var outer = new StackLayout(); @@ -224,6 +225,25 @@ export function test_proxy_iniside_border() { helper.buildUIAndRunTest(scroll, testAction); } +export function test_proxy_iniside_listview_itemtemplate_crash() { + // Usually reproducible with an Angular component in the template + // We use a simple declaration here to simulate it. + var list = new ListView(); + list.items = ["item 1"]; + list.itemTemplate = ` + + + + `; + + function testAction(views: Array) { + var page = views[1]; + waitUntilElementLayoutIsValid(page); + }; + + helper.buildUIAndRunTest(list, testAction); +} + // TODO: Proxy as a direct child to of TabItem is not supported. Not sure if we want to support it. //export function test_proxy_iniside_tab() { // var proxy = new ProxyViewContainer(); diff --git a/ui/list-view/list-view.android.ts b/ui/list-view/list-view.android.ts index f1235929c..00aad53d8 100644 --- a/ui/list-view/list-view.android.ts +++ b/ui/list-view/list-view.android.ts @@ -6,6 +6,7 @@ import proxy = require("ui/core/proxy"); import dependencyObservable = require("ui/core/dependency-observable"); import definition = require("ui/list-view"); import utils = require("utils/utils") +import {ProxyViewContainer} from "ui/proxy-view-container"; import * as layoutBase from "ui/layouts/layout-base"; import * as colorModule from "color"; @@ -229,7 +230,10 @@ function ensureListViewAdapterClass() { } this._listView._prepareItem(args.view, index); if (!args.view.parent) { - if (args.view instanceof layoutBase.LayoutBase) { + // Proxy containers should not get treated as layouts. + // Wrap them in a real layout as well. + if (args.view instanceof layoutBase.LayoutBase && + !(args.view instanceof ProxyViewContainer)) { this._listView._addView(args.view); convertView = args.view.android; } else { diff --git a/ui/list-view/list-view.ios.ts b/ui/list-view/list-view.ios.ts index 5c978798c..668aacc68 100644 --- a/ui/list-view/list-view.ios.ts +++ b/ui/list-view/list-view.ios.ts @@ -4,6 +4,8 @@ import common = require("./list-view-common"); import utils = require("utils/utils"); import view = require("ui/core/view"); import proxy = require("ui/core/proxy"); +import {StackLayout} from "ui/layouts/stack-layout"; +import {ProxyViewContainer} from "ui/proxy-view-container"; import dependencyObservable = require("ui/core/dependency-observable"); import * as colorModule from "color"; @@ -322,11 +324,18 @@ export class ListView extends common.ListView { let args = notifyForItemAtIndex(this, cell, view, ITEMLOADING, indexPath); view = args.view || this._getDefaultItemContent(indexPath.row); + // Proxy containers should not get treated as layouts. + // Wrap them in a real layout as well. + if (view instanceof ProxyViewContainer) { + var sp = new StackLayout(); + sp.addChild(view); + view = sp; + } + // If cell is reused be have old content - remove it first. if (!cell.view) { cell.owner = new WeakRef(view); - } - else if (cell.view !== view) { + } else if (cell.view !== view) { this._removeContainer(cell); (cell.view._nativeView).removeFromSuperview(); cell.owner = new WeakRef(view); @@ -341,8 +350,7 @@ export class ListView extends common.ListView { } cellHeight = this._layoutCell(view, indexPath); - } - finally { + } finally { this._preparingCell = false; } return cellHeight;