Answered by:
'bind' in base.js is not supported when bing a nested array to ListView template

Question
-
I wanted to bind the nested array to a list view but got the following exception. However, if I just bind a normal array to it, it works. Does it mean i cannot bind nested array? Any help would be appreciated.
When i tried to run this application, an exception was thrown:
Exception was thrown at line 6687, column 17 in ms-appx://microsoft.winjs.0.6.debug-8wekyb3d8bbwe/js/base.js 0x800a01b6 - JavaScript runtime error: Object doesn't support property or method 'bind' File: base.js, line: 6687 column: 17
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Application9</title> <!-- WinJS references --> <link href="//Microsoft.WinJS.0.6/css/ui-dark.css" rel="stylesheet"> <script src="//Microsoft.WinJS.0.6/js/base.js"></script> <script src="//Microsoft.WinJS.0.6/js/ui.js"></script> <!-- Application9 references --> <link href="/css/default.css" rel="stylesheet"> <script src="/js/default.js"></script> </head> <body> <div id="myTemplate" data-win-control="WinJS.Binding.Template"> <span data-win-bind="innerText: text"></span> <p></p> <span data-win-bind="innerText: data[0].key"></span><span data-win-bind="innerText: data[0].value"></span> <p></p> <span data-win-bind="innerText: data[1].key"></span><span data-win-bind="innerText: data[1].value"></span> </div> <div id="basicListView" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource : SmapleData.itemList.dataSource , itemTemplate: select('#myTemplate')}"> </div> </body> </html>
// For an introduction to the Blank template, see the following documentation: // http://go.microsoft.com/fwlink/?LinkId=232509 (function () { "use strict"; var app = WinJS.Application; app.onactivated = function (eventObject) { if (eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) { if (eventObject.detail.previousExecutionState !== Windows.ApplicationModel.Activation.ApplicationExecutionState.terminated) { // TODO: This application has been newly launched. Initialize // your application here. init(); } else { // TODO: This application has been reactivated from suspension. // Restore application state here. } WinJS.UI.processAll(); } }; function init() { var dataArray = [ { text: "test1", data:[{key: "key1", value: "value1"},{key: "key2", value: "value2"}] }, { text: "test2", data: [{ key: "key3", value: "value3" }, { key: "key4", value: "value4" }] } ]; var dataList = new WinJS.Binding.List(dataArray); var publicMembers = { itemList: dataList }; WinJS.Namespace.define("SmapleData", publicMembers); } app.oncheckpoint = function (eventObject) { // TODO: This application is about to be suspended. Save any state // that needs to persist across suspensions here. You might use the // WinJS.Application.sessionState object, which is automatically // saved and restored across suspension. If you need to complete an // asynchronous operation before your application is suspended, call // eventObject.setPromise(). }; app.start(); })();
Thursday, April 19, 2012 8:30 AM
Answers
-
Nested templates are not supported (which is what this would take to bind automatically) however you could provide a custom renderer to draw your data.
Here is a brief discussion of custom rendering with listview: http://msdn.microsoft.com/en-us/library/windows/apps/Hh781224.aspx (see: Custom render function)
Jeff Sanders (MSFT)
- Proposed as answer by Jeff SandersMicrosoft employee, Moderator Wednesday, April 25, 2012 1:32 PM
- Marked as answer by Jiankui Saturday, April 28, 2012 1:29 AM
Wednesday, April 25, 2012 1:32 PMModerator
All replies
-
You could use a converter:
Jeff Sanders (MSFT)
- Proposed as answer by Jeff SandersMicrosoft employee, Moderator Friday, April 20, 2012 1:07 PM
Friday, April 20, 2012 1:07 PMModerator -
Looks linke convert only works in the same listview's template.
Below codes didn't work. Anyway, thanks a lot. i'm still looking for the way:(
function init() { var dataArray = [ { text: "test1", data:[{key: "key1", value: "value1"},{key: "key2", value: "value2"}] }, { text: "test2", data: [{ key: "key3", value: "value3" }, { key: "key4", value: "value4" }] } ]; var dataList = new WinJS.Binding.List(dataArray); var dataCoverter = WinJS.Binding.converter(function (theValue) { return (new WinJS.Binding.List(theValue)).dataSource; }); var publicMembers = { itemList: dataList dataCoverter: dataCoverter }; WinJS.Namespace.define("SampleData", publicMembers); }
HTML:
<div id="mySubTemplate" data-win-control="WinJS.Binding.Template"> <span>data-win-bind="innerText: key"</span><span>data-win-bind="innerText: value" </span> </div> <div id="myTemplate" data-win-control="WinJS.Binding.Template"> <span data-win-bind="innerText: text"></span> <div data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource : data SampleData.dataCoverter, itemTemplate: select('#mySubTemplate')}"> </div> </div> <div id="Div1" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource : SmapleData.itemList.dataSource , itemTemplate: select('#myTemplate')}"> </div>
Tuesday, April 24, 2012 9:36 AM -
You have a spelling error in your original and latest post:
SmapleData
Jeff Sanders (MSFT)
Tuesday, April 24, 2012 12:18 PMModerator -
A dataconverter takes the bound data element and you return the value you want to display.
So for example for value[0].key you would write a converter like this:
var dataCoverterVal0Key = WinJS.Binding.converter(function (theValue) {
return theValue[0].key;
});expose it:
var publicMembers =
{
itemList: dataList,
myConverter: dataCoverterVal0Key
};
WinJS.Namespace.define("SampleData", publicMembers);and use it: <span data-win-bind="innerText: data SampleData.myConverter"><
You would need a converter for each value.
-Jeff
Jeff Sanders (MSFT)
- Proposed as answer by Jeff SandersMicrosoft employee, Moderator Tuesday, April 24, 2012 2:16 PM
Tuesday, April 24, 2012 2:16 PMModerator -
Yes, thanks for your reply. i had noticed the typo about SampleData and updated it in my second version codes.
Your solution does work, but if the data contains more data and I want to show them on the page, without hardcoding the index 0, 1,2,3...
I want the items in the data array to be displayed via the second template "mySubTemplate" using the second listview "subListView".
the converter would return (new WinJS.Binding.List(theValue)).dataSource;
<div id="mySubTemplate" data-win-control="WinJS.Binding.Template">
<span>data-win-bind="innerText: key"</span><span>data-win-bind="innerText: value"
</span>
</div>
<div id="myTemplate" data-win-control="WinJS.Binding.Template">
<span data-win-bind="innerText: text"></span>
<div id= "subListView" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource : data SampleData.dataCoverter, itemTemplate: select('#mySubTemplate')}">
</div>
</div>
<div id="Div1" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource : SmapleData.itemList.dataSource , itemTemplate: select('#myTemplate')}">
</div>Wednesday, April 25, 2012 1:31 AM -
Nested templates are not supported (which is what this would take to bind automatically) however you could provide a custom renderer to draw your data.
Here is a brief discussion of custom rendering with listview: http://msdn.microsoft.com/en-us/library/windows/apps/Hh781224.aspx (see: Custom render function)
Jeff Sanders (MSFT)
- Proposed as answer by Jeff SandersMicrosoft employee, Moderator Wednesday, April 25, 2012 1:32 PM
- Marked as answer by Jiankui Saturday, April 28, 2012 1:29 AM
Wednesday, April 25, 2012 1:32 PMModerator