locked
Unable to iterate/select listview elements reliably after the page has loaded?

    Question

  • I'm trying to iterate over a listview that i have created AFTER it has loaded, so i can update the content of each element dynamically (using ajax). So it's important that the listview is loaded in 'flat' view, and then i bring it to life.

    The problem i have, is that the event that i'm tapping into only works a small number of times in so far as getting references to the items in the DOM are not actually 'there' when i'm trying to select them. So obviously i'm trying to get these at the wrong point in time.

    What i have so far setting this up, in my page control 

    ready: function (element, options) {

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

                function initialize() {
                    WinJS.UI.processAll().done(function () {
                        updateListView();
                    });
                }

    }

    ... So presumably we are waiting for the DOM content to finish loading, then setting up a promise to run our update, once our WinJS elements have been processed.

    Now, inside my updateListView() method :

                 Data.refreshUserInterfaceItems.forEach(function (item) {
                            // Get a reference to each listview element here, update it's tile/view with an ajax 'in progress' indicator that 
                            // goes off and updates each tile before fading it back in.
                            var thisTile = document.querySelector("#" + item.associatedReport);

                            if (thisTile != null) {}

    }

    ... So the check on 'thisTile' not being null only returns true a handful of times.

    So is there a more reliable event i can tap into with the ListView or the Page/Document itself so i know everything is loaded and ready before i start making DOM seletctions???

    Friday, July 6, 2012 10:52 AM

Answers

  • ready: fires after DOMContentLoaded has already fired (see line 293 of base.js).  The quickstarts do not utilize the templates provided by Visual Studio and that is why they sync DOMContentLoaded.

    Here is the order of how these events get fired and what they correspond to:

        // loaded == DOMContentLoaded
        // activated == after WinRT Activated
        // ready == after all of the above

    Items in the list view are rendered Async so there is no convinient way to know when all things are rendered (you can look into this in ui.js).

    You should take advantage of the custom render function and templates to generate your output instead of trying to modify the ListView DOM directly.  If you cannot use the build in functionality of ListView you should create your own control.

    -Jeff


    Jeff Sanders (MSFT)

    Tuesday, July 10, 2012 12:37 PM
    Moderator

All replies

  • Do not try and iterate over the listview items manually.  For an intro on how to use ListView see this quickstart, and the samples listed at the end of this document: http://msdn.microsoft.com/en-us/library/windows/apps/hh465496.aspx

    Do not add a listener for DOMContentLoaded in your page control because 'ready' fires when the content is loaded.

    -Jeff


    Jeff Sanders (MSFT)

    Friday, July 6, 2012 12:05 PM
    Moderator
  • I'm not trying to iterate over the Listview items as a WinJS object.

    I'm trying to manipulate the DOM after everything is loaded, the listview has databound, and the 'browser' has displayed rendered HTML to the screen. The query selectors i'm using try to access the various DIV elements that have been created through the listview templates.

    I've used the quickstart as my starting basis for this particular task, and bound items to the listview in the manner that has been setout. The issue i'm having is that i'm assuming that once we have things databound and displayed, we are free to manipulate the DOM in the manner i'm used to as per regular web development.

    Unless of course you are suggesting that this is not the 'metro' way of doing things?

    Friday, July 6, 2012 12:31 PM
  • Depending on the size of the underlying data, items can be added on the fly to the listview as you scroll items into view so it is possible that everything is not loaded into the DOM.

    What are you trying to accomplish?


    Jeff Sanders (MSFT)

    • Proposed as answer by satish sagar Friday, April 26, 2013 8:39 AM
    Friday, July 6, 2012 12:33 PM
    Moderator
  • All i'm trying to do is use my databound listview to output a 'skeleton' of markup to the page, which functions in the normal way as a listview would.

    After this has output, i want to update the content (not the underlying data, i just want to make changes to the dom for visual effect) via various async calls to various data sources.

    In effect, it makes the listview elements look 'alive'. 

    Of course, i could just loop over my datasource, and manually output some elements to the page, but wanted the flexibility that the listview offers in terms of scrolling, databinding and contextual zoom.

    Friday, July 6, 2012 1:47 PM
  • Images have the potential to load lazy.  Other than that you should be able to walk the DOM.  Note however these names are auto generated and could change in the next revision.

    Jeff Sanders (MSFT)

    Friday, July 6, 2012 6:29 PM
    Moderator
  • I'm still not getting the results i expect.

    Interesting that you mention above not to listen for the "DOMContentLoaded" event. I've used this code from the quickstarts which advice using this event as a basis for handing the WinJS.UI.processAll().done() event. If i just wrap my call to my listview 'DOM walking' code with the WinJS.UI.processAll().done() event without the DOMContentLoaded event, all attempts to traverse the DOM result in null values as it appears everything is not yet set up.

    I'm fairly sure i'm still doing something wrong, since although i can appear to modify the listview DOM elements (using the debugger to check), they actually display only 10-20% of the time, usually when setting breakpoints and the like. 

    Tuesday, July 10, 2012 8:28 AM
  • ready: fires after DOMContentLoaded has already fired (see line 293 of base.js).  The quickstarts do not utilize the templates provided by Visual Studio and that is why they sync DOMContentLoaded.

    Here is the order of how these events get fired and what they correspond to:

        // loaded == DOMContentLoaded
        // activated == after WinRT Activated
        // ready == after all of the above

    Items in the list view are rendered Async so there is no convinient way to know when all things are rendered (you can look into this in ui.js).

    You should take advantage of the custom render function and templates to generate your output instead of trying to modify the ListView DOM directly.  If you cannot use the build in functionality of ListView you should create your own control.

    -Jeff


    Jeff Sanders (MSFT)

    Tuesday, July 10, 2012 12:37 PM
    Moderator
  • Hi Jeff,

    This explains it perfectly. Thanks. Seems like trying to manipulate the DOM in this manner (and have it reflect visually) is not going to work how i want it to.

    Can you point me in any useful directions with regards to the custom render function you mentioned?

    Cheers,

    Mark

    Tuesday, July 10, 2012 12:43 PM
  • Tuesday, July 10, 2012 12:49 PM
    Moderator
  • Perfect. EXACTLY what i need.

    Thank's Jeff :)
    Tuesday, July 10, 2012 12:59 PM