2

We are using jquery grid 4.6. We want to set a select box for filter toolbar. The select box should have columns unique name, this has already been answered and the solution could be found at: https://jsfiddle.net/4k0xgxok/

How ever when we change the data from local to url the search box will not appear at all. I tried to make a simple sample which only change the searchoptions:value to some thing hard coded, but it does not work. https://jsfiddle.net/xdbw5hmy/

The code is

    var getUniqueNames = function(columnName) {
      var texts = $("#jqGrid").jqGrid('getCol', columnName),
        uniqueTexts = [],
        textsLength = texts.length,
        text, textsMap = {},
        i;
      for (i = 0; i < textsLength; i++) {
        text = texts[i];
        if (text !== undefined && textsMap[text] === undefined) {
          // to test whether the texts is unique we place it in the map.
          textsMap[text] = true;
          uniqueTexts.push(text);
        }
      }
      return uniqueTexts;
    };
    var  buildSearchSelect = function(uniqueNames) {
        var values=":All";
        $.each (uniqueNames, function() {
            values += ";" + this + ":" + this;
        });
        console.log(values);
        return values;
    };
    var mydata = [{
      "OrderId": "1",
      "CategoryName": "Beverages",
      "ProductName": "Steeleye Stout"
    }, {
      "OrderId": "2",
      "CategoryName": "Beverages",
      "ProductName": "Laughing Lumberjack Lager"
    }];
    $("#jqGrid").jqGrid({
      datatype: 'local',
      data: mydata,
      colModel: [{
        label: 'OrderID',
        name: 'OrderID',
        key: true,
        width: 75
      }, {
        label: 'ProductName',
        name: 'ProductName',
        width: 150
      }, {
        label: 'CategoryName',
        name: 'CategoryName',
        width: 150
      }],
      gridComplete: function() {
        $('#jqGrid').jqGrid("setColProp", "ProductName", {
          stype: "select",
          align: "center",
          searchoptions: {
            value: buildSearchSelect(getUniqueNames("ProductName")),
          }
        });
      },
      viewrecords: true,
      height: 250,
      rowNum: 20,
    });
    $('#jqGrid').jqGrid('filterToolbar');
  });
Alireza Fattahi
  • 42,517
  • 14
  • 123
  • 173
  • You wrote "we change the data from local to url". It seems be incorrect. You mean probably that you change `datatype: "local", data: mydata` to `datatype: "json", url: "someUrl", loadonce: true`. Is it so? – Oleg Oct 23 '16 at 11:34

1 Answers1

2

The main problem in your code: the usage of gridComplete to set the column properties and the usage of getCol inside of getUniqueNames. The method getCol uses only the data from the current page, but you should take in consideration all data returned from the server. The second problem: you should set searchoptions.value only once after loading the data from the server. On the other side gridComplete will be called after every paging, sorting and so on. Finally it's very important to call filterToolbar after the new settings searchoptions.value are already set. The code from your demo https://jsfiddle.net/xdbw5hmy/ will first create the filter toolbar, before and data are loaded from the server and before searchoptions.value is set.

What you should do is the usage of beforeProcessing callback instead of gridComplete. The callback beforeProcessing get full data returned from the server as the parameter. One can scan the data and to call setColProp to modify searchoptions.value. After that one can create the filter toolbar by calling of filterToolbar. You will get the code like below

var getUniqueNames = function(columnName, mydata) {
        var texts = $.map(mydata, function(item) {
            return item[columnName];
        }),
            uniqueTexts = [],
            textsLength = texts.length,
            text, textsMap = {},
            i;
        for (i = 0; i < textsLength; i++) {
            text = texts[i];
            if (text !== undefined && textsMap[text] === undefined) {
                // to test whether the texts is unique we place it in the map.
                textsMap[text] = true;
                uniqueTexts.push(text);
            }
        }
        return uniqueTexts;
    },
    buildSearchSelect = function(uniqueNames) {
        var values = "";
        $.each(uniqueNames, function() {
            values += this + ":" + this + ";";
        });
        values = values.slice(0, -1);
        return values;
    },
    setSearchSelect = function(columnName, data) {
        $(this).jqGrid("setColProp", columnName, {
            stype: "select",
            align: "center",
            searchoptions: {
                value: buildSearchSelect(getUniqueNames.call(this, columnName, data)),
                sopt: ["eq", "ne"]
            }
        });
    },
    myDefaultSearch = "cn";

$("#jqGrid").jqGrid({
    url: 'https://api.myjson.com/bins/42mdc',
    datatype: 'json',
    colModel: [
        { name: 'OrderID', key: true, width: 75 },
        { name: 'ProductName' },
        { name: 'CategoryName' }
    ],
    beforeProcessing: function (data) {
        // !!! it will be called only after loading from the server
        // datatype is always "json" here
        setSearchSelect.call(this, "ProductName", data.rows);

        if (this.ftoolbar === true) {
            // if the filter toolbar already exist: we have to recreate it
            $(this).jqGrid('destroyFilterToolbar');
        }
        $(this).jqGrid("filterToolbar", {
            stringResult: true,
            defaultSearch: myDefaultSearch
        });
    },
    viewrecords: true,
    height: "auto",
    autoencode: true,
    rowNum: 20,
    loadonce: true
});

See the modified demo https://jsfiddle.net/OlegKi/xdbw5hmy/1/

By the way, I recommend you co consider to use select2 instead of the standard <select>. It's much more comfortable for the user if one has many items of data because select2 has integrated search input field and the selected data will be reduced during the user types the text. Look at the demos from the answer, this one. I recommend you additionally to read the answer, which demonstrates beforeProcessing.

Community
  • 1
  • 1
Oleg
  • 220,925
  • 34
  • 403
  • 798