Full solution to restore lost form values due to searching / paging

Full solution to restore lost form values due to searching / paging

Timmer3Timmer3 Posts: 1Questions: 0Answers: 0

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);
            
        }
    }
This discussion has been closed.