locked
Cannot get groupDataSource to work with WinJS.xhr

    Question

  • Here's my code

    ViewModel.js

    /// <reference path="../../default.html" />
    (function () {
        "use strict";
        WinJS.Namespace.define("AppData", {
    
            dataStuff:null
        });
        var ContactList = new WinJS.Binding.List(null, { binding: true });
        var GroupList = null;
    
            //Adds a contact to the grid. Accepts a Array of Objects.
        function addContact(gridObject) {
            //iterate through the collection of objects            
            this.bindData('?a=add&fname=' + gridObject.firstName + '&lname=' + gridObject.lastName + '&picture=' + gridObject.picture);
    
        }
            //Binds data once the control has loaded
        function bindData(params) {
            //assigns the ContactList binding list to a local variable
            var contactList = this.ContactList;
            var param = (params != null && typeof (params) !== 'undefined') ? params : '?a=""';
            if (contactList.length > 0) {
                contactList.splice(0, contactList.length);
            }
            //Returned object from the ajax request
            this.ajax(param).done(
                //Function to handle once the request has completed
               function completed(request) {
                   //convert all the data to objects and assign it to gridObject
                   var gridObject = eval(request.response);
                   //Remove all the data in the list, since new changes have took place
                   contactList.oniteminserted = function (e) {
                       var msg = e.detail.value.firstName;
                   }
                   //contactList.splice(0, contactList.length);
    
                   //iterate through the collection of objects
                   for (var i = 0; i < gridObject.length; i++) {
                       //Adds a contact to the grid as an observable object
                       contactList.push(WinJS.Binding.as({ category: gridObject[i].category, firstName: gridObject[i].firstName, lastName: gridObject[i].lastName, picture: gridObject[i].picture }));
    
                   }
                   AppData.dataStuff = contactList.createGrouped(function (data) { return data.category }, function (data) { return { category: data.category } });
                   ContactViewModel.populateView();
               },
               //Function to handle the data while in progress
               function progress() { },
               //Function to handle the data when errors out
               function error() { });
    
    
        }
        function populateView() {
            ContactViewModel.GroupList = AppData.dataStuff.groups.dataSource;
        }
            //Deletes a contact in the grid. Accepts a Array of Objects.
        function deleteContact (deleteObjects) {
            //Iterates through the deleteObjects array
            for (var i = 0; i < deleteObjects.length; i++) {
                //Deletes the ith element in the grid
                //'splice' accepts three arguments.
                //The first argument is the position of the item
                //Second argument is the number of items to remove from that position. 
                //In this case, I want to just remove the selected object, nothing else.
                //Third argument the new item that you want to add. In this case I don't
                //want anything to be added, so left it blank
                this.ContactList.splice(deleteObjects[i], 1);
            }
        }
            //Updates a contact in the grid.
            //gridItemToUpdate: the array that contains the selected item number
            //gridObject: the array that contains the data to be updated
        function updateContact (gridItemToUpdate, gridObject) {
            //Iterates through the gridItemToUpdate array
            for (var i = 0; i < gridItemToUpdate.length; i++) {
                //Sets the position that needs to be updated in the array
                //and the new values that needs to be updated.
                this.ContactList.setAt(gridItemToUpdate[i], gridObject[i]);
            }
        }
        function searchContact (queryText) {
            this.bindData('?a=search&searchtext=' + queryText);
        }
            //Function to call the ajax request
        function ajax (params) {
            //returns the xhr object that contains the data
            return WinJS.xhr({ url: "http://www.csmasterpiece.com/team.php" + params });
        }
        //Defines a namespace for the ContactViewModel
        WinJS.Namespace.define("ContactViewModel", {
            ajax: ajax,
            searchContact: searchContact,
            addContact: addContact,
            deleteContact: deleteContact,
            updateContact: updateContact,
            ContactList: ContactList,
            bindData: bindData,
            appData: AppData.dataStuff,
            populateView: populateView,
            GroupList:GroupList
            
        });
    })();

    ContactList.html

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <title>contactList</title>
    
        <!-- WinJS references -->
        <link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" />
        <script src="//Microsoft.WinJS.1.0/js/base.js"></script>
        <script src="//Microsoft.WinJS.1.0/js/ui.js"></script>
    
        <link href="/Controls/ContactList/contactList.css" rel="stylesheet" />
        <script src="/Controls/ContactList/viewModel.js"></script>
        <script src="/Controls/ContactList/contactList.js"></script>
    
    </head>
    <body>
        <div class="contactList fragment">
            <header aria-label="Header content" role="banner">
                <button class="win-backbutton" aria-label="Back" disabled type="button"></button>
                <h2 class="titlearea win-type-ellipsis">
                    <span class="pagetitle"><span data-win-bind="textContent:listName"></span></span>
                </h2>
                <p data-win-bind="textContent:description"></p>
            </header>
            <section aria-label="Main content" role="main">
                <div>
                    <div style="float: left">
                        <div id="fName">
                            FirstName:<br />
                            <input type="text" id="txtFname" />
    
                        </div>
                        <div id="lName">
                            LastName:<br />
                            <input type="text" id="txtLname" />
                        </div>
                        <div id="txtPicPath">
                            Picture:<br />
                            <input type="text" id="txtPicture" />
                        </div>
                        <div>
                            <button id="addContact">Add Contact</button>
                            <button id="deleteContact">Delete Contact</button>
                            <button id="updateContact">Update Contact</button>
                        </div>
                    </div>
                    <div id="headerTemplate" data-win-control="WinJS.Binding.Template"
                        style="display: none">
                        <div class="simpleHeaderItem">
                            <h1 data-win-bind="innerText: category"></h1>
                        </div>
                    </div>
    
                    <div id="mediumListIconTextTemplate" data-win-control="WinJS.Binding.Template" style="display: -ms-grid; float: right">
                        <div style="width: 282px; height: 70px; padding: 5px; overflow: hidden; display: -ms-grid;">
    
                            <!-- Displays the "picture" field. -->
                            <img data-win-bind="alt: firstName; src: picture"
                                src="#"
                                style="width: 60px; height: 60px; margin: 5px; -ms-grid-column: 1;" />
                            <div style="margin: 5px; -ms-grid-column: 2">
    
                                <!-- Displays the "title" field. -->
                                <h4 data-win-bind="innerText: firstName"></h4>
    
                                <!-- Displays the "text" field. -->
                                <h6 data-win-bind="innerText: lastName"></h6>
                            </div>
                        </div>
                    </div>
    
                    <div id="basicListView" data-win-control="WinJS.UI.ListView"
                        data-win-options="{itemDataSource : ContactViewModel.ContactList.dataSource, itemTemplate: select('#mediumListIconTextTemplate'), layout : {type: WinJS.UI.GridLayout}, tapBehavior:'toggleSelect', selectionMode:'single', groupDataSource:ContactViewModel.GroupList, groupHeaderTemplate:select('#headerTemplate')}">
                    </div>
    
                </div>
            </section>
        </div>
    </body>
    </html>
    

    ContactList.js

    // For an introduction to the Page Control template, see the following documentation:
    // http://go.microsoft.com/fwlink/?LinkId=232511
    (function () {
        "use strict";
        //Get the search for this view
        var search = Windows.ApplicationModel.Search.SearchPane.getForCurrentView();
    
        var ContactListObject = WinJS.UI.Pages.define("/Controls/ContactList/contactList.html", {
            // This function is called whenever a user navigates to this page. It
            // populates the page elements with the app's data.
            ready: function (element, options) {
                options = options || {};
                this._data = WinJS.Binding.as({ listName: options.listName, description: options.description });
               // var search = Windows.ApplicationModel.Search.SearchPane.getForCurrentView();
    
                WinJS.Binding.processAll(element, this._data);
                // TODO: Initialize the page here
    
                this._bind();
    
                //ContactViewModel.populateView();
                WinJS.Utilities.query("#addContact", element).listen("click",
                    this._add.bind(this)
                 );
                WinJS.Utilities.query("#deleteContact", element).listen("click",
                    this._del.bind(this)
                );
                WinJS.Utilities.query("#updateContact", element).listen("click",
                    this._update.bind(this)
                );
                //Event that triggers when the query is submitted
                /*search.onquerysubmitted = function (args) {
                    //Pass it to the model's search contact method and pass the searchtext
                    ContactViewModel.searchContact(args.queryText);
                };*/
                
            },
            listName:{
                get:function () {return this._data.listName;},
                set: function (value) { this._data.listName = value; }
            },
            description: {
                get: function () { return this._data.description; },
                set: function (value) { this._data.description = value; }
            },
            _add: function (evt) {            
                    var data = {
                        'firstName': document.getElementById("txtFname").value,
                        'lastName': document.getElementById("txtLname").value,
                        'picture': document.getElementById("txtPicture").value
                    };
                    ContactViewModel.addContact(data);           
            },
            _bind: function () {
                ContactViewModel.bindData();
            },
            _update: function () {
                //Gets the list view control/div tag in the page
                var listView = document.getElementById("basicListView").winControl;
                //Create a array object which contains the first name, last name, and picture and set the 
                //values typed from the input boxes
                var gridItem = [{ 'firstName': document.getElementById("txtFname").value, 'lastName': document.getElementById("txtLname").value, 'picture': document.getElementById("txtPicture").value }];
                //listView.selection.getIndices() : Passes the selection that was selected in the list
                //gridItem: the array object that contains the data that needs to be updated
                ContactViewModel.updateContact(listView.selection.getIndices(), gridItem);
            },
            _del: function () {
                //Gets the list view control/div tag in the page
                var listView = document.getElementById("basicListView").winControl;
                //Passes the selection that was selected in the list.
                //'listView.selection.getIndices()' contains an selected items array.
                //This will only have one item in the array, since, selectionMode in the grid is single.
                //i.e. only one item can be selected in the list.
                ContactViewModel.deleteContact(listView.selection.getIndices());
                
            },     
            unload: function () {
                // TODO: Respond to navigations away from this page.
            },
    
            updateLayout: function (element, viewState, lastViewState) {
                /// <param name="element" domElement="true" />
    
                // TODO: Respond to changes in viewState.
            }
    
        });
        WinJS.Namespace.define("ContactList", {
            PageControl: ContactListObject
        });
    })();
    
    I dont know why its not rendering the groupdatasource...please help

    Tuesday, July 30, 2013 1:52 AM

Answers

  • Ok, I got it working. I had to add the createGrouped function in the GroupList variable itself rather than assigning the function in the ajax.done method.
    • Marked as answer by vsajinda Sunday, August 11, 2013 7:47 PM
    Sunday, August 11, 2013 7:47 PM

All replies

  • What do you see when you debug this?

    Can you provide a complete project that reproduces the problem (perhaps share on skyDrive)?


    Jeff Sanders (MSFT)

    @jsandersrocks - Windows Store Developer Solutions @WSDevSol
    Getting Started With Windows Azure Mobile Services development? Click here
    Getting Started With Windows Phone or Store app development? Click here
    My Team Blog: Windows Store & Phone Developer Solutions
    My Blog: Http Client Protocol Issues (and other fun stuff I support)

    Wednesday, July 31, 2013 2:46 PM
    Moderator
  • Here is the sample in SkyDrive

    The zip file is MVVMTestPages

    http://sdrv.ms/1aXJQeY


    • Edited by vsajinda Thursday, August 1, 2013 1:04 AM forgot to include name of file
    Thursday, August 1, 2013 1:01 AM
  • I pulled down the project thanks!

    Can you tell me where you are displaying the group?  I see the group data being created successfully but not sure where you are displaying it.  Please provide step by step directions.


    Jeff Sanders (MSFT)

    @jsandersrocks - Windows Store Developer Solutions @WSDevSol
    Getting Started With Windows Azure Mobile Services development? Click here
    Getting Started With Windows Phone or Store app development? Click here
    My Team Blog: Windows Store & Phone Developer Solutions
    My Blog: Http Client Protocol Issues (and other fun stuff I support)

    Thursday, August 1, 2013 4:34 PM
    Moderator
  • It is in my my ContactList.html page that I am binding the groupDataSource. 

    <div id="basicListView" data-win-control="WinJS.UI.ListView"
                        data-win-options="{itemDataSource : ContactViewModel.ContactList.dataSource, itemTemplate: select('#mediumListIconTextTemplate'), layout : {type: WinJS.UI.GridLayout}, tapBehavior:'toggleSelect', selectionMode:'single', groupDataSource:ContactViewModel.GroupList, groupHeaderTemplate:select('#headerTemplate')}">
                    </div>

     If you look at the ViewModel.js, you will see that I am using a variable called dataStuff in the AppData namespace to capture the group information. Next, I'm using another method called populateView to get the data from AppData.dataStuff and assigning to variable called GroupList. Finally, I expose this variable in the ContactViewModel GroupList for binding in page.

    Friday, August 2, 2013 12:15 AM
  • Hi Jeff,

    were you able to look into the problem

    Tuesday, August 6, 2013 9:36 PM
  • No sorry,

    I really need to get step by step instructions from you.  I could probably spend a bunch of time trying to figure out what to do to create the problem, but if you simply provide instructions to repro the issue along with expected result vs actual result, I can look at this quickly.

    -Jeff


    Jeff Sanders (MSFT)

    @jsandersrocks - Windows Store Developer Solutions @WSDevSol
    Getting Started With Windows Azure Mobile Services development? Click here
    Getting Started With Windows Phone or Store app development? Click here
    My Team Blog: Windows Store & Phone Developer Solutions
    My Blog: Http Client Protocol Issues (and other fun stuff I support)

    Wednesday, August 7, 2013 12:37 PM
    Moderator
  • In the ajax.done() found in the bindData method in ViewModel.js, returns the completed request. Each object returned has an associated key called category. Each object could fall into the category value Team A or Team B. All I want is to bind the category to the basicListView's groupDataSource. Right now it doesn't bind this data in the basicListView.


    Let me know if this is clear.


    • Marked as answer by vsajinda Friday, August 9, 2013 6:29 PM
    • Unmarked as answer by vsajinda Friday, August 9, 2013 6:29 PM
    • Marked as answer by vsajinda Friday, August 9, 2013 6:30 PM
    • Unmarked as answer by vsajinda Friday, August 9, 2013 6:30 PM
    Wednesday, August 7, 2013 4:18 PM
  • Ok, I got it working. I had to add the createGrouped function in the GroupList variable itself rather than assigning the function in the ajax.done method.
    • Marked as answer by vsajinda Sunday, August 11, 2013 7:47 PM
    Sunday, August 11, 2013 7:47 PM