0

Please note that I have tried almost all the solutions I could find on various questions already available on Stack Overflow but no solution has worked for me.

So please do not mark this as duplicate or down vote. Kindly assist with the situation given below:

I have a JQGrid which initially loads all the data from some table (SQL Db). There is an option to filter the data by selecting the values from drop down list. Changing the drop down list triggers an ajax call to the server which returns filtered data from the server (MVC Controller). However, when the data is returned from the Controller, the data is correct but it is not reflecting in the JQGrid. I have tried all different methods for triggering the reload of JQGrid but nothing works.

Razor View/JQuery code:

@model IEnumerable<OSMPortalV2.Models.NetworkCertsATC_SP>

<!-- widget content -->
<div class="widget-body fuelux">
    <form name="networkCertficates">
        <!-- widget div-->
        @{
            List<SelectListItem> ddlistItems = new List<SelectListItem>();
            ddlistItems.Add(new SelectListItem { Text = "All Certificates", Value = "All", Selected = true });
            ddlistItems.Add(new SelectListItem { Text = "1 Day", Value = "1Day" });
            ddlistItems.Add(new SelectListItem { Text = "5 Days", Value = "5Days" });
            ddlistItems.Add(new SelectListItem { Text = "15 Days", Value = "15Days" });
            ddlistItems.Add(new SelectListItem { Text = "30 Days", Value = "30Days" });
        }
        <div style="padding-bottom: 10px;">
            Show certificates expiring in:  @Html.DropDownList("ddlTimeFrame", new SelectList(ddlistItems, "Value", "Text"))
            @*<button type="submit" class="btn btn-sm btn-primary btn-prev" id="btnPrev">
                <i class="fa fa-refresh"></i> Reload Grid
            </button>*@
        </div>
    </form>
    <div style="width: 100%; overflow: auto;">
        <table id="jqgrid"></table>
        <div id="pjqgrid"></div>
    </div>
    <br>
</div>
<!-- end widget content -->

<!-- Style for Grid data load -->
<style type="text/css">
    .ui-jqgrid .loading {
        background-image: url("../../Content/img/ajax-loader.gif");
        border: 2px solid #706457;
        background-repeat: no-repeat;
        background-color: ghostwhite;
        border-radius: 10px;
        top: 20%;
        min-height: 102px; 
        min-width: 102px;
    }
</style>

<script src="~/Scripts/libs/jquery-2.1.1.min.js"></script>
<script type="text/javascript">
    // DO NOT REMOVE : GLOBAL FUNCTIONS!
    /* Function to Get Profile Count */
    $(document).ready(function () {
        // Fronend UI Script
        pageSetUp();

        /* Function to Get Environment Details */
        function GetEnvironment(ipAddress) {
        }

        var timeRange;
        // Trigger reload Dropdown selection change event
        $("#ddlTimeFrame").change(function () {
            timeRange = $("#ddlTimeFrame option:selected").val();
            // Callback operation to load filtered data 
            $.ajax({
                type: 'GET',
                contentType: "application/json",
                url: '/Network/GetCertDetails',
                data: {timeframe: timeRange},
                success: function (returnedData) {
                    // This returns correct data but JQ Grid is not updated.
                    jQuery("#jqGrid").setGridParam({ datatype: 'json', data: returnedData }).trigger('reloadGrid');
                    var gridData = jQuery("#jqgrid").jqGrid('getRowData');
                    alert(gridData);
                }
            });
        });

        Date.prototype.addDays = function (days) {
            this.setDate(this.getDate() + parseInt(days));
            return this;
        };

        $.jgrid.defaults.loadtext = '';

        jQuery("#jqgrid").jqGrid({
            url: '/Network/GetCertDetails',
            postData: {
                timeframe: function () { return $("#ddlTimeFrame option:selected").val(); }
            },
            mtype: 'GET',
            datatype: 'json',
            height: 'auto',
            colNames: ['Common Name', 'Certificate', 'Device', 'Expiry Date',
                'Profile', 'Virtual', 'Partition', 'Pool',
                'VIP', 'Virtual Port', 'Member Name', 'Member IP Address',
                'Member Port', 'Environment', 'ATC Name', 'ATC Email ID'],
            colModel: [
                { name: 'Common_Name', index: 'Common_Name', sortable: true, width: 200 },
                { name: 'Certificate', index: 'Certificate', sortable: true, width: 250 },
                { name: 'Device', index: 'Device', sortable: true },
                { name: 'Expiry_Date', index: 'Expiry_Date', formatter: 'date', formatoptions: { srcformat: 'd/m/Y', newformat: 'd/m/Y' }, sortable: true, align: "center"},
                { name: 'Profile', index: 'Profile', align: "left" },
                { name: 'Virtual', index: 'Virtual', align: "left" },
                { name: 'Partition', index: 'Partition', align: "left" },
                { name: 'Pool', index: 'Pool', align: "left" },
                { name: 'VIP', index: 'VIP', align: "left" },
                { name: 'Virtual_Port', index: 'Virtual_Port', align: "center", width: 90 },
                { name: 'Member_Name', index: 'Member_Name', align: "left" },
                { name: 'MemberIPAddress', index: 'MemberIPAddress', align: "left" },
                { name: 'Member_Port', index: 'Member_Port', align: "center", width: 90 },
                {
                    name: 'MemberIPAddress', index: 'Environment', sortable: true, align: "left", formatter: function (cellvalue, options, rowObject) {
                        var IPAddress = cellvalue;
                        return GetEnvironment(IPAddress);
                    }
                },                { name: 'ATCName', index: 'ATCName', align: "left" },
                { name: 'ATCEmail', index: 'ATCEmail', align: "left", width: 200 }
            ],
            ajaxGridOptions: { cache: false },
            autoencode: true,
            autowidth: true,
            beforeRefresh: function () {
                grid.jqGrid('setGridParam', { datatype: 'json' }).trigger('reloadGrid');
            },
            caption: "Certificate Details",
            emptyrecords: "No records to view",
            gridview: true,
            hoverrows: true,
            ajaxGridOptions: { cache: false },
            loadonce: true,
            loadui: 'block',
            multiboxonly: true,
            multiselect: true,
            pager: '#pjqgrid',
            rowList: [15, 20, 30, 50],
            rowNum: 15,
            rownumbers: true,
            sortname: 'srno',
            sortorder: "asc",
            toolbarfilter: true,
            viewrecords: true
        });

        // Add Filter on top of the column
        jQuery("#jqgrid").jqGrid('filterToolbar', { stringResult: true, searchOnEnter: false, defaultSearch: "cn" });
        // Adding pagination
        jQuery("#jqgrid").jqGrid('navGrid', "#pjqgrid", {
            edit: false,
            add: false,
            del: false,
            reloadGridOptions: { fromServer: true },
            refreshstate: "current"
        });
    });

    $(window).on('resize.jqGrid', function () {
        $("#jqgrid").jqGrid('setGridWidth', $("#content").width());
    });
</script>

MVC Controller code:

public ActionResult GetCertDetails(string timeframe, string ddlTimeFrame)
{
    using (NetworkAutomationContext NAC = new NetworkAutomationContext())
    {
        List<NetworkCertsATC_SP> results = new List<NetworkCertsATC_SP>();
        try
        {
            if (timeframe != null)
                ViewData["TimeFrame"] = timeframe;
            else
                ViewData["TimeFrame"] = "All";

            // Fetch Grid data filtered according to time frame
            DateTime ExpiryDate = DateTime.Now.Date;
            switch (timeframe)
            {
                case "All":
                    results = NAC.NetworkCMDB_Certss.ToList();
                    break;
                case "1Day":
                    ExpiryDate = ExpiryDate.AddDays(1);
                    results = NAC.NetworkCMDB_Certss.Where(record => record.Expiry_Date < ExpiryDate).ToList();
                    break;
                case "5Days":
                    ExpiryDate = ExpiryDate.AddDays(5);
                    results = NAC.NetworkCMDB_Certss.Where(record => record.Expiry_Date < ExpiryDate).ToList();
                    break;
                case "15Days":
                    ExpiryDate = ExpiryDate.AddDays(15);
                    results = NAC.NetworkCMDB_Certss.Where(record => record.Expiry_Date < ExpiryDate).ToList();
                    break;
                case "30Days":
                    ExpiryDate = ExpiryDate.AddDays(30);
                    results = NAC.NetworkCMDB_Certss.Where(record => record.Expiry_Date < ExpiryDate).ToList();
                    break;
                default:
                    results = NAC.NetworkCMDB_Certss.ToList();
                    break;
            }
        }
        catch (Exception ex)
        {
            var ErrorObject = new NetworkCertsATC_SP
            {
                Common_Name = "Error",
                Certificate = ex.Message,
                Device = "NA",
                Expiry_Date = DateTime.Now.Date,
                Profile = "NA",
                Virtual = "NA",
                Partition = "NA",
                Pool = "NA",
                VIP = "NA",
                Virtual_Port = 0,
                Member_Name = "NA",
                MemberIPAddress = "NA",
                Member_Port = 0,
                ATCEmail = "NA",
                ATCName = "NA",
                EnvironmentType = "NA"
            };
            results.Add(ErrorObject);
        }
        return Json(results, JsonRequestBehavior.AllowGet);
    }
}

EDIT 1: Added screen-shot of the new data successfully received from the Controller but not updated in the jqGrid. enter image description here

EDIT 2: Updated code as suggested by @Oleg. But still facing the same issue. MVC Controller is not called this time. Also, the second break point in JQuery is also not hit: Updated code as suggested by @Oleg

EDIT 3: Screen-shot of the next error after updating the code. p = $grid.jqGrid("getGridParam"); is undefined.

SavindraSingh
  • 878
  • 13
  • 39

1 Answers1

1

If I correctly understand your problem, you should change the code of $("#ddlTimeFrame").change(...). You don't need to make $.ajax yourself. Inside of change event handler you need just call

jQuery("#jqGrid").trigger("reloadGrid", { fromServer: true });

if you use free jqGrid fork or to use

var $grid = jQuery("#jqGrid");
var p = $grid.jqGrid("getGridParam");

p.datatype = "json";
$grid.trigger("reloadGrid");

in case of using old version of jqGrid or commercial Guriddo jqGrid.

By the way. The code of beforeRefresh callback, which you use currently seems be wrong. If you use free jqGrid fork then you can remove it. If you use other jqGrid, then you should remove .trigger('reloadGrid') because jqGrid reloads grid itself after calling beforeRefresh callback. Additionally, grid variable seems be undefined. The fixed code could look like the following

beforeRefresh: function () {
    var p = $(this).jqGrid("getGridParam"); // get reference to internal parameters
    p.datatype = "json";
}

UPDATED: Be carefully in usage the case of ids: you used low case in HTML: <table id="jqgrid"></table> and the correct case during creating the grid (see jQuery("#jqgrid").jqGrid({...});). On the other side the code of change event handler (see $("#ddlTimeFrame").change(...);) uses wrong case of id (see jQuery("#jqGrid") instead of jQuery("#jqgrid")). It could be the origin of your problem.

Oleg
  • 220,925
  • 34
  • 403
  • 798
  • The reason I am using `$.ajax()` is to load the details from the server side again based on the value selected from the drop down. Not sure how grid will load NEW data from server without making the ajax call. Also, I have used this code which came with an admin template I purchased online, not sure how to check the version of jqGrid. – SavindraSingh Apr 04 '19 at 03:41
  • @SavindraSingh: Your current code uses `postData` with `timeframe` defined as function. The function will be called every time if jqGrid makes request to `url`. I described the approach in [the old answer](https://stackoverflow.com/a/2928819/315935). Thus it's enough to reset `datatype` to initial value (`"json"`) and trigger `reloadGrid` to load the data from the server using the current selected value of the the dropdown. Do you tried the changes, which I described in my answer? – Oleg Apr 04 '19 at 06:52
  • I have tried the code suggested by you. Updated the `grid` variable and also removed the `$.ajax` call. I have put a break point in the controller to check if jqGrid reload hits correct `case` in `switch` statement in controller but it is not even hitting the controller. Can you please suggest what is going wrong. – SavindraSingh Apr 04 '19 at 08:26
  • @SavindraSingh: First of all you still don't wrote **which version of jqGrid you use and from which fork of jqGrid**. Seconds, you posted screenshot with your **old code without modifications, which i suggested**. I suggested to **remove** `$.ajax` call from `$("#ddlTimeFrame").change(function () {/*here should be included NEW code*/});`. You need replace the code to either `jQuery("#jqGrid").trigger("reloadGrid", { fromServer: true });` (if you use free jqGrid) or `var $grid = jQuery("#jqGrid"), p = $grid.jqGrid("getGridParam"); p.datatype = "json";$grid.trigger("reloadGrid");` – Oleg Apr 04 '19 at 08:57
  • @SavindraSingh: You can include breakpoint inside of the function `timeframe: function () { return $("#ddlTimeFrame option:selected").val(); }` to see that new selected value will be sent to the server after `.trigger("reloadGrid")` if `datatype` is `"json"`. – Oleg Apr 04 '19 at 08:59
  • The screen-shot I pasted here is before I tried your code, to show that the server is returning correct data but it is not reflecting in the jqGrid. However, as mentioned earlier I don't know how to find the jqGrid version since I am using a template I purchased online (how to check this?). For your second comment, it hits the `timeframe: function()..` only during first load. Nothing related to `reloadGrid` coming into picture. – SavindraSingh Apr 04 '19 at 09:53
  • @SavindraSingh: The whole (or almost the whole) code of jqGrid is inside one file: `jquery.jqgrid.min.js` or `jquery.jqgrid.src.js`. If you open the file you will see the version in the comment at the start of the file. If you what that I help you to find the error in your code, you should post the corresponding code fragment of your *current* code. Additionally you should describe the test case, which you use. For example, you change selected option in the select `#ddlTimeFrame`, verify that `.change` event handler be called and the function `postData.timeframe` be called too. – Oleg Apr 04 '19 at 11:05
  • In the entire file `jquery.jqGrid.min.js` i can find only one entry for the work `version` which is `b.extend(b.jgrid, { "version": "4.5.3", ....`. – SavindraSingh Apr 05 '19 at 06:33
  • it has been over 15 days now I am still trying to find solution for this issue. I found only you are to one who is providing solution to jqGrid related issues all over the internet. Please assist me further. I have already tried the solutions you have suggested and added the screen-shot above. Please let me know if you need any other details to assist me further. – SavindraSingh Apr 09 '19 at 08:35
  • @SavindraSingh: You should post comment if you modify the text of your question. I don't seen "EDIT 2" part after I read your previous comment. I wrote in my answer that you should use `jQuery("#jqGrid").trigger("reloadGrid", { fromServer: true });` **only if you use free jqGrid fork**, which I develop. You wrote that you use retro version 4.5.3, which is about 6 years old (why don't upgrade from https://github.com/free-jqgrid/jqGrid, https://www.nuget.org/packages/free-jqGrid/ or https://www.npmjs.com/package/free-jqgrid). – Oleg Apr 09 '19 at 09:06
  • @SavindraSingh: If you **really required** to use old version 4.5.3 then you should use code fragment (see my answer and my previous comments): you need replace `jQuery("#jqGrid").trigger("reloadGrid", { fromServer: true });` to `var $grid = jQuery("#jqGrid"), p = $grid.jqGrid("getGridParam"); p.datatype = "json";$grid.trigger("reloadGrid");` – Oleg Apr 09 '19 at 09:07
  • I have tried this code. But, I am getting error `Uncaught TypeError: Cannot set property 'datatype' of undefined`. Please check attached screen-shot in EDIT-3 in question and suggest. BTW, I am going to update the jqGrid using free-jqgrid from nuget.org. Just to see if that can help. – SavindraSingh Apr 10 '19 at 06:34
  • @SavindraSingh: It's probably because you use `` with low case `id="jqgrid"`, and use correct case during creating the grid (see `jQuery("#jqgrid").jqGrid({...})`), but you use **wrong** (wrong case) id inside of `change` handler: `jQuery("#jqGrid")` instead of `jQuery("#jqgrid")`.
    – Oleg Apr 10 '19 at 06:40
  • Bingo!! Thanks a lot @Oleg. Hats off for the perfect solution. Now it is working as expected. You saved me. Thanks again. – SavindraSingh Apr 10 '19 at 08:08