Datatables and "Back" feature
Datatables and "Back" feature
abrachet
Posts: 8Questions: 0Answers: 0
Hi there,
I try to implement a back feature and I'm having problem. Let me explain.
I have a first page with some search criteria + a search action + a datatable component. Here is the datatable code :
[code]
// target DataTables for members
var Members = $('#Members').dataTable({
aoColumns: [
{ mDataProp: 'avatar', bSortable: false, bUseRendered: true, fnRender: function (o, val) { return tools.dtRenderMemberAvatar(val); }, sClass: 'centeredRow', sWidth: '100px' },
{ mDataProp: 'lastName', sClass: 'centeredRow', sType: 'string', sWidth: '150px' },
{ mDataProp: 'firstName', sClass: 'centeredRow', sType: 'string', sWidth: '150px' },
{ mDataProp: 'gender', sClass: 'centeredRow', sType: 'string', sWidth: '100px' },
{ mDataProp: 'age', sClass: 'centeredRow', sType: 'numeric', sWidth: '50px' },
{ mDataProp: 'level', fnRender: function (o, val) { return tools.dtRenderLevelWithColor(val); }, sClass: 'centeredRow', sType: 'numeric', sWidth: '50px' },
{ mDataProp: 'lastConnection', sClass: 'centeredRow', sType: 'date', sWidth: '300px' }
],
fnCreatedRow: function (nRow, aData, iDataIndex) {
$(nRow).attr('data-user-id', aData.userID);
},
fnServerParams: function (aoData) {
tools.dtSearchOnField(aoData, '#institution', 'InstitutionID');
tools.dtSearchOnField(aoData, '#group', 'GroupID');
tools.dtSearchOnField(aoData, '#level', 'LevelID');
tools.dtSearchOnField(aoData, '#sex', 'IsMaleGender');
tools.dtSearchOnField(aoData, '#lastname', 'LastName');
tools.dtSearchOnField(aoData, '#firstname', 'FirstName');
},
iDisplayLength: 10,
sAjaxSource: '@Url.Action("SearchMembers", "DataTables")',
oLanguage: {
sUrl: '/assets/js/resources/jquery.dataTables.fr-FR.txt'
}
});
[/code]
When the table is bound, I get a list member. I can click on each member to access a second page that displays detailed information (in the same time, criteria are persisted using cookies). On this second page I added a back button to come back on the search page.
On the search page I added this code :
[code]
// handle back action
if (tools.parseQueryString().back) {
// load search form state
tools.loadFormField('members', 'institution', '#institution');
tools.loadFormField('members', 'group', '#group');
tools.loadFormField('members', 'level', '#level');
tools.loadFormField('members', 'sex', '#sex');
tools.loadFormField('members', 'lastname', '#lastname');
tools.loadFormField('members', 'firstname', '#firstname');
tools.loadFormField('members', 'pagination', '#NumberResultItemsToDisplay');
// draw members DataTables
Members.fnDraw();
}
[/code]
When I return on the initial page, I get the following error :
Uncaught TypeError: Cannot read property 'sSortAscending' of undefined
After some tests, if I remove this section :
[code]
oLanguage: {
sUrl: '/assets/js/resources/jquery.dataTables.fr-FR.txt'
}
[/code]
in the code above, everything works fine.
Of course I need to keep localization and I can't remove these lines...
Any help would be greatly appreciated ;)
Thx
I try to implement a back feature and I'm having problem. Let me explain.
I have a first page with some search criteria + a search action + a datatable component. Here is the datatable code :
[code]
// target DataTables for members
var Members = $('#Members').dataTable({
aoColumns: [
{ mDataProp: 'avatar', bSortable: false, bUseRendered: true, fnRender: function (o, val) { return tools.dtRenderMemberAvatar(val); }, sClass: 'centeredRow', sWidth: '100px' },
{ mDataProp: 'lastName', sClass: 'centeredRow', sType: 'string', sWidth: '150px' },
{ mDataProp: 'firstName', sClass: 'centeredRow', sType: 'string', sWidth: '150px' },
{ mDataProp: 'gender', sClass: 'centeredRow', sType: 'string', sWidth: '100px' },
{ mDataProp: 'age', sClass: 'centeredRow', sType: 'numeric', sWidth: '50px' },
{ mDataProp: 'level', fnRender: function (o, val) { return tools.dtRenderLevelWithColor(val); }, sClass: 'centeredRow', sType: 'numeric', sWidth: '50px' },
{ mDataProp: 'lastConnection', sClass: 'centeredRow', sType: 'date', sWidth: '300px' }
],
fnCreatedRow: function (nRow, aData, iDataIndex) {
$(nRow).attr('data-user-id', aData.userID);
},
fnServerParams: function (aoData) {
tools.dtSearchOnField(aoData, '#institution', 'InstitutionID');
tools.dtSearchOnField(aoData, '#group', 'GroupID');
tools.dtSearchOnField(aoData, '#level', 'LevelID');
tools.dtSearchOnField(aoData, '#sex', 'IsMaleGender');
tools.dtSearchOnField(aoData, '#lastname', 'LastName');
tools.dtSearchOnField(aoData, '#firstname', 'FirstName');
},
iDisplayLength: 10,
sAjaxSource: '@Url.Action("SearchMembers", "DataTables")',
oLanguage: {
sUrl: '/assets/js/resources/jquery.dataTables.fr-FR.txt'
}
});
[/code]
When the table is bound, I get a list member. I can click on each member to access a second page that displays detailed information (in the same time, criteria are persisted using cookies). On this second page I added a back button to come back on the search page.
On the search page I added this code :
[code]
// handle back action
if (tools.parseQueryString().back) {
// load search form state
tools.loadFormField('members', 'institution', '#institution');
tools.loadFormField('members', 'group', '#group');
tools.loadFormField('members', 'level', '#level');
tools.loadFormField('members', 'sex', '#sex');
tools.loadFormField('members', 'lastname', '#lastname');
tools.loadFormField('members', 'firstname', '#firstname');
tools.loadFormField('members', 'pagination', '#NumberResultItemsToDisplay');
// draw members DataTables
Members.fnDraw();
}
[/code]
When I return on the initial page, I get the following error :
Uncaught TypeError: Cannot read property 'sSortAscending' of undefined
After some tests, if I remove this section :
[code]
oLanguage: {
sUrl: '/assets/js/resources/jquery.dataTables.fr-FR.txt'
}
[/code]
in the code above, everything works fine.
Of course I need to keep localization and I can't remove these lines...
Any help would be greatly appreciated ;)
Thx
This discussion has been closed.
Replies
So two options I think:
1. Put the contents of your translation file into oLanguage - you don't have to get it by Ajax (although it can be useful).
2. Move your continuation code (tools.loadFormField etc) into fnInitComplete which is fired once the table is finally ready.
Allan
Thank u for these advices, it was very helpfull. However I still have a problem about reload the datatable on the selected page (example : I leave by clicking a member on the third page, I need to come back on the third page).
Here is the datatable initialization code :
[code]
// defines default configuration for DataTables
$.extend($.fn.dataTable.defaults, {
bAutoWidth: false,
bFilter: false,
bLengthChange: false,
bProcessing: true,
bServerSide: true,
iDisplayLength: 10,
iDeferLoading: 0,
fnStateLoad: function (oSettings) {
// define datatable prefix for localstorage
var datatablePrefix = 'DataTables_' + window.location.pathname + '_';
// check if back button is clicked
if (tools.parseQueryString().back) {
// restore form values from localstorage
tools.loadFormFields();
// restore datatable settings from localstorage
oSettings._iDisplayLength = JSON.parse(localStorage.getItem(datatablePrefix + 'PageSize'));
oSettings._iDisplayStart = JSON.parse(localStorage.getItem(datatablePrefix + 'PageStart'));
oSettings.aaSorting = JSON.parse(localStorage.getItem(datatablePrefix + 'Sorting'));
}
},
fnStateSave: function (oSettings, oData) {
// define datatable prefix for localstorage
var datatablePrefix = 'DataTables_' + window.location.pathname + '_';
// store form values to localstorage
tools.saveFormFields('div.dt-searchform');
// store datatable settings to localstorage
localStorage.setItem(datatablePrefix + 'PageSize', JSON.stringify(oSettings._iDisplayLength));
localStorage.setItem(datatablePrefix + 'PageStart', JSON.stringify(oSettings._iDisplayStart));
localStorage.setItem(datatablePrefix + 'Sorting', JSON.stringify(oSettings.aaSorting));
},
sPaginationType: 'full_numbers'
});
[/code]
and here is the datatable code in the page :
[code]
// target DataTables for members
var Members = $('#Members').dataTable({
aoColumns: [
{ mDataProp: 'avatar', bSortable: false, bUseRendered: true, fnRender: function (o, val) { return tools.dtRenderMemberAvatar(val); }, sClass: 'centeredRow', sWidth: '100px' },
{ mDataProp: 'lastName', sClass: 'centeredRow', sType: 'string', sWidth: '150px' },
{ mDataProp: 'firstName', sClass: 'centeredRow', sType: 'string', sWidth: '150px' },
{ mDataProp: 'gender', sClass: 'centeredRow', sType: 'string', sWidth: '100px' },
{ mDataProp: 'age', sClass: 'centeredRow', sType: 'numeric', sWidth: '50px' },
{ mDataProp: 'level', fnRender: function (o, val) { return tools.dtRenderLevelWithColor(val); }, sClass: 'centeredRow', sType: 'numeric', sWidth: '50px' },
{ mDataProp: 'lastConnection', sClass: 'centeredRow', sType: 'date', sWidth: '300px' }
],
bStateSave: true,
fnInitComplete: function(oSettings, json) {
if (tools.parseQueryString().back) {
Members.fnDraw();
}
},
fnCreatedRow: function (nRow, aData, iDataIndex) {
$(nRow).attr('data-user-id', aData.userID);
},
fnServerParams: function (aoData) {
tools.dtSearchOnField(aoData, '#institution', 'InstitutionID');
tools.dtSearchOnField(aoData, '#group', 'GroupID');
tools.dtSearchOnField(aoData, '#level', 'LevelID');
tools.dtSearchOnField(aoData, '#sex', 'IsMaleGender');
tools.dtSearchOnField(aoData, '#lastname', 'LastName');
tools.dtSearchOnField(aoData, '#firstname', 'FirstName');
},
oLanguage: {
sUrl: '/assets/js/resources/jquery.dataTables.fr-FR.txt',
},
sAjaxSource: '@Url.Action("SearchMembers", "DataTables")'
});
[/code]
I can restore sorting and items per page correctly but the current page isn't recovered. Should I use iDisplayStart parameter to do it ? If yes, how ? Because the code above doesn't work.
Once again, thank you in advance for your help.
[code]
oSettings._iDisplayStart = oData.iStart;
oSettings.iInitDisplayStart = oData.iStart;
oSettings._iDisplayEnd = oData.iEnd;
oSettings._iDisplayLength = oData.iLength;
[/code]
So I suspect the issue is that iInitDisplayStart is not being set.
Allan
I really appreciate your help. Thank you so much.
To be sure that I do the right thing, here is my new code :
[code]
// target DataTables for members
var Members = $('#Members').dataTable({
aoColumns: [
{ mDataProp: 'avatar', bSortable: false, bUseRendered: true, fnRender: function (o, val) { return tools.dtRenderMemberAvatar(val); }, sClass: 'centeredRow', sWidth: '100px' },
{ mDataProp: 'lastName', sClass: 'centeredRow', sType: 'string', sWidth: '150px' },
{ mDataProp: 'firstName', sClass: 'centeredRow', sType: 'string', sWidth: '150px' },
{ mDataProp: 'gender', sClass: 'centeredRow', sType: 'string', sWidth: '100px' },
{ mDataProp: 'age', sClass: 'centeredRow', sType: 'numeric', sWidth: '50px' },
{ mDataProp: 'level', fnRender: function (o, val) { return tools.dtRenderLevelWithColor(val); }, sClass: 'centeredRow', sType: 'numeric', sWidth: '50px' },
{ mDataProp: 'lastConnection', sClass: 'centeredRow', sType: 'date', sWidth: '300px' }
],
bStateSave: true,
fnInitComplete: function(oSettings, json) {
if (tools.parseQueryString().back) {
Members.fnDraw();
}
},
fnStateLoad: function (oSettings) {
// check if back button is clicked
if (tools.parseQueryString().back) {
// define prefix for localstorage
var fieldsPrefix = 'Fields_' + window.location.pathname + '_';
var datatablePrefix = 'DataTables_' + window.location.pathname + '_';
// restore combo values from sessionstorage
deserializeCombo('#institution', JSON.parse(sessionStorage.getItem(fieldsPrefix + 'InstitutionCombo')));
deserializeCombo('#group', JSON.parse(sessionStorage.getItem(fieldsPrefix + 'GroupCombo')));
// restore fields values from sessionstorage
$('#NumberResultItemsToDisplay').val(JSON.parse(sessionStorage.getItem(fieldsPrefix + 'NumberResultItemsToDisplay')));
$('#institution').val(JSON.parse(sessionStorage.getItem(fieldsPrefix + 'Institution')));
$('#group').val(JSON.parse(sessionStorage.getItem(fieldsPrefix + 'Group')));
$('#level').val(JSON.parse(sessionStorage.getItem(fieldsPrefix + 'Level')));
$('#lastname').val(JSON.parse(sessionStorage.getItem(fieldsPrefix + 'LastName')));
$('#firstname').val(JSON.parse(sessionStorage.getItem(fieldsPrefix + 'FirstName')));
$('#sex').val(JSON.parse(sessionStorage.getItem(fieldsPrefix + 'Sex')));
// restore datatable settings from sessionstorage
oSettings._iDisplayLength = JSON.parse(sessionStorage.getItem(datatablePrefix + 'PageSize'));
oSettings._iDisplayStart = JSON.parse(sessionStorage.getItem(datatablePrefix + 'PageStart'));
oSettings.aaSorting = JSON.parse(sessionStorage.getItem(datatablePrefix + 'Sorting'));
}
},
fnStateSave: function (oSettings, oData) {
// define prefix for sessionstorage
var fieldsPrefix = 'Fields_' + window.location.pathname + '_';
var datatablePrefix = 'DataTables_' + window.location.pathname + '_';
// store fields combo values to sessionstorage
sessionStorage.setItem(fieldsPrefix + 'InstitutionCombo', JSON.stringify(serializeCombo('#institution')));
sessionStorage.setItem(fieldsPrefix + 'GroupCombo', JSON.stringify(serializeCombo('#group')));
// store fields values to sessionstorage
sessionStorage.setItem(fieldsPrefix + 'NumberResultItemsToDisplay', JSON.stringify($('#NumberResultItemsToDisplay').val()));
sessionStorage.setItem(fieldsPrefix + 'Institution', JSON.stringify($('#institution').val()));
sessionStorage.setItem(fieldsPrefix + 'Group', JSON.stringify($('#group').val()));
sessionStorage.setItem(fieldsPrefix + 'Level', JSON.stringify($('#level').val()));
sessionStorage.setItem(fieldsPrefix + 'LastName', JSON.stringify($('#lastname').val()));
sessionStorage.setItem(fieldsPrefix + 'FirstName', JSON.stringify($('#firstname').val()));
sessionStorage.setItem(fieldsPrefix + 'Sex', JSON.stringify($('#sex').val()));
// store datatable settings to sessionstorage
sessionStorage.setItem(datatablePrefix + 'PageSize', JSON.stringify(oSettings._iDisplayLength));
sessionStorage.setItem(datatablePrefix + 'PageStart', JSON.stringify(oSettings._iDisplayStart));
sessionStorage.setItem(datatablePrefix + 'Sorting', JSON.stringify(oSettings.aaSorting));
oSettings._iDisplayStart = oData.iStart;
oSettings.iInitDisplayStart = oData.iStart;
oSettings._iDisplayEnd = oData.iEnd;
oSettings._iDisplayLength = oData.iLength;
},
fnCreatedRow: function (nRow, aData, iDataIndex) {
$(nRow).attr('data-user-id', aData.userID);
},
fnServerParams: function (aoData) {
tools.dtSearchOnField(aoData, '#institution', 'InstitutionID');
tools.dtSearchOnField(aoData, '#group', 'GroupID');
tools.dtSearchOnField(aoData, '#level', 'LevelID');
tools.dtSearchOnField(aoData, '#sex', 'IsMaleGender');
tools.dtSearchOnField(aoData, '#lastname', 'LastName');
tools.dtSearchOnField(aoData, '#firstname', 'FirstName');
},
oLanguage: {
sUrl: '/assets/js/resources/jquery.dataTables.fr-FR.txt',
},
sAjaxSource: '@Url.Action("SearchMembers", "DataTables")'
});
[/code]
Is it what you expected ?
If I do that, the pagination doesn't work anymore. I systematically stay on page 1 when I try to go on another page. So I can't go on page 2 to process my test...
[code]
// restore datatable settings from sessionstorage
oSettings._iDisplayStart = JSON.parse(sessionStorage.getItem(datatablePrefix + 'Start'));
oSettings.iInitDisplayStart = JSON.parse(sessionStorage.getItem(datatablePrefix + 'Start'));
oSettings._iDisplayEnd = JSON.parse(sessionStorage.getItem(datatablePrefix + 'End'));
oSettings._iDisplayLength = JSON.parse(sessionStorage.getItem(datatablePrefix + 'Length'));
oSettings.aaSorting = JSON.parse(sessionStorage.getItem(datatablePrefix + 'Sorting'));
[/code]
The initial pagination works now (as before), but the current page is still not selected when I use Back feature. fnDraw seems to systematically reset _iDisplayStart property to 0...