Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Datatables - How to load only a certain amount rows on page-load?

I have a fiddle that make an ajax to URL and rendering a table, but I want to defer and load only 10 rows during page load.

HTML

<table id="example" class="display" cellspacing="0" width="100%">
    <thead>
        <tr>
            <th>Account ID</th>
            <th>Name</th>
            <th>Email</th>
        </tr>
    </thead>
</table>

JS

$(document).ready(function() {

$('#example').DataTable( {
        "bPaginate": true,
        "processing": true,
        "bServerSide": true,

        ajax: {
            url: 'https://api.myjson.com/bins/1egsx',
            dataSrc: 'data'
        },
        columns: [
            { data: 'account_id' },
            { data: 'name' },
            { data: 'email' }
        ],
        "deferRender": true,
        "deferLoading": 10,

    } );

});

I kept getting

No matching records found

like image 952
code-8 Avatar asked Aug 27 '16 13:08

code-8


People also ask

How do I display only 5 records in a DataTable?

There is a option called pageLength . You can set this for show only 5 entries.

How do you change the length of a DataTable?

len() method can still be used if you wish to programmatically change the page size and pageLength can be used to specify the initial page length.

What is Deferrender in DataTables?

This option allows DataTables to create the nodes (rows and cells in the table body) only when they are needed for a draw.


2 Answers

TL;DR: You should probably be either using deferRender with client-side processing OR server-side processing without deferRender (by fixing your JSON data). This answer assumes you want server-side processing.

deferLoading

When correctly using server-side processing, the default behavior is to only send the number of rows on one page per ajax request. You shouldn't need to be using deferLoading - here's what that does (from documentation here):

When using server-side processing, the default mode of operation for DataTables is to simply throw away any data that currently exists in the table and make a request to the server to get the first page of data to display. This is fine for an empty table, but if you already have the first page of data displayed in the plain HTML, it is a waste of resources. As such, this option exists to allow you to instruct DataTables to not make that initial request, rather it will use the data already on the page (no sorting etc will be applied to it).

Since all your data comes from ajax, that option shouldn't be selected.

deferRender

You really shouldn't need to use deferRender either, if you're correctly using serverside processing. deferRender will (from it's documentation here):

As an example to help illustrate this, if you load a data set with 10,000 rows, but a paging display length of only 10 records, rather than create all 10,000 rows, when deferred rendering is enabled, DataTables will create only 10.

Note the important phrase here:

if you load a data set with 10,000 rows

If you're using serverside processing correctly, you should only be loading the number of rows per page in a single load. deferRender is really an option to speed up datatables when using clientside processing. Serverside processing already handles what deferRender does. See this picture from the DataTables FAQ for how to speed up datatables:

enter image description here

Note that it emphasizes deferRender for clientside only. A note to make here is that if you don't have a LOT of rows (tens of thousands +) you probably don't need to use serverside processing.

Using Serverside Processing Correctly:

Your problem probably comes from the fact that your API isn't returning the proper form of JSON for server-side processing; you need to send more information than just the data to be displayed. Here is the documentation page with the full description (you should definitely read it), but I'll try to outline the basics below.

Request

The request sent to your API is going to contain some data that you need to address.

draw is a unique identifier that tracks sets of request-response pairs; the value in the response needs to match the value in the request. This is how datatables matches requests to responses.

start represents the record that should be the first in the response; if we are showing 10 records per page and we're on page 2, start will be equal to 10, so that in the response we send only records numbered 10-19.

length represents the expected number of rows for this draw, so in the above example of 10 records per page on page 2, length will be equal to 10. This is how many records you should return. This value will be based on the lengthMenu or pageLength options to the Datatables initialization. (Documented here and here, respectively)

An important thing to remember that is often forgotten is to ONLY send as many rows as length; don't send all your rows in the first request.

Response

Your response will need to be altered as well. Basically, instead of just returning data, you need to return an object that looks like the below example (from that documentation page):

{
    "draw": 1,
    "recordsTotal": 57,
    "recordsFiltered": 57,
    "data": [
        [
            "Angelica",
            "Ramos",
            "System Architect",
            "London",
            "9th Oct 09",
            "$2,875"
        ],
        [
            "Ashton",
            "Cox",
            "Technical Author",
            "San Francisco",
            "12th Jan 09",
            "$4,800"
        ],
        ...
    ]
}

Note the additional data: draw, recordsTotal, and recordsFiltered in addition to the usual data. These are required options when using serverside processing.

draw represents the number corresponding to the request made to your API; the GET request will also have a draw value, and the value in the GET must match the value in the response.

recordsTotal represents the total number of records in the table, across all pages, where recordsFiltered represents the number of records that meet the filtering requirements set by the GET request (if there is no filtering, it should be equal to recordsTotal.

These are the minimum required elements to your reply, but you should look into the linked documentation for more information on optional values.

Side Note

As a side note; bServerSide should be serverSide and bPaginate should be paging if you're using DataTables version 1.10 or later.

like image 66
Chris H. Avatar answered Sep 16 '22 23:09

Chris H.


I assume your intention here is to display the DataTable as soon as the page loads. Described below are two ways to load partial data depending on your requirements. The entire data can be loaded at a later point in time by triggering an event like click of a button. In both cases, the entire data will be downloaded as well and stored locally which can then be loaded based on the triggered event so as to avoid making another call to fetch the entire data.

Case 1: Only want to download partial data from the source

The entire data will be fetched from 'https://api.myjson.com/bins/1egsx' before the DataTable will process the data. If you want to only fetch partial data from the URL, you can create your custom function that will parse the data in AJAX interactive mode (readyState=3), stop after receiving the first 10 entries and then massage the data and pass that as the input data for the DataTable. Here's a summary of what you need to do

var inputData = '';
function loadDataTablePreview() {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 3 && this.status == 200) {
        inputData += this.responseText;
        // Count the number of closing '}'. If its 10, lets start processing our data
        // Get the index of 10 closing '}'
        // Create a substring of inputData
        // append ']}'
        // Now JSON Decode
        var decodedData = JSON.parse(inputData);
        // Now create an instance of the DataTable passing this data as the input data 
        $('#example').DataTable( {
          "bPaginate": true,
          "processing": true,
          "bServerSide": true,
          data: decodedData,
          columns: [
            { data: 'account_id' },
            { data: 'name' },
            { data: 'email' }
          ],
        });
    }
    else if (this.readyState == 4 && this.status == 200) {
       // JSON Decode the data and store it to load later
    }
  };
  xhttp.open("GET", "https://api.myjson.com/bins/1egsx", true);
  xhttp.send();
}

$(document).ready(function() {
  loadDataTablePreview();
}

Case 2: Only load the first 10 entries after downloading entire data

Assuming you are ok with having the entire data downloaded, before displaying the DataTable, you can create a function for your dataSrc as seen below. This will display return only the 10 entries in the table. You can optionally store the entire JSON in this function in the browser data store (like sessionStorage) and then trigger a JS function to load the entire JSON at a later point in time.

$(document).ready(function() {

  $('#example').DataTable( {
    "bPaginate": true,
    "processing": true,
    "bServerSide": true,
    ajax: {
        url: 'https://api.myjson.com/bins/1egsx',
        dataSrc: function ( json ) {
                    // Store entire data in sessionStorage
                    // return the first 10 entries only for now
                    return json.data.slice(0,10);
                 },
    },
    columns: [
        { data: 'account_id' },
        { data: 'name' },
        { data: 'email' }
    ],
  });
});
like image 41
Raghav Tandon Avatar answered Sep 18 '22 23:09

Raghav Tandon