locked
Get an exception when using SemanticZoom with imperatively set data source RRS feed

  • Question

  • Hi all,

    I can get the SemanticZoom control to work when I set the ListView data sources declaratively, but not when I set the data sources imperatively.

    My HTML looks like this  (Two ListView controls in a SemanticZoom control). Notice that I am not setting the itemDataSource and groupDataSource properties here:


        <!-- SemanticZoom and ListViews -->
        <div id="divSemanticZoom" data-win-control="WinJS.UI.SemanticZoom"> 
            <!-- Zoom In ListView (Products) -->
            <div id="lvProducts"
                data-win-control="WinJS.UI.ListView"
                data-win-options="{
                    itemTemplate: select('#tmplProduct'),
                    groupHeaderTemplate: select('#tmplProductGroupHeader')
                }"></div>

            <!-- Zoom Out ListView (Categories) --> 
            <div id="lvCategories"
                data-win-control="WinJS.UI.ListView"
                data-win-options="{
                    itemTemplate: select('#tmplCategory') 

                }"></div> 
        </div>


    And, my JavaScript looks like this (notice that I am setting the ListView data sources here):

    (function () {
        "use strict";

        function initialize() {
            WinJS.UI.processAll().done(function () {
                // Get reference to ListView control
                var lvProducts = document.getElementById("lvProducts").winControl;

                // Create a List of products
                var listProducts = new WinJS.Binding.List([
                    { name: "Milk", price: 2.44, category: "Beverages" },
                    { name: "Oranges", price: 1.99, category: "Fruit" },
                    { name: "Wine", price: 8.55, category: "Beverages" },
                    { name: "Apples", price: 2.44, category: "Fruit" },
                    { name: "Steak", price: 1.99, category: "Other" },
                    { name: "Eggs", price: 2.44, category: "Other" },
                    { name: "Mushrooms", price: 1.99, category: "Other" },
                    { name: "Yogurt", price: 2.44, category: "Other" },
                    { name: "Soup", price: 1.99, category: "Other" },
                    { name: "Cereal", price: 2.44, category: "Other" },
                    { name: "Pepsi", price: 1.99, category: "Beverages" }
                ]);

                // Create grouped data source
                var groupListProducts = listProducts.createGrouped(
                    function (dataItem) {
                        return dataItem.category;
                    },
                    function (dataItem) {
                        return { title: dataItem.category };
                    },
                    function (group1, group2) {
                        return group1 > group2 ? 1 : -1;
                    }
                );

                // Bind the list of products to the Zoom In ListView
                lvProducts.itemDataSource = groupListProducts.dataSource;
                lvProducts.groupDataSource = groupListProducts.groups.dataSource;

                // Bind the list of categories to the Zoom Out ListView
                lvCategories.itemDataSource = groupListProducts.groups.dataSource;
            });

     
        }

        document.addEventListener("DOMContentLoaded", initialize);
    })();

    When I run the code above, I get the following exception:

      "JavaScript runtime error: Object.defineProperty: argument is not an Object"

    Suggestions? 

        -- Stephen

    Sunday, July 1, 2012 1:32 PM

Answers

  • Hi Stephen,

    As I said, the sample works fine if you modify it to set the datasource at runtime.  There must be an issue with how you are declaring your datasource, templates or html.

     <!-- SemanticZoom using two ListViews -->
            <div id="semanticZoomDiv" data-win-control="WinJS.UI.SemanticZoom">   
                    
                <!-- The zoomed in ListView -->
                <div id="zoomedInListView"
                    data-win-control="WinJS.UI.ListView" 
                    data-win-options="{ 
                        itemTemplate: mediumListIconTextTemplate, 
                        groupHeaderTemplate: headerTemplate, 
                        selectionMode: 'none', 
                        tapBehavior: 'none', 
                        swipeBehavior: 'none' 
                    }"
                ></div>
                <!-- The zoomed out ListView -->
                <div id="zoomedOutListView"
                    data-win-control="WinJS.UI.ListView"
                    data-win-options="{ 
                        itemTemplate: semanticZoomTemplate, 
                        selectionMode: 'none', 
                        tapBehavior: 'invoke', 
                        swipeBehavior: 'none' 
                    }"
                ></div>
      var page = WinJS.UI.Pages.define("/html/scenario2.html", {
            ready: function (element, options) {
                WinJS.UI.processAll(element);
                var lvZoomIn = document.getElementById("zoomedInListView").winControl;
                lvZoomIn.itemDataSource=myGroupedList.dataSource;
                lvZoomIn.groupDataSource = myGroupedList.groups.dataSource;
                
                var lvZoomOut = document.getElementById("zoomedOutListView").winControl;
                lvZoomOut.itemDataSource = myGroupedList.groups.dataSource;
            }
        });


    Start by changing the sample as I did to set the datasources at runtime instead of in the HTML binding attributes and backtrack what is different between the sample and your code.

    Make sense?

    -Jeff


    Jeff Sanders (MSFT)

    • Marked as answer by Dino He Friday, July 6, 2012 4:50 AM
    Monday, July 2, 2012 3:08 PM
    Moderator

All replies

  • Hi Stephen,

    Start with this sample and compare to your code.  This sample works great when assigning the data at runtime instead of as binding in the HTML (try it yourself).  I suggest you compare what you are doing with this (after making the changes to bind at runtime).

    http://code.msdn.microsoft.com/windowsapps/ListView-grouping-and-6d032cc1/

    My best guess is that you are defining the datasource incorrectly (or the grouped data source). 

    -Jeff


    Jeff Sanders (MSFT)

    Monday, July 2, 2012 2:23 PM
    Moderator
  • Hi Jeff,

    As I said, I don't have any problem getting the SemanticZoom control to work when I follow the sample and set the ListView controls itemDataSources declaratively. However, this does not work when I set the itemDataSource property in my JavaScript code like this:

     // Bind the list of products to the Zoom In ListView
     lvProducts.itemDataSource = groupListProducts.dataSource;
     lvProducts.groupDataSource = groupListProducts.groups.dataSource;

     // Bind the list of categories to the Zoom Out ListView
     lvCategories.itemDataSource = groupListProducts.groups.dataSource;

    Are you saying that the WinJS controls are not designed to be used imperatively?  That I must use the controls declaratively?  My understanding was that the WinJS controls could be used either way.

    I would prefer to set the ListView itemDataSource property imperatively because I do not want to pollute the global namespace.

      -- Stephen

    Monday, July 2, 2012 3:04 PM
  • Hi Stephen,

    As I said, the sample works fine if you modify it to set the datasource at runtime.  There must be an issue with how you are declaring your datasource, templates or html.

     <!-- SemanticZoom using two ListViews -->
            <div id="semanticZoomDiv" data-win-control="WinJS.UI.SemanticZoom">   
                    
                <!-- The zoomed in ListView -->
                <div id="zoomedInListView"
                    data-win-control="WinJS.UI.ListView" 
                    data-win-options="{ 
                        itemTemplate: mediumListIconTextTemplate, 
                        groupHeaderTemplate: headerTemplate, 
                        selectionMode: 'none', 
                        tapBehavior: 'none', 
                        swipeBehavior: 'none' 
                    }"
                ></div>
                <!-- The zoomed out ListView -->
                <div id="zoomedOutListView"
                    data-win-control="WinJS.UI.ListView"
                    data-win-options="{ 
                        itemTemplate: semanticZoomTemplate, 
                        selectionMode: 'none', 
                        tapBehavior: 'invoke', 
                        swipeBehavior: 'none' 
                    }"
                ></div>
      var page = WinJS.UI.Pages.define("/html/scenario2.html", {
            ready: function (element, options) {
                WinJS.UI.processAll(element);
                var lvZoomIn = document.getElementById("zoomedInListView").winControl;
                lvZoomIn.itemDataSource=myGroupedList.dataSource;
                lvZoomIn.groupDataSource = myGroupedList.groups.dataSource;
                
                var lvZoomOut = document.getElementById("zoomedOutListView").winControl;
                lvZoomOut.itemDataSource = myGroupedList.groups.dataSource;
            }
        });


    Start by changing the sample as I did to set the datasources at runtime instead of in the HTML binding attributes and backtrack what is different between the sample and your code.

    Make sense?

    -Jeff


    Jeff Sanders (MSFT)

    • Marked as answer by Dino He Friday, July 6, 2012 4:50 AM
    Monday, July 2, 2012 3:08 PM
    Moderator
  • Hi Jeff,

    I think we are talking past one another here :)  The only difference between my SemanticZoom code and the sample SemanticZoom code is that I am binding my ListView data sources imperatively.  I can bind imperatively in every other scenario when using the ListView control and it works fine. However, it does not seem to work with the SemanticZoom control.

    It seems to be a sequence of events issues. My code is pretty straightforward -- you can see all of my JavaScript code in the first post above -- but it doesn't work. So I am stuck and would appreciate any advice which you can provide. Again, my understanding is that using the WinJS controls imperatively is a supported use of the controls.

    Thanks!

      -- Stephen

      

    Monday, July 2, 2012 3:19 PM
  • Hi Stephen,

    I am trying to get you to debug your own code :-).  I provided the code to show how to modify the sample to bind directly in code and not declarative (you call this imperative).  You should be able to compare what I have done vs. what your code has done and figure out what may be different.  Short of that you can post your entire project and someone can look at that to determine what is different, but frankly that is all I would do (compare the example that does what you want with your code).

    -Jeff


    Jeff Sanders (MSFT)

    Monday, July 2, 2012 3:26 PM
    Moderator
  • Hi Jeff,

    My bad :)  I didn't see that you had set the data sources imperatively in your reply. I'll do some debugging -- thanks!

       -- Stephen

     

    Monday, July 2, 2012 3:38 PM