Using data tables as a scrolling virtual table

Using data tables as a scrolling virtual table

prubinprubin Posts: 26Questions: 0Answers: 0
edited October 2011 in DataTables 1.8
I apologize if this is a duplicate issue, I have been unable to find the correct search terms to find what I am looking for.

I need to use Data Tables to make a dynamically loaded scrolling table.

What do I mean? The table requests data from the server, the server then sends back the first page and then in the background loads the remaining rows and the table is scrollable. When things external to the table change the data is flushed and new data is loaded.

I have found all the api's for adding rows and deleting rows and clearing the table.

In my initial tests I am able to load the first page of data using aoColumns, fnServerData and sAjaxDataProp. I am using aoColumns and sAjaxDataProp because my data is in a JSON object that contains meta data about the whole result set and and array of the first page of data.

Where I am stuck is how to load the second page of data without coding another complete set of functions to process the next object which is in the same structure as the first, but contains then next page in the data array.

Further how can I trigger fnServerData a second time to get a completely new data set.

A minor associated piece is how to the the total record count set correctly when I am in sAjaxDataProp which is the point at which I have access to the result set information data.

Any link, examples or just pointing me to the correct functions would be greatly appreciated.

Thank you.

Replies

  • OmnimikeOmnimike Posts: 22Questions: 0Answers: 0
    You are looking for the Scroller extra, which you can get from here:
    http://www.datatables.net/extras/

    It has this example for how to use it with server side processing.
    http://www.datatables.net/release-datatables/extras/Scroller/server-side_processing.html

    There is an issue in the v1.0.0 release which spawned this thread:
    http://datatables.net/forums/discussion/5458/scroller-issue-tofrom-numbers-wrong/p1
    You may not run into this same issue like I did, but if you do you can always get the latest version of Scroller from https://github.com/DataTables/Scroller
  • prubinprubin Posts: 26Questions: 0Answers: 0
    Thank you. I think this might handle the final display issues, but I am not sure how it helps me consume the pages of data.

    I think I may have poorly explained my difficulty. The server is a 'generic' webservice it has no knowledge of the target use of the data, it is sending fairly complex data structures in pages. I am trying to use data table to consume the data in it's native form without writing server side code to render it down. This allows the client browser to for instance display a detail view of the item highlighted in the data table without going back to the server. A typical json from the server looks like this:

    { "total": 232, "start": 0, "count": 20, "data":[{"iMonitoredOOSDelegate":{"monitoredObjectOfServiceKey":2,"monitoredObjectOfServiceTypeCode":"CITSYS","objectOfServiceTypeIdentifier":"CITSYS","rootHwOosKey":2,"rootOsOosKey":3},"iCustomerItSystemDelegate":{"hostName":null,"monitoredObjectOfServiceKey":2,"globalDeviceIdentifier":"892dba41-6efd-4127-94ea-58ed6932a483","globalDeviceIdentifierTypeCode":"HW","displayNameText":"kommgmt01","confirmedHpSerialNumberIdentifier":"CZJ018079S","confirmedHpProductNumberIdentifier":null,"autoDetectedSerialNumberText":"CZJ018079S","autoDetectedProductNumberText":"AD275A","userEnteredSerialNumberText":"CZJ018079S","userEnteredProductNumberText":null,"worldwideName":null,"physicalDeviceFlag":true,"onSiteSystemIdentifier":null,"vendorName":null,"lastCommunicationReceivedTimestamp":13130447440
    ...
    null,"organizationSiteIdentifierReferenceSystemCode":null,"organizationSiteMasterReturnStatusCode":null,"reportedModelName":null,"latestReportedDeploymentTypeName":null,"remoteSupportEnabledFlag":true,"monitoredObjectOfServiceDashboardStatusCode":null,"monitoredObjectOfServiceCount":null,"supportAutomationRegistrationIncompleteCount":null,"remoteSupportDisenabledCount":null,"monitoredObjectOfServiceEventActiveCriticalCount":null,"monitoredObjectOfServiceEventActiveWarningCount":null,"monitoredObjectOfServiceDashboardSortOrderNumber":null}] }

    This single packet of 20 rows was about 128k and there 23 more behind it for about 2MB of data. We want to get something on the screen as quickly as possible and then load the rest of the data after the first has been rendered.

    I was able to use the function of the data table to load the first page very painlessly, What I am looking for is way to use those same functions to append the data already loaded.
  • prubinprubin Posts: 26Questions: 0Answers: 0
    For Instance if I tried to call fnServerData with a parameter in aoData telling it to get the next page instead if the initial request I would not know what to pass as the call back function. It seems from single stepping the code that the callback is an anonymous function defined in the call to fnServerData in _fnInitialise. So it seems I would have to completely duplicate this function. I am trying to find a way to not duplicate working tested code that already does what I need.
  • prubinprubin Posts: 26Questions: 0Answers: 0
    edited October 2011
    This is doing what I want but I was trying to avoid duplicating code which existing with data tables itself. The functions getNext and processNext are doing the follow on work.

    [code]

    var oTable = null;
    $(document).ready(function(){
    var arr1 = new Array();
    var i;
    for(i=1; i<150; i++)
    arr1[i-1] = i;
    oTable = $('#Devices').dataTable( {
    "bProcessing": true,
    "bServerSide": false,
    "sScrollY": "205px",
    "bPaginate": false,
    "bJQueryUI": false,
    "sAjaxSource": "mapTest.jsp",
    "sDom": "frtiS",
    "iDeferLoading": 0,
    "sAjaxDataProp": function (data) {
    var map = jQuery.parseJSON(data);
    if (map.total > map.start+map.count)
    setTimeout("getNext()", 200);
    return map.data;
    },
    "aoColumns": [
    { "mDataProp": "deviceId" },
    { "mDataProp": "gdid" },
    { "mDataProp": "productNumber" },
    { "mDataProp": "serialNumber" }
    ],
    "fnServerData": function ( sSource, aoData, fnCallback ) {
    $.ajax( {
    "url": sSource,
    "type": "POST",
    //"dataType": "json",
    "success": fnCallback,
    "data": {
    "Command": "callSBS",
    "Service": "DeviceConfiguration",
    "Method": "retrieveDeviceIdentifierByDeviceId",
    "Param0": "UserId",
    "Param1": JSON.stringify(arr1)
    }
    });
    }
    });
    $('#Devices tbody tr').live( 'mouseenter', function() {
    $(this).addClass( 'hovered' );
    })
    $('#Devices tbody tr').live( 'mouseleave', function() {
    $(this).removeClass( 'hovered' );
    } );
    $('#Devices tbody tr').live("click", function() {
    $('#Devices tbody tr').removeClass('selected');
    $(this).addClass('selected');
    });
    });
    function processNext(json) {
    var oSettings = oTable.fnSettings();
    var aData = oSettings.sAjaxDataProp( json );
    /* Got the data - add it to the table */
    for ( i=0 ; i
  • OmnimikeOmnimike Posts: 22Questions: 0Answers: 0
    edited October 2011
    What I think you want is something like this. You will also need to include Scroller.js from the extras folder which came with the datatables download on the page.

    [code]
    oTable = $('#Devices').dataTable( {
    bProcessing: true,
    bServerSide: true,
    sScrollY: "205px",
    sDom: "frtiS",
    bPaginate: true,
    sAjaxSource: "mapTest.jsp",
    iDeferLoading: true,
    aoColumns: [
    {mDataProp: "deviceId"},
    {mDataProp: "gdid"},
    {mDataProp: "productNumber"},
    {mDataProp: "serialNumber"}
    ],
    fnServerData: function ( sSource, aoData, fnCallback ) {
    // aoData is an array of objects which
    // look like [{name: paramName, value: paramValue}].
    // This converts it to the more useful form:
    // {paramName: paramValue}.
    var params = {};
    for (var i in aoData) {
    params[aoData[i].name] = aoData[i].value;
    };
    // If what I'm assuming is correct you need to send the
    // server an array containing the ids of all the devices
    // you want. The important thing to note is that
    // params.iDisplayStart is the "offset" and
    // params.iDisplayLength is the "limit" (in database terms).
    var arr1 = [];
    for (var i = 0; i < params.iDisplayLength; i++) {
    arr1.push(params.iDisplayStart + i);
    }
    $.ajax({
    url: sSource,
    type: "POST",
    //"dataType": "json",
    data: {
    "Command": "callSBS",
    "Service": "DeviceConfiguration",
    "Method": "retrieveDeviceIdentifierByDeviceId",
    "Param0": "UserId",
    "Param1": JSON.stringify(arr1)
    }
    success: function(json) {
    // Here's how you call the callback function.
    fnCallback({
    // Datatables needs this. No idea why.
    sEcho: params.sEcho,
    // There is a slight difference between
    // iTotalRecords and iTotalDisplayRecords,
    // but it's not important for now.
    iTotalRecords: json.total,
    iTotalDisplayRecords: json.total,
    // Here's data you will send the grid.
    aaData: json.data
    });
    }
    });
    }
    });
    [/code]

    bServerSide needs to be true otherwise data will only be retreived from the server once, instead of for each page. For scroller to work sScrollY needs to be set and the sDom needs to have an "S" in it somewhere. bPagination needs to be turned on too, or iDisplayStart and iDisplayLength don't get sent to fnServerData (well, they do but iDisplayLength will be -1, which isn't what you want).

    The server side usage page details what fnCallback needs to be passed. The example here is very close to what I use myself, and I have it working fine.
  • prubinprubin Posts: 26Questions: 0Answers: 0
    Thanks, you have given me something to consider.
This discussion has been closed.