locked
'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

All replies

  • Friday, April 20, 2012 1:07 PM
    Moderator
  • 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 PM
    Moderator
  • 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)

    Tuesday, April 24, 2012 2:16 PM
    Moderator
  • 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)

    Wednesday, April 25, 2012 1:32 PM
    Moderator