Merge pull request #1679 from NativeScript/hdeshev/listview-proxycontainer-child

Fix a crash when using a ProxyViewContainer in ListView item templates.
This commit is contained in:
Hristo Deshev
2016-03-02 10:45:26 +02:00
3 changed files with 37 additions and 5 deletions

View File

@ -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 = `
<ProxyViewContainer>
<Label text="{{$value}}"></Label>
</ProxyViewContainer>
`;
function testAction(views: Array<View>) {
var page = <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();

View File

@ -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 {

View File

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