Persistent CheckBox State in MVC Telerik grid when paging in ASP.NET MVC application

I use the Telerik MVC grid, where one of the columns is the checkboxes. If I select the checkboxes, then go to page 2 and then go back to page 1, all the checkboxes will disappear. This, of course, is the way HTTP works. Now I put all the selected checkboxes inside the hidden field, but since the grid does some kind of postback, my hidden field is cleared the next time.

+4
source share
3 answers

If you are using client-side data binding, you can use javascript / jquery below to maintain the state of the checkbox.

Maintain checkbox status:

var selectedIds = []; $(document).ready(function () { //wire up checkboxes. $('#YOUR_GRID_ID :checkbox').live('change', function (e) { var $check = $(this); console.log($check); if ($check.is(':checked')) { //add id to selectedIds. selectedIds.push($check.val()); } else { //remove id from selectedIds. selectedIds = $.grep(selectedIds, function (item, index) { return item != $check.val(); }); } }); }); 

Restore flag state after data binding:

 function onDataBound(e) { //restore selected checkboxes. $('#YOUR_GRID_ID :checkbox').each(function () { //set checked based on if current checkbox value is in selectedIds. $(this).attr('checked', jQuery.inArray($(this).val(), selectedIds) > -1); }); } 

A more detailed explanation is available on my blog: http://blog.cdeutsch.com/2011/02/preserve-telerik-mvc-grid-checkboxes.html

+11
source

You need to save the state of the checkboxes in your database, and then restore them again from the database when you reload the page.

During paging, you only need to reload entries that relate to a particular page. You can do this with Linq's Skip() and Take() methods.

0
source

to save the check checked / unchecked checkbox with the telerik grid clientemplate through callbacks and asynchronous callbacks, as well as in grid updates and (auto) paging, I tried the solution above to no avail and therefore went with a more complicated solution; since I could not save state in db, I used a session variable and a hidden field:

firstly, a way to do the ajax postback (see DoAjaxPostAndMore function, courtesy of someone here), where in the process of success we take care of client values โ€‹โ€‹of samples, adding and deleting them as marked / unchecked

I also had to manually check / uncheck the checkboxes inside the ajax post manual

secondly, a hidden field (see "hidSelectedRefs") for saving client operations, because the Session variable that I use will not be considered by clients in partial rendering

 @model IEnumerable<yourInterfaceOrClass> @{ ViewBag.Title = "Select Something via checkboxes"; Layout = "~/Views/Shared/_Layout.cshtml"; } <h2>Select Something via checkboxes</h2> <!-- we need a form with an id, action must be there but can be an empty string --> <form id="frm" name ="frm" action=""> <p> <!--we need this as Session new values will not be takein in aajax requests clientisde, so it is easier to mange this field, which, in first and subsequent complete postbacks can have the value of the Session variable --> <input type="hidden" name="hidSelectedRefs" id="hidSelectedRefs" value= '@Session["SelectedReferencesToPrint"]' /> </p> <br /> <script type="text/javascript"> //ajax manual post to a custom action of controller, passing the id of record and the state of the checkbox //to adjust the Session value //data: $form.serialize() will have the single checbox value //but only if checked. To make my life eaasier, I added the value (is id ) and the checked/unchecked //state of checkbox (is the $(chkClicked).attr('checked')) function DoAjaxPostAndMore(chkClicked) { var $form = $("#frm"); $.ajax({ type: "POST", url: 'SelectReferences', data: $form.serialize() + '&id=' + $(chkClicked).val() + '&checked=' + $(chkClicked).attr('checked'), error: function (xhr, status, error) { //do something about the error alert("Sorry, we were not able to get your selection..."); }, success: function (response) { //I also needed to check / uncheck manually the checkboxes: $(chkClicked).attr('checked', !$(chkClicked).attr('checked')); //and now put correct values in hidSelectedRefs hidden field: if ($(chkClicked).attr('checked')) { $('input[name=hidSelectedRefs]').val($('input[name=hidSelectedRefs]').val() + '|' + $(chkClicked).val() + '|'); } else { var tmp = $('input[name=hidSelectedRefs]').val(); $('input[name=hidSelectedRefs]').val(tmp.toString().replace('|' + $(chkClicked).val() + '|', '')); } } }); return false; // if it a link to prevent post }


 Then I handled the OnRowDataBound, to ensure the checboxes would be correctly checked on postbacks,
function onRowDataBound(e) { var itemsChecked = $('input[name=hidSelectedRefs]').val(); if (itemsChecked) { if (itemsChecked.indexOf('|' + $(e.row).find('input[name=checkedRecords]').val() + '|') >= 0) { $(e.row).find('input[name=checkedRecords]').attr('checked', true); } } } </script>

     The telerik mvc Grid is as follows:
    
(you can see I also handled OnDataBinding and OnDataBound, but thats only to show a "Loading" gif. The controller is named "Output" and the action that normally would be called "Index" here is callled "PrintReferences". The correspondenting Ajax action is called "_PrintReferences") Of interest here is the ClientTemplate for checkbox (cortuesy of someone else herearound, where onclick we call our custom ajax action (named "SelectReferences") on our Output controller via a call to the DoAjaxPostAndMore () javascript / jquery function @(Html.Telerik().Grid<yourInterfaceOrClass>() .Name("Grid") .ClientEvents(e => e.OnDataBinding("showProgress").OnDataBound("hideProgress").OnRowDataBound("onRowDataBound")) .DataBinding(dataBinding => { dataBinding.Server().Select("PrintReferences", "Output", new { ajax = ViewData["ajax"]}); dataBinding.Ajax().Select("_PrintReferences", "Output").Enabled((bool)ViewData["ajax"]); }) .Columns( columns => { columns.Bound(o => o.ID); columns.Bound(o => o.ID) .ClientTemplate( "<input type='checkbox' name='checkedRecords' value='<#= ID #>' onclick='return DoAjaxPostAndMore(this)' />" ) .Width(30) .Title("") .HtmlAttributes(new { style = "text-align:center; padding: 0px; margin: 0px;" }); columns.Bound(o => o.TITLE); columns.Bound(o => o.JOBCODE); columns.Bound(o => o.ORDERCODE ); //columns.Bound(o => o.AUTHOR); columns.Bound(o => o.STATE); columns.Command(commands => commands .Custom("Details") .ButtonType(GridButtonType.Image) .HtmlAttributes(new { @class = "t-icon-details" }) .DataRouteValues(route => route.Add(o => o.ID) .RouteKey("ID")) .Ajax(false) .Action("Details", "Referenza") ); }) .Pageable(paging => paging.PageSize(10) .Style(GridPagerStyles.NextPreviousAndNumeric) .Position(GridPagerPosition.Bottom)) .Sortable() .Filterable() .Resizable(resizing => resizing.Columns(true)) .Reorderable(reorder => reorder.Columns(true)) .NoRecordsTemplate("No Reference found. Please review your filters...") .ColumnContextMenu() ) </form> that all for the View. Now, to the controller: //Get : this is the usally called "Index" action //here we can load data, but we also must ensure the Session variable is fine public ActionResult PrintReferences(bool? ajax, string msgInfo, string selectedRef) { if (Session["SelectedReferencesToPrint"] == null) { Session["SelectedReferencesToPrint"] = string.Empty; } if (string.IsNullOrEmpty(selectedRef)) { selectedRef = "|0|"; } string msgOut = string.Empty; //this is where I get data to show List<yourInterfaceOrClass> ret = LoadData(out msgOut); if (!string.IsNullOrEmpty(msgInfo) && !string.IsNullOrEmpty(msgInfo.Trim())) { msgOut = msgInfo + ' ' + msgOut; } ViewBag.msgOut = msgOut; ViewData["ajax"] = ajax ?? true; return View(ret); } //GridAction: here is telerik grid Ajax get request for your "_Index" [GridAction] public ActionResult _PrintReferences(string msgInfo) { //again, we must take care of Session variable if (Session["SelectedReferencesToPrint"] == null) { Session["SelectedReferencesToPrint"] = string.Empty; } string msgOut = string.Empty; List<yourInterfaceOrClass> ret = LoadData(out msgOut); return View(new GridModel(ret)); } //Post: this is where our custom ajax post goes //we are here if a checkbox is cheched or unchecked //in the FormCollection parameter we get the checkbox value only if checked, and also //(and always) the parms we passed (id of record and state of checkbox: we cannot simply add, //we must also subtract unchecked) [HttpPost] public ActionResult SelectReferences(FormCollection collection) { //we need a session variable if (Session["SelectedReferencesToPrint"] == null) { Session["SelectedReferencesToPrint"] = string.Empty; } //use a local variable for calculations string wholeSelectionToPrint = Session["SelectedReferencesToPrint"].ToString(); //get value passed: id string selectedRefId = collection["id"]; if (!string.IsNullOrEmpty(selectedRefId)) { selectedRefId = "|" + selectedRefId + "|"; } bool cheked = (collection["checked"].ToString()=="checked"); //get vcalue passed :checked or unchecked if (cheked) { //the element is to add wholeSelectionToPrint += selectedRefId; } else { //the element is to remove wholeSelectionToPrint = wholeSelectionToPrint.Replace(selectedRefId, ""); } //set session variable final value Session["SelectedReferencesToPrint"] = wholeSelectionToPrint; return null; } //normal postback: //we will be here if we add a button type submit in our page, //here we can collect all data from session variable to do //something with selection [HttpPost] public ActionResult PrintReferences(FormCollection collection) { //get selected references id if (Session["SelectedReferencesToPrint"] == null) { Session["SelectedReferencesToPrint"] = string.Empty; } //use a local variable for calculations string wholeSelectionToPrint = Session["SelectedReferencesToPrint"].ToString(); wholeSelectionToPrint = wholeSelectionToPrint.Replace("||", "|"); string[] selectdIDs = wholeSelectionToPrint.Split(new char[] { '|' }); foreach (string id in selectdIDs) { if (!string.IsNullOrEmpty(id)) { //do something with single selected record ID System.Diagnostics.Debug.WriteLine(id); } } //omitted [....] ViewData["ajax"] = true; return View(ret); } //Get : this is the usally called "Index" action //here we can load data, but we also must ensure the Session variable is fine public ActionResult PrintReferences(bool? ajax, string msgInfo, string selectedRef) { if (Session["SelectedReferencesToPrint"] == null) { Session["SelectedReferencesToPrint"] = string.Empty; } if (string.IsNullOrEmpty(selectedRef)) { selectedRef = "|0|"; } string msgOut = string.Empty; //this is where I get data to show List<yourInterfaceOrClass> ret = LoadData(out msgOut); if (!string.IsNullOrEmpty(msgInfo) && !string.IsNullOrEmpty(msgInfo.Trim())) { msgOut = msgInfo + ' ' + msgOut; } ViewBag.msgOut = msgOut; ViewData["ajax"] = ajax ?? true; return View(ret); } //GridAction: here is telerik grid Ajax get request for your "_Index" [GridAction] public ActionResult _PrintReferences(string msgInfo) { //again, we must take care of Session variable if (Session["SelectedReferencesToPrint"] == null) { Session["SelectedReferencesToPrint"] = string.Empty; } string msgOut = string.Empty; List<yourInterfaceOrClass> ret = LoadData(out msgOut); return View(new GridModel(ret)); } //Post: this is where our custom ajax post goes //we are here if a checkbox is cheched or unchecked //in the FormCollection parameter we get the checkbox value only if checked, and also //(and always) the parms we passed (id of record and state of checkbox: we cannot simply add, //we must also subtract unchecked) [HttpPost] public ActionResult SelectReferences(FormCollection collection) { //we need a session variable if (Session["SelectedReferencesToPrint"] == null) { Session["SelectedReferencesToPrint"] = string.Empty; } //use a local variable for calculations string wholeSelectionToPrint = Session["SelectedReferencesToPrint"].ToString(); //get value passed: id string selectedRefId = collection["id"]; if (!string.IsNullOrEmpty(selectedRefId)) { selectedRefId = "|" + selectedRefId + "|"; } bool cheked = (collection["checked"].ToString()=="checked"); //get vcalue passed :checked or unchecked if (cheked) { //the element is to add wholeSelectionToPrint += selectedRefId; } else { //the element is to remove wholeSelectionToPrint = wholeSelectionToPrint.Replace(selectedRefId, ""); } //set session variable final value Session["SelectedReferencesToPrint"] = wholeSelectionToPrint; return null; } //normal postback: //we will be here if we add a button type submit in our page, //here we can collect all data from session variable to do //something with selection [HttpPost] public ActionResult PrintReferences(FormCollection collection) { //get selected references id if (Session["SelectedReferencesToPrint"] == null) { Session["SelectedReferencesToPrint"] = string.Empty; } //use a local variable for calculations string wholeSelectionToPrint = Session["SelectedReferencesToPrint"].ToString(); wholeSelectionToPrint = wholeSelectionToPrint.Replace("||", "|"); string[] selectdIDs = wholeSelectionToPrint.Split(new char[] { '|' }); foreach (string id in selectdIDs) { if (!string.IsNullOrEmpty(id)) { //do something with single selected record ID System.Diagnostics.Debug.WriteLine(id); } } //omitted [....] ViewData["ajax"] = true; return View(ret); }
0
source

Source: https://habr.com/ru/post/1336493/


All Articles