locked
Implementing IListDataAdapter.change RRS feed

  • Question

  • I'm creating a custom data source for the ListView but I am having trouble implementing the IListDataAdapter change() method so that I can edit records in the data source. I get the following exception:

    Exception was thrown but not handled in user code at line 6691, column 21 in ms-appx://microsoft.winjs.1.0.rc/js/ui.js
    0x800a138f - JavaScript runtime error: Unable to set property 'itemNew' of undefined or null reference

    The relevant lines of code are in the onEditComplete() method in the ui.js library:

    } else if (edit.editType === EditType.change) {
        //#DBG _ASSERT(slot.item);
        slot.itemNew = item;
    
        if (!reentrant) {
            changeSlotIfNecessary(slot);
        }
    }
    

    When the onEditComplete() method is called, slot does not have a value and a null reference exception is thrown.

    My implementation of the IListDataAdapter.change method looks like this:

    change: function(key, changedData, indexHint) {
        var that = this;
        return new WinJS.Promise(function (complete, error) {
            that._ensureData().then(function (data) {
                var i = that._getIndexFromKey(data.items, key);
                var changedItem = {
                    key: key,
                    index: indexHint,
                    data: changedData
                };
                data.items[i] = changedItem;
                that._saveData(data).then(function () {
                    complete(changedItem);
                });
            });
        });
    },
    

    I've tried both including and not including the indexHint when I return the IItem, but I get the same exception in either case.

    Advice here would be appreciated!

      -- Stephen

    Saturday, July 14, 2012 3:38 PM

Answers

  • Hi Stephen,

    Good catch. It seems that topic in the docs for VDS somehow escaped the doc review process, and need some more work. We'll fix them.

    It turns out the IListDataSource.change function should return a promise that does not yield a value, so use promise.wrap() or promise.wrap(null). The reason for it returning a promise is to indicate that the datasource has finished the commit for the data, and it was successful. So if you change the code to:

    change: function (key, data, indexHint) {
        var newItem = {
            key: key+"new",
            data: data
        };
        var i = this._getIndexFromKey(key);
        this._arrayData[i] = data;
        return new WinJS.Promise.wrap(null);
    },

    it should work as expected. The insertXXXX methods return an item so that the datasource can update the item with the key.

    Sam

     

    • Marked as answer by S Walther Saturday, July 21, 2012 4:09 AM
    Friday, July 20, 2012 9:34 PM

All replies

  • Hi,

    Base on my understanding, since it is a complex scenario, it would be better if you can share your demo project to SkyDrive, then we can find the issue conveniently and provide further suggestions for you.

    Best Regards,

    Ming Xu.


    Please mark the replies as answers if they help or unmark if not.
    If you have any feedback about my replies, please contact msdnmg@microsoft.com.
    Microsoft One Code Framework

    Tuesday, July 17, 2012 10:51 AM
    Moderator
  • Hi Ming,

    Sure -- I have a simple implementation of a custom data source located here:

    http://sdrv.ms/Mv1GxR

    If you select an item in the ListView and click the Edit button then you get the error described above when the change() method is called.

      -- Stephen

    Tuesday, July 17, 2012 3:39 PM
  • Hi,

    In the onEditComplete function, the slot variable is defined in the if branch:
     
            function onEditComplete(item) {
                if (item) {
                    if (keyUpdate && keyUpdate.key !== item.key) {
                            var slot = keyUpdate.slot;
    // …
                    } else if (edit.editType === EditType.change) {
                        //#DBG _ASSERT(slot.item);
                        slot.itemNew = item;
                    }
                }
            }
     
    So if you enter the else branch, slot is never defined. Thus you get the error.

    If you treat it is a bug, you can also report it on http://connect.microsoft.com/visualstudio.

    Best Regards,

    Ming Xu.


    Please mark the replies as answers if they help or unmark if not.
    If you have any feedback about my replies, please contact msdnmg@microsoft.com.
    Microsoft One Code Framework


    Wednesday, July 18, 2012 10:58 AM
    Moderator
  • Hi Ming,

    Is that really the right place to report bugs in WinJS?  I only see areas to report bugs on Visual Studio, .NET framework, and Silverlight -- there is no area for submitting a Metro/WinJS bug.

      -- Stephen

    Wednesday, July 18, 2012 4:46 PM
  • Hi Stephen,

    I will check this out further for you!

    Could you put a complete project up there for me to look at rather than me trying to piece together a repro from your datasource?

    -Jeff


    Jeff Sanders (MSFT)

    Thursday, July 19, 2012 12:27 PM
    Moderator
  • Okay, I created an archive named BadChange.zip which includes the project at http://sdrv.ms/Mv1GxR

    Select a task and click the Edit button to create the error.

       -- Stephen

    Thursday, July 19, 2012 5:21 PM
  • Hi Stephen,

    Good catch. It seems that topic in the docs for VDS somehow escaped the doc review process, and need some more work. We'll fix them.

    It turns out the IListDataSource.change function should return a promise that does not yield a value, so use promise.wrap() or promise.wrap(null). The reason for it returning a promise is to indicate that the datasource has finished the commit for the data, and it was successful. So if you change the code to:

    change: function (key, data, indexHint) {
        var newItem = {
            key: key+"new",
            data: data
        };
        var i = this._getIndexFromKey(key);
        this._arrayData[i] = data;
        return new WinJS.Promise.wrap(null);
    },

    it should work as expected. The insertXXXX methods return an item so that the datasource can update the item with the key.

    Sam

     

    • Marked as answer by S Walther Saturday, July 21, 2012 4:09 AM
    Friday, July 20, 2012 9:34 PM
  • Thanks Sam!  Really appreciate the answer. That works great!  All of my data sources are working now.

       -- Stephen

       

    Saturday, July 21, 2012 4:09 AM