Ajax: Differences Between jQuery and DataTables

20 Jan 2021

Table of Contents


Introduction

The DataTables ajax option provides different ways for users to handle ajax-sourced data. For the sake of this discussion, I will focus on the DataTables ajax option which takes an initialization object, since that is how DataTables allows you to leverage the jQuery ajax function call.

jQuery Ajax

First, a quick look at the jQuery ajax function. Here is a simple example, adapted from the documentation:

JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$("button").click(function() {
  $.ajax({
    method: "POST",
    url: "http://whatever.com/somedata",
    data: { name: "John", location: "Boston" }
  })
    .done(function( msg ) {
      alert( "Data Saved: " + msg );
    });
});

This example uses the jQuery deferred done() method. Or you can use the ajax success() function, which is called if the request succeeds:

JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$("button").click(function() {
  $.ajax({
    method: "POST",
    url: "http://whatever.com/somedata",
    data: { name: "John", location: "Boston" },
    success: function(result) {
      $("#div1").html(result);
    }
  });
});

Request Data

The data parameter is used to specify data to be sent to the server as part of the ajax request, either in the request body (e.g. using POST), or as URL query parameters (e.g. using GET).

The examples shown above use a JavaScript object:

JavaScript
1
data: { name: "John", location: "Boston" }

You could provide this as JSON, too (it’s still a JavaScript object):

JavaScript
1
data: { "name": "John", "location": "Boston" }

You can also provide string or array data.

An example of string data could be as follows:

"name=John&location=Boston"

In this case, the data matches the format of data provided by an HTML form. The assumption made by jQuery is that this data has already been percent-encoded as needed, to match the correct contentType, which by default is application/x-www-form-urlencoded.

In fact, the above object example (data: { name: "John", location: "Boston" }) will result in the same key/value string being sent with the request: name=John&location=Boston.

Arrays are a bit more complicated. From the documentation:

If the value is an array, jQuery serializes multiple values with same key based on the value of the traditional setting. For example, { a: [1,2] } becomes the string "a%5B%5D=1&a%5B%5D=2".

The point is: JavaScript strings, arrays, and objects can all be handled by jQuery’s ajax data parameter.

DataTables Ajax

Here is a simple DataTables ajax example, using an object ({...}) for its settings :

JavaScript
1
2
3
4
5
6
7
8
$('#example').dataTable( {
  "ajax": {
    "method": "POST",
    "url": "http://whatever.com/somedata",
    "data": { name: "John", location: "Boston" },
    "dataSrc": "tableData"
  }
} );

Request Data

Here is where we start to see some differences between jQuery and DataTables.

In the above example we have the same data object as we used with jQuery:

JavaScript
1
"data": { name: "John", location: "Boston" }

Note that the double-quotes around data, here, are often used for DataTables options, but are themselves optional. This also works:

JavaScript
1
data: { name: "John", location: "Boston" }

And this (the valid JSON object):

JavaScript
1
"data": { "name": "John", "location": "Boston" }

Strings? No!

However, if we try to do this, using a string…

JavaScript
1
"data": "foo=bar"

…then unexpected things start to happen.

In this case, the request body will contain the following:

JavaScript
1
{ 0: "f", 1: "o", 2: "o", 3: "=", 4: "b", 5: "a", 6: "r" }

What happened?

DataTables is clear in its documentation:

As with jQuery, data can be provided as an object…

But it does not explicitly state that strings will become objects like this - and the code will not warn you.

The reason this happens is because DataTables pre-processes your data value on the assumption that it is, in fact, a JavaScript object. One reason for this is that DataTables also uses this same mechanism to support server-side processing - and it therefore performs a “merge” of its server-side data object with your additional data values:

JavaScript
1
2
// second object's properties are added to first object, using "true" for deep copy:
data = $.extend( true, data, newData );

In this line of code, which is part of the DataTables _fnBuildAjax( oSettings, data, fn ) function:

  • true means “deep recursion”
  • data refers to server-side parameters (if there are any), or an empty object {} otherwise
  • newData is your "foo=bar" string

The result of merging the string into the object is the above exploded string.

See here for the jQuery extend() documentation.

See below for more information about server-side processing!

A Function? Yes!

DataTables extends jQuery by allowing you to provide your data from a function. From the documentation:

JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$('#example').dataTable( {
  "ajax": {
    "url": "data.json",
    "data": function ( d ) {
      return $.extend( {}, d, {
        "extra_search": $('#extra').val()
      } );
    }
  }
} );

This is basically allowing you to provide your own data and your own $.extend() logic.

The Data Source

Another major difference between jQuery and DataTables is the DataTables ajax dataSrc option. This is not about sending data to the server from DataTables, but is about receiving data from the server.

We saw it being used in the first DataTables example:

JavaScript
1
2
3
4
5
6
7
8
$('#example').dataTable( {
  "ajax": {
    "method": "POST",
    "url": "http://whatever.com/somedata",
    "data": { name: "John", location: "Boston" },
    "dataSrc": "tableData"
  }
} );

This allows you to tell DataTables where the entry point is in the JSON data you recived in your ajax response. By “entry point” I mean the location of the JSON array, over which DataTables will iterate to populate your table’s rows - in the following example, that is the tableData array:

JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{
  "tableData": [
    {
      "id": "1",
      "name": "Tiger Nixon",
      "position": "System Architect",
      "salary": "$320,800",
      "start_date": "2011/04/25",
      "office": "Edinburgh",
      "extn": "5421"
    },
    {
      "id": "2",
      "name": "Garrett Winters",
      "position": "Accountant",
      "salary": "$170,750",
      "start_date": "2011/07/25",
      "office": "Tokyo",
      "extn": "8422"
    },
    ...
    {
      "id": "57",
      "name": "Donna Snider",
      "position": "Customer Support",
      "salary": "$112,000",
      "start_date": "2011/01/25",
      "office": "New York",
      "extn": "4226"
    }
  ]
}

If your array has no name, then you need to use "":

JavaScript
1
"dataSrc": ""

If your array is called data then you do not need to use the dataSrc option if you don’t want to: data is the default value for dataSrc:

JavaScript
1
"dataSrc": "data" // completely optional!

See the documentation for dataSrc here.

Success

The final major difference between jQuery and DataTables relates to the jQuery success function. From the DataTables documentation:

success must not be overridden as it is used internally in DataTables. To manipulate / transform the data returned by the server use ajax.dataSrc, or use ajax as a function…

HTML Forms

Assuming a form such as the following:

JavaScript
1
2
3
4
5
<form id="filter-form">
    <input type="text" id="city" name="city">
    <input type="text" id="country" name="country">
    <input type="submit" value="Submit">
</form>

Then we can use ajax together with the jQuery serializeArray() function to send form data to the server.

Assuming we type the city name Lisbon and country name Portugal into our form, then $( "#filter-form" ).serializeArray() will return an array:

JavaScript
1
2
3
4
[
  { "name": "city", "value": "Lisbon" },
  { "name": "country", "value": "Portugal" }
]

jQuery Form Data

Using the serialized array shown above, a jQuery ajax call will apply its standard rules and convert the array data to:

city=Lisbon&country=Portugal

Here is an example call:

JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$( "#filter-form" ).submit(function( event ) {
  event.preventDefault();
  $.ajax({
    method: "POST",
    url: "http://whatever.com/somedata",
    data: $( this ).serializeArray(),
    success: function( result ) {
      $("#div1").html(result);
    }
  });
});

DataTables Form Data

To achieve the equivalent result using a DataTables jQuery call, we can use the DataTables ajax.reload() call:

JavaScript
1
2
3
4
5
6
7
var form_data = [];

$( "#filter-form" ).submit(function( event ) {
  event.preventDefault();
  form_data = $( this ).serializeArray();
  table.ajax.reload();
});

Our DataTable can now use the form_data variable:

JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
var table = $('#example').DataTable( {
  ajax: {
    method: "POST",
    url: "http://whatever.com/somedata",
    data: function() {
      return form_data
    }
  },
  // other table options...
});

Other DataTables Options

More examples of DataTables ajax usage are shown here.

JSON String Data

To send a JSON string in the body of your request, assume we have a JSON object:

JavaScript
1
var myJson = { "name": "John", "location": "Boston" };

In our ajax parameters we can use this:

JavaScript
1
2
3
data: function() {
  return JSON.stringify( myJson )
}

This will place the JSON string into the request body:

{"name":"John","location":"Boston"}

The followong, however, will not work - for the same reasons as noted earlier in this document:

JavaScript
1
2
// DO NOT DO THIS:
data: JSON.stringify( myJson )

Here, we are back to the “data as string” problem, as previously noted.

Server-Side Processing

As already noted above, when you provide ajax data as follows…

JavaScript
1
data: { name: "John", location: "Boston" }

…then this data will be added to the existing server-side request data generated by DataTables:

draw=1&...&start=0&length=25&name=John&location=Boston

The same result can also be achieved as follows:

JavaScript
1
2
3
4
data: function ( d ) {
  // d is the existing server-side request data
  return $.extend( {}, d, { name: "John", location: "Boston" } );
}

In this case, the jQuery extend() operation creates (and returns) a new object created by merging the existing d server-side request data with your extra custom data values (name and location).

Note however that we cannot do this:

JavaScript
1
2
3
4
// DO NOT DO THIS for SERVER-SIDE PROCESSING:
data: function () {
  return { name: "John", location: "Boston" };
}

This will cause the existing server-side request data to be discarded.

Whenever you are using server-side processing, and you want to send supplementary data in your request, you must ensure you preserve the server-side request data created by DataTables.