1 Reply Latest reply on Sep 14, 2018 2:29 PM by John Snyders-Oracle

    "Windowing" Approach to Interactive Reports/Grids

    Joe Upshaw

      Application Express


      This might turn out to be a new feature request...but, if anyone has figured out a way to do this, we'd be very, very grateful.


      The problem we're trying to solve...please just accept that we honestly do have some requirements where the end user must review/change thousands of rows and wants to be able to scroll through and/or affect large percentages of them.


      Obviously, we can't simply load all of the rows into the DOM as this kills the browser's memory. However, the usual APEX pagination just doesn't work for us either. We can't use the fixed header scrollable approach for the same reason, i.e. all rows are actually in the dom but, only some are displayed in the "view port" as determined by the current scroll position.


      To address this very need, some JS frameworks support the notion of "windowing" where rows are dynamically placed into and removed from the dom as the user scrolls, e.g. React, Angular2.


      Has anyone seen something similar put into place within APEX? If not, do we know if there might be any appetite for "virtual DOM" capabilities in upcoming APEX versions?





        • 1. Re: "Windowing" Approach to Interactive Reports/Grids
          John Snyders-Oracle

          Hi Joe,

          The architecture of Interactive Grid is designed to handle this kind of thing but not yet fully realized. This is a great question to illustrate how IG and more specifically the grid widget works.


          You said: "We can't use the fixed header scrollable approach for the same reason, i.e. all rows are actually in the dom but, only some are displayed in the "view port" as determined by the current scroll position"


          This isn't exactly true. Based on the scroll bar size it may look like all the rows are in the DOM but they are not. Currently data from the model layer is rendered to the DOM as the user scrolls. What is currently not implemented is removing rows from the DOM if they are far away from the view port.


          Motivated by your interesting use case I did the following interactive experiment using the Sample Interactive Grid app page Pagination: Scroll.

          Open the JavaScript console

          Scroll down a few hundred rows (~500). Enough to see the spinner, which indicates more data being added to the model.

          Examine the DOM Note there are many tr elements but the last one is different. It looks like this:
          <tr class="a-GV-scrollFiller" data-start="560" data-end="4143" style="height: 114656px;"><td colspan="8"></td></tr>

          So there aren't really 4143 rows rendered; couldn't be because the client side model doesn't even have this many rows yet.

          Then I entered these commands:

          $("#people .a-GV tbody").first().find("tr").length

          // This just shows how many actual rows are rendered including the filler row.

          $("#people .a-GV tbody tr:lt(100)").remove()  // remove the first 100 rows from the DOM (note there are two tbody elements)

          $("#people .a-GV tbody").first().find("tr").length

          // now this shows there are 100 less rows in the DOM

          $("#people .a-GV tbody").prepend('<tr class="a-GV-scrollFiller" data-start="0" data-end="99" style="height: 3200px;"><td colspan="8"></td></tr>');

          $("#people .a-GV tbody").first().find("tr").length

          //Just one new row added.


          Scroll back up to the top. Notice that new rows are rendered again. There are glitches. One time I noticed I got some duplicate rendered rows but this is just a display issue the data including any edits will be kept safe and correct in the model.


          It would probably be difficult to turn this experiment into a working solution. Would need to know when and which rows to remove. Also the markup details like class a-GV-scrollFiller are an internal detail that could change. Hopefully in the future the grid widget will efficiently remove rows as needed.


          Have you tried using IG for this use case? How many rows can it handle before it gets too slow? Reducing the number of visible columns may help.