1

Using jqgrid free latest version 4.15.2 I am trying to make cascading drop down from db.

I tried the sample as posted by @Oleg jqgrid incorrect select drop down option values in edit box

But this is for older version of jqgrid and does not work fully while using latest version of jqgrid.

var countries = { "UsId": "US", "UkId": "UK" },
            statesOfUS = { "AlabamaId": "Alabama", "CaliforniaId": "California", "FloridaId": "Florida", "HawaiiId": "Hawaii" },
            statesOfUK = { "LondonId": "London", "OxfordId": "Oxford" },
            states = $.extend({}, statesOfUS, statesOfUK),
            allCountries = $.extend({"": "All"}, countries),
            allStates = $.extend({"": "All"}, states),
            // the next maps provide the states by ids to the contries
            statesOfCountry = {
                "": states,
                "UsId": statesOfUS,
                "UkId": statesOfUK
            },

The entire code can be seen in fiddle below

https://jsfiddle.net/svnL4Lsv/

The issue is during the add form the second dropwdown shows all states instead of showing as per country Secondly during the edit the second dropdown again shows all states and not as per the row value

Its just when I change the first dropdown does the second dropdown filters and works.

----------Updated

  editoptions: {
       // value: countries,
       dataInit: dataInitApp,
       dataEvents: dataEventsApp,
       dataUrl: '@Url.Action("GetData", "Home")',
       }

Controller code:

 public enum Countries
 {
    USA = 1,
    UK  = 2               
 }

  public enum State
  {
    Alabama  = 1,           
    Florida  = 2
    London = 3
  }

  public JsonResult GetData()
  {
    var type = typeof(Helpers.UsersEnum.Countries);
    var jsonData = Enum.GetNames(type)
            .Select(name => new
            {
                Id = (int)Enum.Parse(type, name),
                Name = name
            })
                .ToArray();

             return Json(jsonData);
         }

I call the above to populate my dropdown. Also below is the json that is returned back:

[0]: {Id=1, Name="USA"}
[1]: {Id=2, Name="UK"}


[0]: {Id=1, Name="Alabama  "}
[1]: {Id=2, Name="Florida"}
[2]: {Id=3, Name="London"}
aman
  • 4,198
  • 4
  • 24
  • 36

1 Answers1

1

In case of usage free jqGrid you can use a little simplified code

$(function () {
    "use strict";
    var countries = "usId:US;ukId:UK",
        allStates = "alabamaId:Alabama;californiaId:California;floridaId:Florida;hawaiiId:Hawaii;londonId:London;oxfordId:Oxford",
        // the next maps provide the states by ids to the countries
        statesOfCountry = {
            "": allStates,
            usId: "alabamaId:Alabama;californiaId:California;floridaId:Florida;hawaiiId:Hawaii",
            ukId: "londonId:London;oxfordId:Oxford"
        },
        mydata = [
            { id: "10", country: "usId", state: "alabamaId", name: "Louise Fletcher" },
            { id: "20", country: "usId", state: "floridaId", name: "Jim Morrison" },
            { id: "30", country: "ukId", state: "londonId",  name: "Sherlock Holmes" },
            { id: "40", country: "ukId", state: "oxfordId",  name: "Oscar Wilde" }
        ],
        $grid = $("#list"),
        changeStateSelect = function (countryId, countryElem) {
            // build "state" options based on the selected "country" value
            var $select, selectedValues,
                $countryElem = $(countryElem),
                isInSearchToolbar = $countryElem.parent().parent().parent().parent().hasClass("ui-search-table");

            // populate the subset of countries
            if (isInSearchToolbar) {
                // searching toolbar
                $select = $countryElem.closest("tr.ui-search-toolbar")
                        .find(">th.ui-th-column select#gs_list_state");
            } else if ($countryElem.is(".FormElement")) {
                // form editing
                $select = $countryElem.closest("form.FormGrid")
                        .find("select#state.FormElement");
            } else {
                // inline editing
                $select = $("select#" + $.jgrid.jqID($countryElem.closest("tr.jqgrow").attr("id")) + "_state");
            }

            if ($select.length > 0) {
                selectedValues = $select.val();
                if (isInSearchToolbar) {
                    $select.html("<option value=\"\">All</option>");
                } else {
                    $select.empty();
                }
                $.jgrid.fillSelectOptions($select[0], statesOfCountry[countryId], ":", ";", false, selectedValues);
            }
        },
        dataInitCountry = function (elem) {
            setTimeout(function () {
                $(elem).change();
            }, 0);
        },
        dataEventsCountry = [
            { type: "change", fn: function (e) { changeStateSelect($(e.target).val(), e.target); } },
            { type: "keyup", fn: function (e) { $(e.target).trigger("change"); } }
        ],
        cancelInlineEditingOfOtherRows = function (rowid) {
            var $self = $(this), savedRows = $self.jqGrid("getGridParam", "savedRow");
            if (savedRows.length > 0 && rowid !== savedRows[0].id) {
                $self.jqGrid("restoreRow", savedRows[0].id);
            }
        };

    $grid.jqGrid({
        data: mydata,
        datatype: "local",
        colNames: [ "Name", "Country", "State" ],
        colModel: [
            { name: "name", width: 180 },
            { name: "country", formatter: "select", stype: "select", edittype: "select",
                searchoptions: {
                    noFilterText: "Any",
                    dataInit: dataInitCountry,
                    dataEvents: dataEventsCountry
                },
                editoptions: {
                    value: countries,
                    dataInit: dataInitCountry,
                    dataEvents: dataEventsCountry
                }},
            { name: "state", formatter: "select", stype: "select", edittype: "select",
                editoptions: { value: allStates }, searchoptions: { noFilterText: "Any" } }
        ],
        cmTemplate: { width: 100, editable: true },
        onSelectRow: cancelInlineEditingOfOtherRows,
        ondblClickRow: function (rowid) {
            cancelInlineEditingOfOtherRows.call(this, rowid);
            $(this).jqGrid("editRow", rowid);
        },
        inlineEditing: {
            keys: true
        },
        formEditing: {
            onclickPgButtons: function (whichButton, $form, rowid) {
                var $self = $(this), $row = $($self.jqGrid("getGridRowById", rowid)), countryId;
                if (whichButton === "next") {
                    $row = $row.next();
                } else if (whichButton === "prev") {
                    $row = $row.prev();
                }
                if ($row.length > 0) {
                    countryId = $self.jqGrid("getCell", $row.attr("id"), "country");
                    changeStateSelect(countryId, $form.find("#country")[0]);
                }
            },
            closeOnEscape: true
        },
        searching: {
            searchOnEnter: true,
            defaultSearch: "cn"
        },
        navOptions: {
            del: false,
            search: false
        },
        iconSet: "fontAwesome",
        sortname: "name",
        sortorder: "desc",
        viewrecords: true,
        rownumbers: true,
        pager: true,
        pagerRightWidth: 85, // fix wrapping or right part of the pager
        caption: "Demonstrate dependent selects (inline editing on double-click)"
    })
    .jqGrid("navGrid")
    .jqGrid("filterToolbar");
});

see https://jsfiddle.net/OlegKi/svnL4Lsv/3/

Oleg
  • 220,925
  • 34
  • 403
  • 798
  • thanks for the update. This works fine. While the country and state values are hardcoded, I was looking to have them from my database. While I have managed to connect to my mvc controller making an ajax call to get dropdown values. I am not sure how to bind it back. I think its the values returned that are not correct as I am returning json from my controller. See my updated post. – aman Feb 14 '18 at 15:49
  • @aman: Filling dependent selects via Ajax request is absolutely another question. Moreover, the demo https://jsfiddle.net/OlegKi/svnL4Lsv/3/ like the old one demonstrates dependent selects in 1) filter toolbar, 2) inline editing, 3) form editing 4) navigation in form editing dialog (`onclickPgButtons` callback). – Oleg Feb 14 '18 at 19:18
  • @aman: The main idea for dependent selects via Ajax request is the same, but there are exist details in all 4 cases. In general you should make Ajax request to the server inside of `change` event handler of the first select (`country`), convert the response to the string in format `"value1:text1;value2:text2;...;valueN:textN"` and call `$.jgrid.fillSelectOptions` method with DOM of the second select (`state`) as the first parameter, `"value1:text1;value2:text2;...;valueN:textN"` as the second parameter and so on. – Oleg Feb 14 '18 at 19:19
  • @aman: `changeStateSelect` code could looks close. In general `$.jgrid.fillSelectOptions` supports object form of value too, but object form don't grantee the same order of options in different web browsers. Thus I recommend to use `"value1:text1;value2:text2;...;valueN:textN"` form. – Oleg Feb 14 '18 at 19:19
  • since it was related to the drop down I had asked. Shall I raise another ques for this. Thanks – aman Feb 14 '18 at 19:20
  • @aman: I have to do my main job. I can't spend so much time for stackoverflow. First of all you should try to implement the solution yourself based on my above advices. You can post new questions with your attempts if your would get some implementation problems. Moreover, today is Valentine's Day and I have other plans for today... – Oleg Feb 14 '18 at 19:25
  • Sorry not related to this but your example at https://jsfiddle.net/OlegKi/9f9exg91/ is not working. I am also having this issue. Whenever there is a dropdown the search is not working. – aman Feb 22 '18 at 18:50
  • 1
    @aman: jqGrid works corresponds to the options, which you use. If you type `FE`, for example, then you can search for `FedEx`. If you want to display `select` in searching dialog for some column, then you should specify `stype: "select"` and `searchoptions` with `value`. For example, `stype: "select", searchoptions: {sopt: ["eq", "ne"], value: "FE:FedEx;TN:TNT;DH:DHL", noFilterText: "Any" }`. See https://jsfiddle.net/OlegKi/9f9exg91/23/. Moreover the demo use free jqGrid 4.14.1. I recommend you to use always the last version (4.15.3 currently). – Oleg Feb 22 '18 at 19:01
  • Thanks Oleg. This works for me when the search type is a textbox instead of select. With select it doesnt works. May be because I am not using values to bind instead I am using BuildSelect to populate dropdown. I will see whats going on and will open a post if required. – aman Feb 22 '18 at 20:22