1

I have implemented Serverside processing for the jquery datatable. There is a functionality which is working fine for the "ClientSide Processing" but not working when implemented using "Serverside Processing".

My issue is, while navigating from one page to another page in the jquery datatable, if any changes exists(in textbox/dropdown in any cell), then display error message and don't navigate to the next page.

I am able to achieve this above scenario, using client side. But unable to do in server side.

In client side i have implemented like this

(document).ready(function () {
        var isSuperUser = '@isUserSuperAdmin';
        var oTable = $('#tblnotreportingdetails').dataTable(
           {
               dom: 'Bfrtip',
               oLanguage: {
                   sSearch: '<i class="fa fa-search">&nbsp; </i>'
               },                  
               iDisplayLength: 7,
               buttons: [
               {
                   extend: 'copy',
                   text: '<i class="fa fa-files-o fa-2x" style="color: green;"></i>',
                   titleAttr: 'Copy',
                   exportOptions: {
                       columns: "thead th:not(.noExport)"
                   }
               },
               {
                   extend: 'excel',
                   text: '<i class="fa fa-file-excel-o fa-2x" style="color: green;"></i>',
                   titleAttr: 'Excel',
                   exportOptions: {
                       columns: "thead th:not(.noExport)"
                   }
               },
               {
                   extend: 'csv',
                   text: '<i class="fa fa-file-text-o fa-2x" style="color: green;"></i>',
                   titleAttr: 'CSV',
                   exportOptions: {
                       columns: "thead th:not(.noExport)"
                   }
               },
               {
                   extend: 'pdf',
                   text: '<i class="fa fa-file-pdf-o fa-2x" style="color: green;"></i>',
                   titleAttr: 'PDF',
                   exportOptions: {
                       columns: "thead th:not(.noExport)"
                   }
               },
               {
                   extend: 'print',
                   text: '<i class="fa fa-print fa-2x" style="color: green;"></i>',
                   titleAttr: 'Print',
                   exportOptions: {
                       columns: "thead th:not(.noExport)"
                   }
               }]
           });

        //Function to alert the user to save information on navigating to the next page through Pagination
        $('#tblnotreportingdetails').on('page.dt', function () {
            var selectedReasonKeyArr = [];
            //Getting the current page visible rows (10 rows/20 rows/50 rows/100 rows - default is 10 rows)
            var rows = $("#tblnotreportingdetails tbody tr");
            for (var index = 0; index < rows.length; index++) {
                //Getting each row
                var singleRow = $(rows[index]);
                //Get the Reason Dropdown selected value
                var selectedReasonKey = singleRow.find(":selected").val();
                var selectedReasonText = singleRow.find(":selected").text();
                var existingReasonText = $.trim(singleRow.find('td').eq(9).html());
                //If the selected value is not empty (is empty only when the text is "--Select--")
                if (selectedReasonKey != "") {
                    existingReasonText = decodeEntities(existingReasonText);
                    if (selectedReasonText != existingReasonText) {  //Add to the Array
                        //alert("existingReasonText : " + existingReasonText + "selectedReasonText : " + selectedReasonText);
                        selectedReasonKeyArr.push(selectedReasonKey);
                    }
                }
            }

            //Check if the Array length is more than 0 then display message
            if (selectedReasonKeyArr.length > 0) {
                // alert("Please save unsaved Data before Navigating to the next Page.");
                var existingErrMessage = $('#divNrpErrorMessage').text();
                if (existingErrMessage.indexOf("Please save unsaved Data before Navigating to the next Page.") == -1) {
                    var newErrorMessage = existingErrMessage + " Please save unsaved Data before Navigating to the next Page.";
                    $('#divNrpErrorMessage').text(newErrorMessage);
                }
                //Finding the first row of the selected page and staying on the same page by using the below extension method
                oTable.fnGetPageOfRow(rows[0]);
            }
            else {
                $('#divNrpErrorMessage').text('');
                $('#divNrpSuccessMessage').text('');
            }
        });
    });

In client side, i am able to do it easily by using the extension method oTable.fnGetPageOfRow(rows[0]);

For Server side processing my code like below

       [HttpPost, OutputCache(Duration = 0, NoStore = true)]
        public JsonResult LoadNotReportingDataTable()
        {
            var draw = Request.Form.GetValues("draw").FirstOrDefault();
            var start = Request.Form.GetValues("start").FirstOrDefault();
            var length = Request.Form.GetValues("length").FirstOrDefault();
            var sortColumn = Request.Form.GetValues("columns[" + Request.Form.GetValues("order[0][column]").FirstOrDefault() + "][name]").FirstOrDefault();
            var sortColumnDir = Request.Form.GetValues("order[0][dir]").FirstOrDefault();
            var search = Request.Form.GetValues("search[value]").FirstOrDefault().ToLower();
            int pageSize = length != null ? Convert.ToInt32(length) : 0;
            int skip = start != null ? Convert.ToInt32(start) : 0;
            int totalRecord = 0;
            int filteredRecord = 0;

            var assetsNotReportingModelList = new List<AssetsNotReportingModel>();                                     
            var result = GetAssetsByNotReportingReasonWiseCountDts(15, "0", "0", "0", "0", "0", "0", "0", "0", "NR").ToList();
            assetsNotReportingModelList.AddRange(result);

            //Assign the totalrecord for jquery datatable - server side processing
            totalRecord = assetsNotReportingModelList != null ? assetsNotReportingModelList.Count() : totalRecord;
            var v = (from item in assetsNotReportingModelList select item);
            if (!(string.IsNullOrEmpty(sortColumn) && !(string.IsNullOrEmpty(sortColumnDir))))
            {
                v = v.OrderBy(sortColumn + " " + sortColumnDir);
            }
            filteredRecord = v.ToList().Count();
            var data = pageSize == -1 ? v.ToList() : v.Skip(skip).Take(pageSize).ToList();

            JsonResult json = Json(new
            {
                draw = draw,
                recordsFilterd = filteredRecord,
                recordsTotal = totalRecord,
                iTotalRecords = totalRecord,
                iTotalDisplayRecords = filteredRecord,
                data = data
            }, JsonRequestBehavior.AllowGet);
            json.MaxJsonLength = int.MaxValue;
            return json;
        }

ServerSide Processing - Javascript code here

var prestart = 0;
var prepaginationval = 1;

$(document).ready(function () {
    var isSuperUser = '@isUserSuperAdmin';
    var notReportingPaginationArr = [];
    var oTable = $('#tblnotreportingdetails').dataTable({
        "ajax": {
            "url": "@Url.Action("LoadNotReportingDataTable", "Home")",
            "type": "POST",
            "datatype": "json",
            "headers": headers,
            "beforeSend": function (xhr, opts) {
                //debugger;
                //if any changes available in the current  page(reason/remark) tnen get the current page number and assign to the global variable
                if (notReportingPaginationArr.length > 0) {
                    prepaginationval = $('#tblnotreportingdetails_wrapper').find('.dataTables_paginate').find('ul.pagination').find('li.active a').attr("data-dt-idx");
                    //alert('pervious page no : ' + prepaginationval);
                }
            },
            "data": function (d) {
                d.nrp = JSON.stringify(notReportingPaginationArr);
                d.prestart = prestart;
                return d;
            },
        },
        "dom": 'Bftrip',
        "oLanguage": {
            "sSearch": '<i class="fa fa-search">&nbsp; </i>'
        },
        "paging": true,
        "pagingType": "full_numbers",
        "pageLength": 7,
        "serverSide": true,
        "processing": true,
        "language": {
            "loadingRecords": "&nbsp;",
            'processing': "<i id='processingIcon' class='fa fa-cog fa-spin fa-2x'></i>"
        },
        "columns": [

            {
                "title": "Asset Code", "data": "Asset_ID", "name": "Asset_ID", "visible": true, "searchable": true, "sortable": true, "class": "text-left-align",
                "render": function (data, type, full, meta) {
                    var oemkeycontrol = '<input type="hidden" name="OEM_Key" id="hdnOEM_Key" value="' + full.OEM_Key + '" />';
                    var assetidcontrol = '<input type="hidden" name="Asset_ID" id="hdnAsset_ID" value="' + data + '" />';
                    var companycodecontrol = '<input type="hidden" name="CompanyCode" id="hdnCompanyCode" value="' + full.CompanyCode + '" />';
                    var notreportingreasontypecontrol = '<input type="hidden" name="NotReportingReasonType" value="' + full.NotReportingReasonType + '" />';
                    var assetoverviewcontrol = full.IsForAssetOverview == "Y" ? '<a title="Click to view Asset Overview" style="cursor: pointer;font-size: 14px;font-weight: bold;color:#3884c7 !important" data_toggle="tooltip" id="' + data
                                                                   + '" onclick=moveToAssetOverviewFromNotReporting("' + data + '","' + full.CompanyCode + '","' + full.OEM_Key + '","' + full.NotReportingReasonType + '")>' + data + '</a>'
                                                                   : '<a title="EMS Asset" data_toggle="tooltip" id="' + data + '" class="disabled">' + data + '</a>';
                    return oemkeycontrol + assetidcontrol + companycodecontrol + notreportingreasontypecontrol + assetoverviewcontrol;
                }
            },
            {
                "title": "Asset Description", "data": "Asset_Name", "name": "Asset_Name", "visible": true, "searchable": true, "sortable": true, "class": "text-left-align"
            },
            {
                "title": "IC", "data": "ICShortCode", "name": "ICShortCode", "visible": true, "searchable": true, "sortable": true, "class": "text-center"
            },
            {
                "title": "Job Code", "data": "Job_Code", "name": "Job_Code", "visible": true, "searchable": true, "sortable": true, "class": "text-left-align"
            },
            {
                "title": "Job Description", "data": "Job_Desc", "name": "Job_Desc", "visible": true, "searchable": true, "sortable": true, "class": "text-left-align"
            },
            {
                "title": "Last Reported Time", "data": "Date", "name": "Date", "visible": true, "searchable": true, "sortable": true, "class": "text-left-align"
            },
            {
                "title": "Days Not Reported", "data": "NotReportingAge", "name": "NotReportingAge", "visible": true, "searchable": true, "sortable": true, "class": "text-center",
                "render": function (data, type, full, meta) {
                    if (data != null) {
                        var notreportingagecontrol = '<a title="Click to view History" style="cursor: pointer;font-size: 14px;font-weight: bold;color:#3884c7 !important" data_toggle="tooltip" ' +
                        'id="ancNotReportingAge" onclick="displayNotReportingReasonHistoryPopUp(\'' + full.Asset_ID + '\',\'' + full.Asset_Name + '\',\'' + full.CompanyCode + '\',\'' + full.OEM_Key + '\');">' + data + '</a>';
                        return notreportingagecontrol;
                    }
                }
            },
            {
                "title": "Days Not Reported with Current Reason", "data": "CurrentNotReportingReasonAge", "name": "CurrentNotReportingReasonAge", "visible": true, "searchable": true, "sortable": true, "class": "text-center"
            },
            {
                "title": "Reason", "data": "_ReasonKey", "name": "_ReasonKey", "visible": true, "searchable": false, "sortable": false, "className": "noExport",
                "render": function (data, type, full, meta) {
                    var $select = $("<select class = 'form-control', style = 'font-size:11px;width: 150px;'></select>", { "id": "drpReason", "value": data });
                    var $defaultoption = $("<option></option>", { "text": "--Select--", "value": "" });
                    $select.append($defaultoption);
                    $.each(full.NotReportingReason, function (k, v) {
                        var $option = $("<option></option>", { "text": v.Text, "value": v.Value });
                        if (data == v.Value) { $option.attr("selected", "selected") }
                        $select.append($option);
                    });
                    return $select.prop("outerHTML");
                }
            },
            {
                "title": "_Reason", "data": "_Reason", "name": "_Reason", "visible": false, "searchable": true, "sortable": false, "class": "text-left-align"
            },
            {
                "title": "Reason Created By", "data": "ReasonCreatedBy", "name": "ReasonCreatedBy", "visible": true, "searchable": true, "sortable": true, "class": "text-left-align"
            },
            {
                "title": "Reason Updated By", "data": "ReasonUpdatedBy", "name": "ReasonUpdatedBy", "visible": true, "searchable": true, "sortable": true, "class": "text-left-align"
            },
            {
                "title": "Remarks", "data": "Remarks", "name": "Remark", "visible": true, "searchable": true, "sortable": true, "data-orderable": false, "class": "text-center",
                "render": function (data, type, full, meta) {
                    var remarkcontrol = '<textarea id="txtRemarks" class="form-control" style="font-size:11px;width: 150px;" title="' + full.RemarkEnteredOnDate + '">' + data + '</textarea>';
                    return remarkcontrol;
                }
            },
            //{
            //    "data": "Remarks", "name": "Remarks", "visible": false, "searchable": false, "sortable": false, "class": "text-left-align"
            //},
            {
                "title": "Reason & Remark History", "data": "", "name": "Reason&RemarkHistory", "visible": true, "searchable": false, "sortable": false, "data-orderable":false, "class": "text-center noExport",
                "render": function (data, type, full, meta) {
                    if (full._ReasonKey && full._ReasonKey != -1) {
                        return '<a class="btn btn-xs mybtn-info cursorpointer display-mode" onclick="displayNrReasonAndRemarkHistoryPopUp(\'' + full.Asset_ID + '\',\'' + full.Asset_Name + '\',\'' + full.CompanyCode + '\',\'' + full.OEM_Key + '\')" '
                               + 'data-title="Click to view Reason & Remarks History" title="Click to view Reason & Remarks History" data-toggle="tooltip">'
                               + '<i class="fa fa-history" title="Click to view Reason & Remarks History" style="padding:5px; font-size:17px;"></i></a>';
                    } else {
                        return '<a class="btn btn-xs mybtn-info cursorpointer display-mode" title="No Reason & Remarks History Available" data-toggle="tooltip" disabled>'
                               + '<i class="fa fa-history" title="No Reason & Remarks History Available" style="padding:5px; font-size:17px;"></i></a>';
                    }
                }
            },
            {
                "title": "Source/OEM Provider", "data": "OEM_Provider", "name": "OEM_Provider", "visible": true, "searchable": true, "sortable": true, "class": "text-center"
            },
            {
                "title": "Location Details", "data": "", "searchable": false, "sortable": false, "class": "text-center noExport",
                "render": function (data, type, full, meta) {
                    return '<a class="cursorpointer mapmarkercolor dialog" id="btnMap" onclick="getAssetMap(this,\'' + full.Asset_ID + '\',\'' + full.Asset_Name + '\',\'' + full.CompanyCode + '\',\'' + full.OEM_Key + '\',\'Last\')" '
                            + 'data-toggle="tooltip" title="Last known location" name="' + full.Asset_Name + '" style="font-size:2.5em;color:deepskyblue;"> <span class="icon-Map-Marker"></span></a>';
                }
            }
        ],
        "columnDefs": [
                        {
                            "targets": 5,
                            render: function (data) {
                                if (data != null)
                                    return moment(data).format('DD-MMM-YYYY HH:mm:ss A');
                                else
                                    return '';
                            }
                        }
        ],           
        "fnDrawCallback": function (oSettings) {               
        },
        "initComplete": function (settings, json) {                
        }
    });

    //Function to alert the user to save information on navigating to the next page through Pagination
    oTable.on('page.dt', function (e, oSettings) {
        e.preventDefault();
        var selectedReasonKeyArr = [];
        notReportingPaginationArr.length = 0;
        //Getting the current page visible rows (10 rows/20 rows/50 rows/100 rows - default is 10 rows)
        var rows = $("#tblnotreportingdetails tbody tr");
        for (var index = 0; index < rows.length; index++) {
            //Getting each row
            var singleRow = $(rows[index]);
            //Get the Reason Dropdown selected value
            var selectedAssetId = singleRow.find("#hdnAsset_ID").val();
            var selectedCompanyCode = singleRow.find("#hdnCompanyCode").val();
            var selectedOemKey = singleRow.find("#hdnOEM_Key").val();
            var selectedReasonKey = singleRow.find(":selected").val();
            var selectedReasonText = singleRow.find(":selected").text();
            var selectedRemarkText = singleRow.find("#txtRemarks").text();
            var data = oTable.api().row(singleRow).data();
            var existingReasonText = $.trim(data["_Reason"]);
            //If the selected value is not empty (is empty only when the text is "--Select--")
            if (selectedReasonKey != "") {
                existingReasonText = decodeEntities(existingReasonText);
                if (selectedReasonText != existingReasonText) {  //Add to the Array
                    //alert("existingReasonText : " + existingReasonText + "selectedReasonText : " + selectedReasonText);
                    selectedReasonKeyArr.push(selectedReasonKey);
                    notReportingPaginationArr.push(
                        {
                            "Asset_ID": selectedAssetId,
                            "CompanyCode": selectedCompanyCode,
                            "OEM_Key": selectedOemKey,
                            "NewReasonKey": selectedReasonKey,
                            "NewReasonText": selectedReasonText,
                            "NewRemarkText": selectedRemarkText
                        });
                }
            }
        }

        //Check if the Array length is more than 0 then display message
        if (selectedReasonKeyArr.length > 0) {
            // alert("Please save unsaved Data before Navigating to the next Page.");
            var existingErrMessage = $('#divNrpErrorMessage').text();
            if (existingErrMessage.indexOf("Please save unsaved Data before Navigating to the next Page.") == -1) {
                var newErrorMessage = existingErrMessage + " Please save unsaved Data before Navigating to the next Page.";
                $('#divNrpErrorMessage').text(newErrorMessage);
            }
            debugger;
            var p = oTable.api().page.info();
            prestart = p.start > 6 ? (p.start - p.length) : p.start;
            oTable.api().draw(false);

            //var data = oTable.row(rows[0]).data();
            //Finding the first row of the selected page and staying on the same page by using the below extention method
            //oTable.fnGetPageOfRow(rows[0]);
            //oTable.row(rows[0]).data(data).draw(false);
            //var p = oTable.api().page.info();
            //oTable.fnClearTable();
            //for (var i = 0; i < rows.length; i++) {
            //    oTable.fnAddData($(rows[i]));
            //}
            //oTable.page(p.page).draw('page');

            //oTable.ajax.reload(null, false);

            //oTable.draw(false);

            //oTable.fnPageChange(0, true);

            //oTable.settings()[0].oFeatures.bServerSide = false;
            //oTable.settings()[0].ajax = false;
        }
        else {
            $('#divNrpErrorMessage').text('');
            $('#divNrpSuccessMessage').text('');
        }
    });            
});

But server side, how to do ?

Please help.

Chandan Kumar
  • 4,570
  • 4
  • 42
  • 62

1 Answers1

0

You need to cancel the execution on your beforeSend method using xhr.abort();

You should do something like this.

 "ajax": {
        "url": "@Url.Action("LoadNotReportingDataTable", "Home")",
        "type": "POST",
        "datatype": "json",
        "headers": headers,
        "beforeSend": function (xhr, opts) {
            //debugger;
            //if any changes available in the current  page(reason/remark) tnen get the current page number and assign to the global variable
            if (notReportingPaginationArr.length > 0) {
                prepaginationval = $('#tblnotreportingdetails_wrapper').find('.dataTables_paginate').find('ul.pagination').find('li.active a').attr("data-dt-idx"); 
                xhr.abort(); //<------ This will prevent to call your API
                var rows = $("#tblnotreportingdetails tbody tr");
                oTable.fnGetPageOfRow(rows[0]);//<-- this hack will undo the page number highlight.
            }
        },
        "data": function (d) {
            d.nrp = JSON.stringify(notReportingPaginationArr);
            d.prestart = prestart;
            return d;
        },
    },

The answer below cold help you. Stop $.ajax on beforeSend

Lutti Coelho
  • 2,134
  • 15
  • 31