Server side pagination in KTDatatable (Metronic)

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Mastering Server-Side Pagination in KTDatatable (Metronic): A Developer's Guide

As a senior developer, I frequently see developers running into hurdles when implementing complex UI features like data tables with pagination. The issue you are facing—getting the data but failing to access the total page count or subsequent page URLs—is extremely common when transitioning from simple client-side filtering to robust server-side solutions.

This post will walk you through the correct architectural approach for achieving true server-side pagination within KTDatatable, focusing on how the API response must be structured and how to configure your setup correctly.

The Principle of Server-Side Pagination

Server-side pagination is a crucial technique for performance and scalability. Instead of sending the entire dataset to the client and letting JavaScript handle slicing (client-side pagination), you delegate the responsibility of fetching specific subsets of data to the server. This means the database does the heavy lifting, drastically reducing bandwidth usage and improving load times, especially with large datasets.

For this to work seamlessly with a library like KTDatatable, your backend API must provide two primary pieces of information in its response:

  1. The Data: The actual records for the requested page.
  2. The Pagination Metadata: Information about the total number of records and the current page context (total pages, current page number, etc.).

Designing Your API Response

Your initial attempt focused on mapping the data (cards = data.cards.data), which is correct for retrieving the rows. However, to enable Metronic's pagination controls to function, you need to explicitly return the total count and pagination links within the response payload.

If you are using a framework like Laravel (which is often paired with modern API development), structuring your Eloquent query to handle limits and offsets is the first step. Then, ensure your JSON response reflects this structure clearly.

Here is what a well-structured server-side response should look like:

{
    "data": [
        // Array of actual records for the current page
        {"id": 1, "name": "Item A"},
        {"id": 2, "name": "Item B"}
    ],
    "pagination": {
        "current_page": 1,
        "last_page": 5,
        "total": 150 // Crucial: Total number of records available
    }
}

Configuring KTDatatable for Server-Side Control

The key to making this work is correctly utilizing the serverPaging: true setting and ensuring your data source maps to this structure. You should separate the actual data mapping from the pagination metadata retrieval.

In your configuration, instead of trying to extract page numbers from the mapped results, you need to ensure that the framework understands how to use the returned metadata for UI rendering.

Here is an updated approach focusing on fetching the necessary components:

data: {
    type: 'remote',
    source: {
        read: {
            url: dataURL,
            method: 'GET',
            contentType: 'application/json',
            // The map function should only return the actual data rows
            map: function(data) {
                // We only want the records for the current page
                return data.data; 
            }
        },
    },
    pageSize: 10, // How many items per page
    serverPaging: true, // Tells KTDatatable to expect server-side results
},

Implementing Pagination Navigation

The reason you couldn't see the page numbers before is that the pagination controls are generated by Metronic based on the data provided by the server. When serverPaging is true, KTDatatable expects the server endpoint (the API call) to return the total count and page information.

If your backend correctly returns the structure shown above, Metronic's built-in pagination component will automatically utilize the pagination.total and pagination.current_page values to render the correct navigation links. You do not need to manually parse these numbers from the data rows themselves.

To retrieve the next page, your JavaScript logic needs to call the API again, passing the required parameters (page number and page size) to your endpoint. This is where robust backend design shines; ensuring your Laravel routes handle page and limit query parameters correctly is vital for scalable applications, much like designing clean RESTful endpoints in Laravel.

Conclusion

Implementing server-side pagination is less about complex client-side parsing and more about solidifying the contract between your frontend and backend. By structuring your API to return explicit pagination metadata (total count, current page), you empower UI libraries like KTDatatable to handle the presentation layer automatically. Focus on making your API response predictable; this is the foundation for building scalable data applications, whether you are using Laravel or any other robust framework.