3

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?

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

Comments

2

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.

5 Comments

I think this might be problematic. I still need to set the ajax URL on a per-instance basis. If I default ajax to a function then I lose access to the inner properties.
If you pass ajax.url in with your initialization options like normal, it should be set as a property on your function, and retrievable via the api using init().
I thought that'd work, but I've just tried it -- since I'm extending the defaults, when I initialize dataTables with {data: { url: 'xxx' }} it's overwriting the whole function. It never gets called.
You could use an error event listener as @Gyrocode.com suggests, then access the processing element in the way I mention in my answer?
Yeah, that looks like the only way to do it, short of an extension. Which I might investigate later, because I don't love binding an event handler to document.body.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.