I am trying to use stateSave on a DataTable so when the user selects a project it then goes back to the page puts the DataTable on the page that the project was on. I can't seem to get the stateSave to work for me. It always seems to reset back to the first page. I tried putting activeTable.draw(false);
and inactiveTable.draw(false);
with no luck. I see that the data is getting reset each time the table is being built which I believe is overriding the stateSave. I have comment out .clear()
but that didn't help either. I tried checking on populating the table without using .draw()
but I found that if I don't have .draw()
then the DataTable doesn't show the rows.
window.onload = Init;
var activeCnt = 0, inactiveCnt = 0;
var activeTable;
function Init() {
activeTable = $('#activeTable').DataTable({
order: [[0, 'asc']],
columnDefs: [
{ targets: -1, className: 'text-center' }
],
stateSave: true
});
inactiveTable = $('#inactiveTable').DataTable({
order: [[0, 'asc']],
columnDefs: [
{ targets: -1, className: 'text-center' },
{ targets: -1, className: 'text-center' }
],
stateSave: true
});
//Get view
GetProjectsList();
}
function GetProjectsList() {
$.ajax({
url: "/Projects/GetProjects",
type: 'GET',
success: function (dta) {
view = dta;
PopulateProjectTable();
}
});
}
function PopulateProjectTable() {
activeCnt = 0;
inactiveCnt = 0;
// clear project table data
activeTable.clear();
inactiveTable.clear();
for (var i = 0; i < view.projects.length; i++) {
var prj = view.projects[i];
var hrTtl = (prj.Sums != null) ? prj.Sums.PrjTotalHours : 0;
// populate the table
if (prj.PrjStatusID == 1) { // if project belongs to the active table
activeTable.row.add([prj.PrjName, prj.PrjProgressName, prj.PrjStartDateStr, prj.PrjEndDateStr, "$" + prj.PrjBudgetAmt + ".00", "$" + prj.PrjBudgetAmt + ".00", hrTtl + " hrs.",
`<i class="fas fa-search add-pointer text-primary" onclick="ViewProject(${prj.PrjID})"></i><i class="fas fa-edit add-pointer text-primary" onclick="EditProject(${prj.PrjID})" data-bs-toggle="modal" data-bs-target="#modal-prj-details"></i>`]);
activeCnt++;
}
else { // inactive table
inactiveTable.row.add([prj.PrjName, prj.PrjProgressName, prj.PrjStartDateStr, prj.PrjEndDateStr, "$" + prj.PrjBudgetAmt + ".00", hrTtl + " hrs.", prj.PrjStatusName,
`<i class="fas fa-search add-pointer text-primary" onclick="ViewProject(${prj.PrjID})"></i><i class="fas fa-edit no-click text-secondary"></i>`]);
inactiveCnt++;
}
}
activeTable.draw(false);
inactiveTable.draw(false);
document.getElementById("actCnt").innerHTML = activeCnt;
document.getElementById("inactCnt").innerHTML = inactiveCnt;
}
You can re-arrange your logic so that your DataTables use the built-in support for Ajax data sources. This will allow you to use the saved state data you want to use.
See here for an overview of the DataTables Ajax syntax.
See here for Ajax examples.
Your current approach initializes your Data Tables - and then after the tables have been initialized, it populates those tables with your Ajax data - which invalidates any state which may have been saved.
By using the built-in Ajax approach, your data will be populated as part of the initialization process, and can use saved state to restore the relevant page of results during initialization.
Here is a basic demo, but there are some points to note:
There is no JSON data in the question, so I had to invent some.
I don't have your server-side Ajax provider, so I faked that piece in my code. See callback( getActiveProjects(view) )
. This is NOT exactly what you need, as you have your JSON delivered by your Ajax (not my hard-coded data). But the basic structure is there for you to adapt.
Let DataTables decide how to map from your JSON to each specific column - see the columns: [ ... ]
section I added.
You have additional formatting of data - for example, your <i>
links and FontAwesome icons. You can use a column renderer for that, as one way to handle this.
I have not used your two tables - my demo only needs one table to show my approach. Your logic would need to account for how you split your JSON data for the 2 tables.
But the main point is, this will now respect the stateSave: true
option.
Here is the code:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Demo</title>
<link href="https://cdn.datatables.net/2.0.1/css/dataTables.dataTables.min.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>
<script src="https://cdn.datatables.net/2.0.1/js/dataTables.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://datatables.net/media/css/site-examples.css">
</head>
<body>
<div style="margin: 20px;">
<table id="activeTable" class="display dataTable cell-border" style="width:100%">
<thead>
<tr>
<th>PrjName</th>
<th>PrjProgressName</th>
<th>PrjStartDateStr</th>
<th>PrjEndDateStr</th>
<th>PrjBudgetAmt</th>
<th>PrjBudgetAmt</th>
<th>hrTtl</th>
<th>PrjID</th>
</tr>
</thead>
</table>
<div id="actCnt"></div>
</div>
<script>
$(document).ready(function() {
function Init() {
var view = { "projects": [
{ "PrjName": "a", "PrjProgressName": "b", "PrjStartDateStr": "c", "PrjEndDateStr": "d", "PrjBudgetAmt": 123, "hrTtl": 234, "PrjID": "foo", "PrjStatusID": 1 },
{ "PrjName": "b", "PrjProgressName": "b", "PrjStartDateStr": "c", "PrjEndDateStr": "d", "PrjBudgetAmt": 123, "hrTtl": 234, "PrjID": "foo", "PrjStatusID": 1 },
{ "PrjName": "c", "PrjProgressName": "b", "PrjStartDateStr": "c", "PrjEndDateStr": "d", "PrjBudgetAmt": 123, "hrTtl": 234, "PrjID": "foo", "PrjStatusID": 1 },
{ "PrjName": "d", "PrjProgressName": "b", "PrjStartDateStr": "c", "PrjEndDateStr": "d", "PrjBudgetAmt": 123, "hrTtl": 234, "PrjID": "foo", "PrjStatusID": 1 },
{ "PrjName": "e", "PrjProgressName": "b", "PrjStartDateStr": "c", "PrjEndDateStr": "d", "PrjBudgetAmt": 123, "hrTtl": 234, "PrjID": "foo", "PrjStatusID": 1 },
{ "PrjName": "f", "PrjProgressName": "b", "PrjStartDateStr": "c", "PrjEndDateStr": "d", "PrjBudgetAmt": 123, "hrTtl": 234, "PrjID": "foo", "PrjStatusID": 1 },
{ "PrjName": "g", "PrjProgressName": "b", "PrjStartDateStr": "c", "PrjEndDateStr": "d", "PrjBudgetAmt": 123, "hrTtl": 234, "PrjID": "foo", "PrjStatusID": 1 },
{ "PrjName": "h", "PrjProgressName": "b", "PrjStartDateStr": "c", "PrjEndDateStr": "d", "PrjBudgetAmt": 123, "hrTtl": 234, "PrjID": "foo", "PrjStatusID": 1 },
{ "PrjName": "i", "PrjProgressName": "b", "PrjStartDateStr": "c", "PrjEndDateStr": "d", "PrjBudgetAmt": 123, "hrTtl": 234, "PrjID": "foo", "PrjStatusID": 1 },
{ "PrjName": "j", "PrjProgressName": "b", "PrjStartDateStr": "c", "PrjEndDateStr": "d", "PrjBudgetAmt": 123, "hrTtl": 234, "PrjID": "foo", "PrjStatusID": 1 },
{ "PrjName": "k", "PrjProgressName": "b", "PrjStartDateStr": "c", "PrjEndDateStr": "d", "PrjBudgetAmt": 123, "hrTtl": 234, "PrjID": "foo", "PrjStatusID": 1 },
{ "PrjName": "l", "PrjProgressName": "b", "PrjStartDateStr": "c", "PrjEndDateStr": "d", "PrjBudgetAmt": 123, "hrTtl": 234, "PrjID": "foo", "PrjStatusID": 1 }
] } ;
activeTable = $('#activeTable').DataTable({
order: [[0, 'asc']],
columnDefs: [
{ targets: -1, className: 'text-center' }
],
columns: [
{ data: 'PrjName' },
{ data: 'PrjProgressName' },
{ data: 'PrjStartDateStr' },
{ data: 'PrjEndDateStr' },
{ data: 'PrjBudgetAmt' },
{ data: 'PrjBudgetAmt' },
{ data: 'hrTtl' },
{ data: 'PrjID' }
],
ajax: function (data, callback, settings) {
callback( getActiveProjects(view) );
},
stateSave: true
});
}
function getActiveProjects(view) {
var actives = view.projects.filter(function (project) {
return project.PrjStatusID == 1;
});
return { "data": actives };
}
Init();
} );
</script>
</body>
</html>
So, this shows one way how to resolve your issue - but it does involve a significant restructuring, and therefore may require you to research some extra features of DataTables as noted already. There are many questions and answers on Stack Overflow which can assist with those other steps, if you get stuck.
Final note: There is often more than one way to achieve what you want in DataTables. So there may be other approaches which are acceptable.
Some thoughts about that: You can maybe preserve more of your existing approach and code, and use:
and/or:
These give you much more control over what DataTables state gets saved and how you can retrieve it.
You can then jump to the relevant page in DataTables.