Using deferRender with DataTables on Knockout.js

Using deferRender with DataTables on Knockout.js

getalexgetalex Posts: 39Questions: 11Answers: 1

I am returning a few thousand records, and load times take anywhere from 30 seconds and up.
I want to use the deferRender feature but it requires the 'ajax' source parameter, which I'm not certain how to use.

My AJAX call takes parameters, and since I'm using knockout, the problem is I have 'on success' for my ajax to do the necessary "ko.mapping.fromJS" on the observableArray object. Could you provide an example on how this would be configured? or what best approach to follow to improve the performance here ...

Thank you in advance!

This question has an accepted answers - jump to answer

Answers

  • kthorngrenkthorngren Posts: 21,117Questions: 26Answers: 4,916

    deferRender will work with either AJAX or Javascript data sources. Without an example of you AJAX request its hard to provide an example. However it sounds like you might want to use ajax.dataSrc as a function to extract the data you want.

    Kevin

  • getalexagaingetalexagain Posts: 3Questions: 1Answers: 0

    Kevin, thanks for the reply on this thread - as I'm using KnockoutJS I have the following pattern per documentation I found with DataTables support and online forums:

    dt = $('#itemsTable').DataTable({
        columns: [ ... ]
    });
    

    Then a load function after all viewModel observables are set up as follows:

    var params = { ... };
    
        $.ajax({
            type: "GET",
            data: params,
            url: "/SomePath/GetItems",
            success: function (items) {
    
                // clear all former datatable contents
                viewModel.resultItems.removeAll();
    
                // Convert the data set into observable objects, and will also add the initial data to the table
                ko.mapping.fromJS(
                    items,
                    {
                        key: function (data) {
                            return ko.utils.unwrapObservable(data.Id);
                        },
                        create: function (options) {
                            return new customItem(options.data, dt);
                        }
                    },
                    viewModel.resultItems
                );
            }
        });
    

    So now I translate the above and try to move it into the viewModel method and figure out how to sort out the parameter declarations, etc. I was able to get the DataTable to load data, but I don't believe it's 'deferring' anything - when I click on page 2, 3, etc. all the items appear to already be on the client side. So the code doesn't seem to go back to the server to get the next batch of items ... therefore I am guessing this deferRender option is not working with KnockoutJS or the way I'm currently handling the ajax option. Any sample or helpful insights here would be greatly appreciated.

    reference: https://datatables.net/dev/knockout/

  • kthorngrenkthorngren Posts: 21,117Questions: 26Answers: 4,916

    I'm not familiar with Knockout and don't have an example. deferRender is a client side function and works only if you use -optoin data to add Javascript data to Datatables or use ajax within Datatables to fetch the data. It looks like you are fetching the data then adding to the table followed by initializing Datatables. If thats the case then deferRender won't help. Plus I don't see deferRender in your above code.

    when I click on page 2, 3, etc. all the items appear to already be on the client side. So the code doesn't seem to go back to the server to get the next batch of items

    This would require using the serverSide option instead of deferRender. The Server Side Processing doc explains how this works and the requirements of the server side code.

    Kevin

  • getalexgetalex Posts: 39Questions: 11Answers: 1

    Kevin, thanks for the reply on this thread - as I'm using KnockoutJS I have the following pattern per documentation I found with DataTables support and online forums:

    dt = $('#itemsTable').DataTable({
        columns: [ ... ]
    });
    

    Then a load function after all viewModel observables are set up as follows:

    var params = { ... };
    
        $.ajax({
            type: "GET",
            data: params,
            url: "/SomePath/GetItems",
            success: function (items) {
    
                // clear all former datatable contents
                viewModel.resultItems.removeAll();
    
                // Convert the data set into observable objects, and will also add the initial data to the table
                ko.mapping.fromJS(
                    items,
                    {
                        key: function (data) {
                            return ko.utils.unwrapObservable(data.Id);
                        },
                        create: function (options) {
                            return new customItem(options.data, dt);
                        }
                    },
                    viewModel.resultItems
                );
            }
        });
    

    So now I translate the above and try to move it into the viewModel method and figure out how to sort out the parameter declarations, etc.

    I was able to get the DataTable to load data, but I don't believe it's 'deferring' anything - when I click on page 2, 3, etc. all the items appear to already be on the client side, so the code doesn't seem to go back to the server to get the next batch of items ... therefore I am guessing this deferRender option is not working with KnockoutJS or the way I'm currently handling the ajax option.

    Any sample or helpful insights here would be greatly appreciated.

    reference: https://datatables.net/dev/knockout/

  • allanallan Posts: 63,075Questions: 1Answers: 10,384 Site admin

    DataTables will only go to the server to get the information for each page draw if you enable the serverSide option that Kevin mentioned (which doesn't appear to be enabled in your code above, nor does deferRender).

    That said, serverSide and deferRender are effectively useless together. Deferred rendering will delay the creation of the table row and cell nodes until they are needed for the display (thereby saving a chunk of time at startup since it only needs to create the cells for the first page).

    If server-side processing is enabled, then only the data for the current page are available for each draw anyway, which is why I say deferRender is useless with server-side processing (it makes zero difference).

    I've never tried to use the knockout integration with server-side processing - I'm not sure how easy it would be to be honest (I suspect not very).

    If you only have thousands of rows, deferRender will help startup performance.

    Allan

  • getalexgetalex Posts: 39Questions: 11Answers: 1

    Allan / Keving - great responses, thank you for your time.

    The way I understand it, I'm going to avoid 'serverSide' and try to implement 'deferRender' with the 'ajax' option as a function and pasting/rearranging my above ajax call within the datatable setup. So all data is retrieved from the server via JSON, but only the first 10 rows will render, then the next 10 when users click page 2, etc.. I could see how that saves processing time in large data sets.

    However, if the data coming back is large enough to where users see maxJsonLength exceptions, 'serverSide' appears to be the only option to go after, is that right?

    I was looking for KnockoutJS examples to validate my implementation. I'll continue dev/testing, any feedback on the above points would be helpful. Thanks in advance.

  • allanallan Posts: 63,075Questions: 1Answers: 10,384 Site admin
    Answer ✓

    However, if the data coming back is large enough to where users see maxJsonLength exceptions, 'serverSide' appears to be the only option to go after, is that right?

    If the server has limits on the amount of JSON that it can send, then yes. I suppose you could make multiple Ajax requests and combine them on the client-side, but I suspect that would be a really complex solution for the issue.

    Allan

This discussion has been closed.