Full solution to restore lost form values due to searching / paging
Full solution to restore lost form values due to searching / paging
I'm posting this solution here as it took me several hours of searching the forums and internet, and i couldn't find one post that had a complete solution. since this is such a common requirement for server platforms like .Net and PHP, can i suggest that it could be one of the built-in options for the DataTable() constructor in the API, e.g. preserveFormValuesForHiddenRows: true
it was quite a jarring discovery to find that off-screen values were being lost, my (admittedly ill-informed) expectation was that the DataTables API was non-destructive to the HTML form state. I would suggest that the proposed new option would be turned on by default, or else have some in-your-face message on all pages relating to form inputs: "WARNING IF YOU ARE USING ANY SERVER PLATFORM THEN YOU REALLY SHOULD USE THIS OPTION TO AVOID UNEXPECTED SIDE EFFECTS OF CLIENT-SIDE PAGING/SORTING...."
the background to this problem is detailed here:
https://datatables.net/examples/api/form.html
The javascript example code on this page shows how to select hidden form values and access them on the client side. I think it would also be useful to give an example of how to restore those lost form values so that server platforms are not affected by the user performing a client-side page/search.
here is the code i have gleaned from several sources:
$(document).ready(function()
{
var dt = $('#myTable').DataTable({
'order': [], // bypass default first-pass sorting by DataTables API that changes with the original sort order
stateSave: true // persist search/page state across postbacks and page loads
});
$('form').submit(function(){
// create a hidden div, otherwise all the values are displayed on screen momentarily while the form submits
var $div = $('<div>', {style: 'display:none'});
// append all hidden inputs to the hidden div
$(dt.rows({search:'removed'}).nodes()).find('input').appendTo($div);
// append the hidden div to the form
$($div).appendTo(this);
});
}
);
While i'm at it, here is a derived GridView class for .Net users who want an 'out of the box' component that delivers DataTables support for the .Net GridView, with the above functionality built-in.
/// <summary>
/// A standard asp.net Gridview control that is customised for use with the DataTables jquery API.
/// The page should reference the correct javascript and css files:
/// https://code.jquery.com/jquery-1.12.0.min.js
/// https://cdn.datatables.net/1.10.10/js/jquery.dataTables.min.js
/// https://cdn.datatables.net/1.10.10/css/jquery.dataTables.min.css
/// </summary>
public class JsGridView : GridView
{
public JsGridView()
{
// all done on client side
this.AllowCustomPaging = false;
this.AllowPaging = false;
this.AllowSorting = false;
this.CssClass = "display";
this.GridLines = GridLines.None;
// change the GridView to use a tHead element
this.DataBound += (object o, EventArgs ev) =>
{
if(this.HeaderRow != null)
this.HeaderRow.TableSection = TableRowSection.TableHeader;
};
this.Init += JsGridView_Init;
}
private void JsGridView_Init(object sender, EventArgs e)
{
// DataTables loses all form values that are not visible on the page, due to paging / searching etc
// these need to be manually stitched in to the form, ref: https://datatables.net/examples/api/form.html
string script = String.Format(@"
$(document).ready(function()
{{
var dt = $('#{0}').DataTable({{
'order': [], // bypass default first-pass sorting by DataTables API that interferes with the original sort order
stateSave: true // persist search/page state across postbacks and page loads
}});
$('form').submit(function(){{
// create a hidden div
var $div = $('<div>', {{class: 'hide'}});
// append all hidden inputs to the hidden div
$(dt.rows({{search:'removed'}}).nodes()).find('input').appendTo($div);
// append the hidden div to the form
$($div).appendTo(this);
}});
}}
);", this.ClientID);
this.Page.ClientScript.RegisterStartupScript(typeof(string), this.ClientID, script, true);
}
}