Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to refresh DataTables from within ajax/error callback?

I'm extending the DataTables defaults like so:

$.extend(true, $.fn.dataTable.defaults, {
    lengthChange: false,
    deferRender: true,
    displayLength: 25,
    stateSave: false,
    serverSide: true,
    processing: true,
    ajax: {
        type: 'POST',
        error: function($xhr) {
            if($xhr.status === 401) {
                wxu.openLoginBox(function(data) {
                    // HELP: how can I get the DataTables object from this context?
                });
            } else {
                wxu.notify({'text': "Could not load list", 'cssClass': 'error', timeout: 0});
            }
        }
    }
});

Sometimes a user will get logged out and then when they try changing pages or sorting, it just says "Processing" forever. I can catch this by looking for a 401 error response (this is what my app sends when you've been timed out), but then I don't know how to "refresh" dataTables to make the "Processing" message go away so that you can resume using the app.

Please note that I'm extending the defaults here in a .js file -- I don't know what element DataTables is going to be bound to at this point.

How can I "fix" dataTables from inside the ajax/error callback?

like image 348
mpen Avatar asked Jun 01 '26 12:06

mpen


2 Answers

NOTES

You should not override ajax.error since this property is used internally by DataTables, the same applies to ajax.success.

SOLUTION

You can add event handler for xhr event to handle Ajax errors (json === null).

// Prevent alert message from being displayed
$.fn.dataTable.ext.errMode = 'none';

// Use delegated event handler
// to handle Ajax request completion event
$(document.body).on('xhr.dt', function (e, settings, json, xhr){
   // If there is an Ajax error and status code is 401
   if(json === null && xhr.status === 401){         
      var api = new $.fn.dataTable.Api(settings);

      console.log('Session expired');
/*     
      wxu.openLoginBox(function(data){
          api.ajax.reload();
      });
*/

   } else {
      console.log('Could not load list');   
/*       
       wxu.notify({'text': "Could not load list", 'cssClass': 'error', timeout: 0});
*/       
   }
});

DEMO

See this jsFiddle for code and demonstration.

like image 163
Gyrocode.com Avatar answered Jun 03 '26 00:06

Gyrocode.com


Per the documentation, ajax can be a function. It is called with the table settings object, which can be used to construct a new API object for the table. Then, you can just use the API method to get the processing element (using .dataTables_processing) or take whatever other action you like using the other available API methods. Concretely, something like this should work:

{
  "ajax": function (data, callback, settings) {
    $.ajax({
      type: "POST",
      success: function (json) {
        callback(json);
      },
      error: function ($xhr) {
        if ($xhr.status === 401) {
          var api = new $.fn.dataTable.Api(settings);
          var container = api.table().container();
          $(container).find('.dataTables_processing').hide();
        }
      }
    });
  }
}

I don't see it documented specifically, but this is also set to the DataTable object in the ajax function when it is called. Using that could be a more direct route to your goal, but I think the above aligns more with the intended use.

like image 32
Chris Hunt Avatar answered Jun 03 '26 01:06

Chris Hunt