DataTables logo DataTables

Mon, 16th Jan 2012

localStorage for state saving

One of the greatest challenges in writing a software library is in maintaining its API and ensuring that upgrades to newer versions of the library are as pain free as possible. The DataTables API has stood the test of time, but from time-to-time there something that has been implemented previously which is not desirable in future versions. In this case, DataTables 1.9 (beta 2) has seen a significant change to how its state saving is done and two old initialisation options have been removed and replaced with much more flexible options.

In the post I'll explain what has changed, the new features of DataTables 1.9 and show how the improvements can be used to very easily implement state saving for a table using localStorage rather than cookies, or any other state store you wish to use.

State saving

State saving in DataTables is done by saving a JSON string to a cookie, allowing it to maintain as much browser compatibility as possible, while keeping the state storage on the client-side. At times it can be useful to be able to modify the parameters that are saved by the table (either adding your own or modifying the core parameters) and DataTables 1.8 provided this option through two initialisation options:

However, actually working with these options was far from intuitive and they have now been replaced by five new initialisation options which cleanly separate the act of actually saving and loading data (fnStateSave and fnStateLoad), defining and modifying what parameters to save and load (fnStateSaveParams and fnStateLoadParams), and also notification when the state has been loaded (fnStateLoaded).

The parameters that are passed to each function are fully defined in the documentation linked to above. One major advantage of these new functions is that they will give you a Javascript object to work with, rather than a string that had to be manipulated as before making life much easier! The default for fnStateSave and fnStateLoad is to use the internal cookie saving code still, but as you will see below this can be trivially changed to save state anyway you wish.

Don't change an API!

Removing an API without deprecating the changing API at least one major release beforehand is exceptional, and not a pattern that will be employed by the DataTables project in general, but in this case the state saving API was horrendous to work with and rarely used because of that that fact. As such I felt it was correct to take this step - if anyone is currently using the fnStateLoadCallback and fnStateSaveCallback initialisation options and wishes to update to 1.9, please post your current code in the forum and I will offer free support to update the code for the new methods.

localStorage

Cookies have a number of disadvantages such as requiring increased HTTP bandwidth and a 4K limit. The W3C Web Storage specification defines localStorage as a local storage method which we can use in DataTables to store state without the inherent issues in using cookies.

In order to use state saving with localStorage we must first enable state saving with the bStateSave initialisation option and then define our fnStateSave and fnStateLoad functions. fnStateSave will take two parameters, the first being the DataTables settings object and the second being the state object we want to save. To save the sate we simply use localStorage.setItem and JSON.stringify (note that as such this will not work in browser which do not support localStorage or have built-in JSON parsing abilities). We can then define fnStateLoad as a function that will simply read our saved object, parse the JSON and return it:

$(document).ready(function() {
	$('#example').dataTable( {
		"bStateSave": true,
		"fnStateSave": function (oSettings, oData) {
			localStorage.setItem( 'DataTables', JSON.stringify(oData) );
		},
		"fnStateLoad": function (oSettings) {
			return JSON.parse( localStorage.getItem('DataTables') );
		}
	} );
} );

And that's it! localStorage of your DataTables' settings without the drawbacks of cookies. One simple and useful modification is to take into account the current web-page URL in case you are using multiple DataTables in your domain since localStorage is domain wide. We can do this with window.location.pathname:

$(document).ready(function() {
	$('#example').dataTable( {
		"bStateSave": true,
		"fnStateSave": function (oSettings, oData) {
			localStorage.setItem( 'DataTables_'+window.location.pathname, JSON.stringify(oData) );
		},
		"fnStateLoad": function (oSettings) {
			return JSON.parse( localStorage.getItem('DataTables_'+window.location.pathname) );
		}
	} );
} );

Using this method it is easy to see how you might extend this to store the state in a database on the server using Ajax (if you do, then note that the fnStateLoad Ajax call must be synchronous since there is no callback provided for an asynchronous request).

You can see this example running live in the DataTables examples.

Conclusion

Overall I hope you'll agree that this is a very welcome update to the old, obscure and difficult state saving API and I look forward to seeing how the new API is used and hope you enjoy using DataTables 1.9 as a whole.

There is a thread in the forum for comments and discussion on this post should you wish to add anything or have any questions.