Asterios Kalogeras
Asterios Kalogeras

Reputation: 134

DataTables pagination issues: working with Laravel's pagination model and JSON response

I am trying to build a datatable for a webpage that will eventually hold hundreds of thousands of entries. Because pagination is a must-have, I was given certain local API-calls that implemented Laravel's paginate method. As a result, the server's JSON response has the following format:

{
    "current_page": 1,
    "data": [{...,
    }],
    "first_page_url": "http:\/\/127.0.0.1:8000\/api\/test_history\/fullObj?page=1",
    "from": 1,
    "last_page": 134,
    "last_page_url": "http:\/\/127.0.0.1:8000\/api\/test_history\/fullObj?page=134",
    "links": [{...,
    }],
    "next_page_url": "http:\/\/127.0.0.1:8000\/api\/test_history\/fullObj?page=2",
    "path": "http:\/\/127.0.0.1:8000\/api\/test_history\/fullObj",
    "per_page": 15,
    "prev_page_url": null,
    "to": 15,
    "total": 2000
}

QUESTION

How could DataTables' paging feature implement Laravel's or any pagination model?

What changes in the table initialization, or in general, can be made in order for the page buttons to properly call the appropriate batch of entries?

There should be a way to utilize the above model's next_page_url, first_page_url, etc. properties.

Due to a predicted vast amount of entries, calling the entire object is out of the question, so, unless I am mistaken, DataTables' default paging may not do, because it is not a matter of what is rendered in the front end.

ISSUES

Even though the above JSON response contains all the necessary information for a table pagination, it seems to be conflicting with whatever data the datatable is expecting. So, the following issues surfaced within the webpage:

After consulting with documentation, I found that the server's JSON response did not follow DataTables standards, and I had to manipulate some of the data. Here follows the jQuery used to initialize the datatable:

$(document).ready(function() {
  $('#test_table').DataTable( {
    "order": [[ 8, "desc" ]],
    "scrollX": true,
    "paging": true,
    "lengthMenu": [[ 5, 15, 25, 100, -1 ], [ 5, 15, 25, 100, "All" ]],
    "pageLength": 15,
    "processing": true,
    "serverSide": true,
    "ajax": function(data, callback, settings) {
      $.get("http://127.0.0.1:8000/api/test_history/fullObj?page=1", {
        limit: data.length,
        offset: data.start
      },
      function(json) {
        callback({
          recordsTotal: json.total,
          recordsFiltered: json.total,
          data: json.data
        });
      });
    },
    "columns": [
      { "data": "id" },
      { "data": "uid" },
      { "data": "dev_type.type" },
      { "data": "registers.id" },
      { "data": "measurements.id" },
      { "data": "created_at" },
      { "data": "updated_at" }
    ]
  });
});

Alternatively:

$(document).ready(function() {
  $('#test_table').DataTable( {
    "order": [[ 8, "desc" ]],
    "scrollX": true,
    "paging": true,
    "lengthMenu": [[ 5, 15, 25, 100, -1 ], [ 5, 15, 25, 100, "All" ]],
    "pageLength": 15,
    "processing": true,
    "serverSide": true,
    "ajax": {
      "url": "http://127.0.0.1:8000/api/test_history/fullObj?page=1",
      "dataSrc": function(json) {
        json.recordsTotal = json.total;
        json.recordsFiltered = json.total;
        return json.data;
      }
    },
    "columns": [
      { "data": "id" },
      { "data": "uid" },
      { "data": "dev_type.type" },
      { "data": "registers.id" },
      { "data": "measurements.id" },
      { "data": "created_at" },
      { "data": "updated_at" }
    ]
  });
});

These response manipulations fixed the issues of the number of pages not showing, and the incorrect number of page buttons. The rest, however, do persist.

METHODS

Apart from scouring the DataTables' documentation and their website's forum, and combing through the internet for possible solutions, I have tried the following:

I have yet to stumble upon a groundbreaking answer, or think of one. Despite these shortcomings, I do believe that the answer is usually simpler than any complex thinking, and in my case it could be related to the data the table is expecting from the server; the JSON's format, or its properties.

Any suggestion would be greatly appreciated.

Upvotes: 2

Views: 2578

Answers (1)

Asterios Kalogeras
Asterios Kalogeras

Reputation: 134

What finally worked for the question's example, was using the DataTables' ajax.data property to pass pagination-related parameters, more specifically the current page. After the initialization, DataTables can handle the server's response so long as the returned object has a certain structure.

Below is the reworked section of the table's initialization:

$(document).ready(function () {
    let currentDraw = 1;

    $("#test_table").DataTable({
        order: [[8, "desc"]],
        scrollX: true,
        paging: true,
        lengthMenu: [
          [5, 15, 25, 100, -1],
          [5, 15, 25, 100, "All"],
        ],
        pageLength: 15,
        processing: true,
        serverSide: true,
        ajax: {
            url: "http://127.0.0.1:8000/api/test_history",
            type: "GET",
            data: function (d) {
                d.page = d.start / d.length + 1;
            },
            dataSrc: function (response) {
                let data = {
                    draw: currentDraw,
                    recordsTotal: response.total,
                    recordsFiltered: response.total,
                    data: response.data,
                };

                currentDraw++;

                return data.data;
            },
        },
        columns: [
            { data: "id" },
            { data: "uid" },
            { data: "dev_type.type" },
            { data: "registers.id" },
            { data: "measurements.id" },
            { data: "created_at" },
            { data: "updated_at" },
        ],
    });
});

Apart from passing the current page as an argument sent to the server, calculated as shown, in order for DataTables to detect and use the server's pagination, the structuring of a specific object in the ajax.dataSrc property is needed.

Within the newly structured object, a draw property is needed, which essentially is the number of times this particular table has been redrawn with data, i.e., each time a page changes. A recordsTotal property is needed to calculate the pagination buttons' numbering, and a recordsFiltered property to calculate the displayed info about the user's current position within the table on the bottom-left. Each time this callback function is invoked within the ajax.dataSrc section, the table's current draw is incremented to ensure that it is correctly attached as a URL parameter and the new data are returned.

I used this implementation within a Node.js and Angular application, as well as a static website, and the above was all both DataTables and the server needed. I hope this is helpful.

Upvotes: 0

Related Questions