Bug when using serverSide=false with Ajax?

Bug when using serverSide=false with Ajax?

arex18arex18 Posts: 2Questions: 1Answers: 0

Trying to use Datatables with the intention to:

  • Get data through ajax in pages
  • Keeping any search/sorting etc. to the frontend - i.e. Datatables does it's magic without hitting the server every time the user searches for something.

The above is achieved by setting serverSide=false and providing the ajax endpoint:

    $(document).ready(function () {
                $('#all-customers-table').DataTable({
                    "scrollX": true,
                    "order": [[1, "asc"]],
                    "pagingType": "full_numbers",
                    paging: true,
                    pageLength: 50,
                    "processing": true,
                    serverSide: false, -------------> The problem
                    ajax: "customers/",
                    "columns": [
                        {"data": "edit"},
                        {"data": "first_name"},
                        {"data": "last_name"},
                        {"data": "email"},
                        {"data": "mob"},
                        {"data": "tel"},
                        {"data": "address"},
                        {"data": "town"},
                        {"data": "company"},
                        {"data": "account_status"},
                    ]
                });
            });

So far so good, with the backend code being: (this is only for debugging purposes, hardcoded variables)

        def get(self, request):
                datatables = request.GET
                draw = 1
                page_length = 50
                page = 1
                all_customers = Customer.objects.all().order_by('first_name')
                paginator = Paginator(all_customers, page_length)
                all_customers_page: List[Customer] = paginator.get_page(page)
                data = [{
                    'edit': f"""<a href="{reverse('customer:edit_customer', kwargs=dict(customer_id=i.pk))}">
                                    <button class="btn btn-primary btn-sm">Edit</button>
                                </a>""",
                    'first_name': i.first_name,
                    'last_name': i.last_name,
                    'email': i.email,
                    'mob': i.mobile,
                    'tel': i.tel,
                    'address': i.address.address1 + i.address.address2,
                    'town': i.address.town,
                    'company': i.company,
                    'account_status': i.customer_status
                } for i in all_customers_page]

                records_total = all_customers.count()
                return JsonResponse({
                    'draw': draw,
                    'recordsTotal': records_total,
                    'recordsFiltered': records_total,
                    'data': data,
                }, safe=False)

Expected: Search on the frontend (works), Page info shown on frontend, e.g. "Showing 1 to 50 of 500 entries" and page numbers (does not work)

Problem: with serverSide=true, the second part works, meaning the correct number of entries and page numbers are shown, whereas with serverSide=false "Showing 1 to 50 of 50 entries" is shown and only 1 page.

Am I missing some settings or is this a bug? Thanks.


Answers

  • kthorngrenkthorngren Posts: 20,264Questions: 26Answers: 4,764

    Server side processing follows the protocol described here:
    https://datatables.net/manual/server-side

    When using client side process, ie serverSide: false, Datatables doesn't pay attention to all those parameters. It calculates the number of entries and paging buttons based on the full dataset returned in the Ajax request.

    Sounds like your server script is returning only 50 rows of data although you are expecting more. Use the browser's network inspector tool to see the XHR response. How many rows of data are returned?

    Kevin

  • arex18arex18 Posts: 2Questions: 1Answers: 0

    It doesn't make sense to return more than 50 rows in this case since the primary use case is pagination from server side.

    I expected Datatables to use recordsTotal to calculate the number of pages, but only display the 50 which were sent for page 'x'.

    I genuinely think this is a proper bug, although the documentation doesn't do the serverSide false any justice as there's little info on this.

    For future reference, I worked around it and achieved 100% functionality with regards to:

    • Full backend pagination (loads 'x' rows every time the Load More button is pressed)
    • ^ also works with any custom filters/inputs etc. made on the model
    • Takes into consideration duplicate rows/rows < pagination number
    • Full frontend search on any column

    I will upload the code the github when I have the time. Thanks for your fast response kthorngren.

  • kthorngrenkthorngren Posts: 20,264Questions: 26Answers: 4,764

    It doesn't make sense to return more than 50 rows in this case since the primary use case is pagination from server side.

    Yes, that is server side processing not client side processing.

    I expected Datatables to use recordsTotal to calculate the number of pages, but only display the 50 which were sent for page 'x'.

    If you have serverSide: false then that is client side processing where Datatables expects all the rows to be returned to the client and Datatables will calculate the number of pages, etc based on the pageLength and the number of rows returned.

    I genuinely think this is a proper bug, although the documentation doesn't do the serverSide false any justice as there's little info on this.

    Not sure why this is a bug since client side processing expects all the rows to be in the client.

    I just re-read your first two points:

    Get data through ajax in pages
    Keeping any search/sorting etc. to the frontend - i.e. Datatables does it's magic without hitting the server every time the user searches for something.

    Datatables doesn't support server side processing (paging) and searching only the client side data. Take a look at the response from the developer with a similar question in this thread.

    For future reference, I worked around it and achieved 100% functionality with regards to:

    Sounds interesting and others with the same question would like something like this.

    Kevin

This discussion has been closed.