Reputation: 1561
I have a jqGrid that gets data from a database using AJAX (in MVC). The rows and columns are dynamic and change based on what a user chooses from a select list, above the jqGrid. Each column has a drop down list box to filter the rows.
All is working great: Data is returned, columns and search filters are dynamically built and the filter works. There is one issue though:
If I filter a column using its search filter drop-down, after the rows have been filtered, the drop-down filters in the other columns still contain the original options that are no longer relevant to the current result set - e.g.
In a column that I haven't filtered, I may have only the following countries in the filtered results:
but the Search filter for that column still contains all countries, even though they are no longer relevant to the user:
I want the options in any filter drop-down that has not had a filter applied to it to only contain those relevant to the result set - in this case: England, France, Italy.
Is this possible? I have tried setting recreateFilter: true in the searchoptions but it made no difference.
It's my first time working with jqGrid so I've cobbled lots of code together from the web, which I'll post here if it helps anyone answer my question. One thing to note, I am using jqGrid 4.3.2 as I can't get later version to work. Anyway, here's the code and thanks for reading!
grid = $("#list");
grid.jqGrid({
jsonReader: { repeatitems: true, root: "rows", page: "page", total: "total", records: "records" },
url: '@Url.Content("~/DocumentSearch/GetData?keywordSearch=")' + keywords + '&documentTypeId=' + documentTypeId,
datatype: 'json',
mtype: 'GET',
colModel: buildColumnModel(columns),
rowList: [5, 10, 20, 50],
viewrecords: true,
height: 'auto',
autowidth: true,
loadonce: true,
shrinktofit: true,
rowNum: 10000,
autoencode: true,
autowidth: true,
afterInsertRow: function (rowid, rowdata, rowelem) {
$(this).attr("data-toggle", "modal");
$(this).attr("data-target", ".bs-example-modal-sm");
},
beforeRequest: function () {
var separator = ',';
var i, l, rules, rule, parts, j, group, str, iCol, cmi, cm = this.p.colModel,
filters = $.parseJSON(this.p.postData.filters);
if (filters && typeof filters.rules !== 'undefined' && filters.rules.length > 0) {
rules = filters.rules;
for (i = 0; i < rules.length; i++) {
rule = rules[i];
iCol = getColumnIndexByName.call(this, rule.field);
cmi = cm[iCol];
if (iCol >= 0 && ((typeof (cmi.searchoptions) === "undefined" ||
typeof (cmi.searchoptions.sopt) === "undefined")
&& rule.op === myDefaultSearch) ||
(typeof (cmi.searchoptions) === "object" &&
$.isArray(cmi.searchoptions.sopt) &&
cmi.searchoptions.sopt[0] === rule.op)) {
// make modifications only for the 'contains' operation
parts = rule.data.split(separator);
if (parts.length > 1) {
if (typeof filters.groups === 'undefined') {
filters.groups = [];
}
group = {
groupOp: 'OR',
groups: [],
rules: []
};
filters.groups.push(group);
for (j = 0, l = parts.length; j < l; j++) {
str = parts[j];
if (str) {
// skip empty '', which exist in case of two separaters of once
group.rules.push({
data: parts[j],
op: rule.op,
field: rule.field
});
}
}
rules.splice(i, 1);
i--; // to skip i++
}
}
}
this.p.postData.filters = JSON.stringify(filters);
}
}
, loadComplete: function (data) {
var columnNamesArr = columns.split(',');
for (i = 0; i < columnNamesArr.length; i++) {
setSearchSelect(columnNamesArr[i]);
}
grid.jqGrid('filterToolbar', {
search: true, searchOnEnter: true, autosearch: true, defaultSearch: myDefaultSearch
});
if (data != null && data.records != null) {
$("#recordCount").text(data.records.toString());
}
grid.trigger("reloadGrid");
}
});
}
function buildColumnModel(columns) {
var uFields = columns.split(',');
var columns = [];
for (var i = 0; i < uFields.length; i++) {
if (uFields[i].indexOf('Id') > -1) {
columns.push({ name: uFields[i], index: uFields[i], hidden: true });
}
else {
columns.push({ name: uFields[i], index: uFields[i] });
}
}
return columns;
}
function setSearchSelect(columnName) {
grid.jqGrid('setColProp', columnName, {
stype: 'select',
searchoptions: {
sopt: ['eq', 'ne'],
multipleSearch: true,
multipleGroup: true,
recreateFilter: true,
closeOnEscape: true,
closeAfterSearch: true,
value: buildSearchSelect(getUniqueNames(columnName))
, attr: { multiple: 'multiple', size: 2 }
, dataInit: function (elem) {
setTimeout(function () {
$(elem).multiselect({
minWidth: 100,
height: "auto",
selectedList: 4,
checkAllText: "all",
uncheckAllText: "clear",
noneSelectedText: "All",
open: function () {
var $menu = $(".ui-multiselect-menu:visible");
$menu.width("auto");
return;
}
});
}, 50);
}
}
});
}
function buildSearchSelect(uniqueNames) {
var values = '';
$.each(uniqueNames, function () {
if (this.length > 0) {
values += this + ":" + this + ";";
}
});
if (values != null) {
values = values.substr(0, values.length - 1);
}
return values;
}
function getUniqueNames(columnName) {
var texts = grid.jqGrid('getCol', columnName);
var uniqueTexts = [];
var textsLength = texts.length;
var text;
var textsMap = {};
var 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);
}
}
uniqueTexts.sort();
return uniqueTexts;
}
Upvotes: 0
Views: 7336
Reputation: 61
here is a full working sample based on
http://stackoverflow.com/questions/5543902/change-filtertoolbar-options-dynamically
and the post above
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>http://stackoverflow.com/questions/5543902/change-filtertoolbar-options-dynamically</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!--link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/themes/redmond/jquery-ui.css" />
<link rel="stylesheet" type="text/css" href="http://www.ok-soft-gmbh.com/jqGrid/jquery.jqGrid-3.8.2/src/css/ui.jqgrid.css" /-->
<!--script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/jquery-ui.min.js"></script>
<script type="text/javascript" src="http://www.ok-soft-gmbh.com/jqGrid/jquery.jqGrid-3.8.2/js/i18n/grid.locale-en.js"></script>
<script type="text/javascript" src="http://www.ok-soft-gmbh.com/jqGrid/jquery.jqGrid-3.8.2/js/jquery.jqGrid.min.js"></script-->
<script type="text/javascript" src="./jqGrid/js/jquery.min.js"></script>
<script type="text/javascript" src="./jqGrid/js/jquery-ui.min.js"></script>
<!-- The Context Menu 3rd party plugin that we are using -->
<script type="text/javascript" src="./jqGrid/js/context-menu.js"></script>
<!-- This is the Javascript file of jqGrid -->
<script type="text/javascript" src="./jqGrid/js/trirand/jquery.jqGrid.min.js"></script>
<!-- This is the localization file of the grid controlling messages, labels, etc.-->
<!-- We support more than 40 localizations -->
<script type="text/javascript" src="./jqGrid/js/trirand/i18n/grid.locale-en.js"></script>
<!-- A link to a jQuery UI theme, more than 25 custom -->
<link rel="stylesheet" type="text/css" media="screen" href="./jqGrid/themes/overcast/jquery-ui.css" />
<!--link rel="stylesheet" type="text/css" media="screen" href="./jqGrid/jquery-ui-1.12.1.custom/jquery-ui.css" /-->
<!-- The link to the CSS that the grid needs -->
<link rel="stylesheet" type="text/css" media="screen" href="./jqGrid/css/trirand/ui.jqgrid.css?ver=030220181637" />
<script type="text/javascript" src="js/multiselect/multiselect.js"></script>
<script type="text/javascript">
//<![CDATA[
$(document).ready(function()
{
var mygrid = $("#list"),
pagerSelector = "#pager",
mydata = [
{id:"1",invdate:"2007-10-01",name:"abc",note:"note",amount:"200.00",tax:"10.00",total:"210.00"},
{id:"2",invdate:"2007-10-02",name:"test2",note:"note2",amount:"300.00",tax:"20.00",total:"320.00"},
{id:"3",invdate:"2007-09-01",name:"test3",note:"note3",amount:"400.00",tax:"30.00",total:"430.00"},
{id:"4",invdate:"2007-10-04",name:"def",note:"note",amount:"200.00",tax:"10.00",total:"210.00"},
{id:"5",invdate:"2007-10-05",name:"test2",note:"note2",amount:"300.00",tax:"20.00",total:"320.00"},
{id:"6",invdate:"2007-09-06",name:"test3",note:"note3",amount:"400.00",tax:"30.00",total:"430.00"},
{id:"7",invdate:"2007-10-04",name:"test",note:"note",amount:"200.00",tax:"10.00",total:"210.00"},
{id:"8",invdate:"2007-10-03",name:"test2",note:"note2",amount:"300.00",tax:"20.00",total:"320.00"},
{id:"9",invdate:"2007-09-01",name:"test3",note:"note3",amount:"400.00",tax:"30.00",total:"430.00"},
{id:"10",invdate:"2007-10-01",name:"test",note:"note",amount:"200.00",tax:"10.00",total:"210.00"},
{id:"11",invdate:"2007-10-02",name:"test2",note:"note2",amount:"300.00",tax:"20.00",total:"320.00"},
{id:"12",invdate:"2007-09-01",name:"test3",note:"note3",amount:"400.00",tax:"30.00",total:"430.00"},
{id:"13",invdate:"2007-10-04",name:"test",note:"note",amount:"200.00",tax:"10.00",total:"210.00"},
{id:"14",invdate:"2007-10-05",name:"test2",note:"note2",amount:"300.00",tax:"20.00",total:"320.00"},
{id:"15",invdate:"2007-09-06",name:"test3",note:"note3",amount:"400.00",tax:"30.00",total:"430.00"},
{id:"16",invdate:"2007-10-04",name:"xyz",note:"note",amount:"200.00",tax:"10.00",total:"210.00"},
{id:"17",invdate:"2007-10-03",name:"test2",note:"note2",amount:"300.00",tax:"20.00",total:"320.00"},
{id:"18",invdate:"2007-09-01",name:"test3",note:"note3",amount:"400.00",tax:"30.00",total:"430.00"}
];
columns = "id,invdate,name,amount,tax,total,note";
function getColumnIndexByName(mygrid, columnName)
{
var cm = $("#list").jqGrid('getGridParam', 'colModel');
for (var i = 0, l = cm.length; i < l; i++)
{
if (cm[i].name === columnName)
{
return i;
}
}
return -1;
};
$("#list").jqGrid({
datatype: 'local',
data: mydata,
colNames:['Inv No','Date', 'Client', 'Amount','Tax','Total','Notes'],
colModel: buildColumnModel(columns),
height: '100%',
width: 720,
toppager: true,
gridview: true,
pager: pagerSelector,
rowNum: 10,
rowList: [5, 10, 20, 50],
sortname: 'id',
sortorder: 'asc',
viewrecords: true,
caption: 'Add buttons to both top and bottom toolbars',
afterInsertRow: function (rowid, rowdata, rowelem) {
$(this).attr("data-toggle", "modal");
$(this).attr("data-target", ".bs-example-modal-sm");
},
beforeRequest: function () {
var separator = ',';
var i, l, rules, rule, parts, j, group, str, iCol, cmi;
console.log("filter:" + this.p.postData.filters);
var cm = this.p.colModel, filters;
if (this.p.postData.filters && this.p.postData.filters !== 'undefined')
filters = $.parseJSON(this.p.postData.filters);
if (filters && typeof filters.rules !== 'undefined' && filters.rules.length > 0) {
rules = filters.rules;
for (i = 0; i < rules.length; i++) {
rule = rules[i];
iCol = getColumnIndexByName.call(this, rule.field);
cmi = cm[iCol];
if (iCol >= 0 && ((typeof (cmi.searchoptions) === "undefined" ||
typeof (cmi.searchoptions.sopt) === "undefined")
&& rule.op === 'cn') /*||
(typeof (cmi.searchoptions) === "object" &&
$.isArray(cmi.searchoptions.sopt) &&
cmi.searchoptions.sopt[0] === rule.op)*/) {
// make modifications only for the 'contains' operation
parts = rule.data.split(separator);
if (parts.length > 1) {
if (typeof filters.groups === 'undefined') {
filters.groups = [];
}
group = {
groupOp: 'OR',
groups: [],
rules: []
};
filters.groups.push(group);
for (j = 0, l = parts.length; j < l; j++) {
str = parts[j];
if (str) {
// skip empty '', which exist in case of two separaters of once
group.rules.push({
data: parts[j],
op: rule.op,
field: rule.field
});
}
}
rules.splice(i, 1);
i--; // to skip i++
}
}
}
this.p.postData.filters = JSON.stringify(filters);
}
}
, loadComplete: function (data) {
var columnNamesArr = columns.split(',');
for (i = 0; i < columnNamesArr.length; i++) {
setSearchSelect(columnNamesArr[i]);
}
$("#list").jqGrid('filterToolbar', {
search: true, searchOnEnter: true, autosearch: true, defaultSearch: 'cn'
});
if (data != null && data.records != null) {
$("#recordCount").text(data.records.toString());
}
$("#list").trigger("reloadGrid");
}
});
$("#list").jqGrid('filterToolbar',
{stringResult:true, searchOnEnter:true, defaultSearch:'cn'});
$("#setbw").click(function() {
$("#list").jqGrid('setColProp','name',{searchoptions:{sopt:['bw']}});
});
$("#setew").click(function() {
$("#list").jqGrid('setColProp','name',{searchoptions:{sopt:['ew']}});
});
function buildColumnModel(columns) {
var uFields = columns.split(',');
var columns = [];
for (var i = 0; i < uFields.length; i++) {
if (uFields[i].indexOf('Id') > -1) {
columns.push({ name: uFields[i], index: uFields[i], hidden: true });
}
else {
columns.push({ name: uFields[i], index: uFields[i] });
}
}
return columns;
}
function setSearchSelect(columnName) {
mygrid.jqGrid('setColProp', columnName, {
stype: 'select',
searchoptions: {
sopt: ['eq', 'ne'],
value: buildSearchSelect(getUniqueNames(columnName))
, attr: { multiple: 'multiple', size: 2 }
, dataInit: function (elem) {
setTimeout(function () {
$(elem).multiselect({
minWidth: 100,
height: "auto",
selectedList: 4,
checkAllText: "all",
uncheckAllText: "clear",
noneSelectedText: "All",
open: function () {
var $menu = $(".ui-multiselect-menu:visible");
$menu.width("auto");
return;
}
});
}, 50);
}
, dataEvents: [
{
type: "change",
fn: function (e) {
setTimeout(function () {
var columnNamesArr = columns.split(',');
for (i = 0; i < columnNamesArr.length; i++) {
if (columnNamesArr[i].toString() != columnName) {
htmlForSelect = ""; // = '<option value="">All</option>';
var un = getUniqueNames(columnNamesArr[i]);
var $select = $("select[id='gs_" + columnNamesArr[i] + "']");
for (j = 0; j < un.length; j++) {
val = un[j];
htmlForSelect += '<option value="' + val + '">' + val + '</option>';
}
$select.find('option').remove().end().append(htmlForSelect);
$select.multiselect('refresh');
setTimeout(function () {
$select.multiselect('destroy').multiselect({
minWidth: 100,
height: "auto",
selectedList: 4,
checkAllText: "all",
uncheckAllText: "clear",
noneSelectedText: "All",
open: function () {
var $menu = $(".ui-multiselect-menu:visible");
$menu.width("auto");
return;
}
});
}, 50);
}
}
}, 500);
}
}
]
}
});
}
function buildSearchSelect(uniqueNames) {
var values = '';
$.each(uniqueNames, function () {
if (this.length > 0) {
values += this + ":" + this + ";";
}
});
if (values != null) {
values = values.substr(0, values.length - 1);
}
return values;
}
function getUniqueNames(columnName) {
var texts = mygrid.jqGrid('getCol', columnName);
var uniqueTexts = [];
var textsLength = texts.length;
var text;
var textsMap = {};
var 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);
}
}
uniqueTexts.sort();
return uniqueTexts;
}
});
//]]>
</script>
</head>
<body>
<fieldset style="float:left">
<button id="setbw">Set on 'Client' search option to 'begin with'</button>
<button id="setew">Set on 'Client' search option to 'end with'</button>
</fieldset>
<div style="clear:left">
<table id="list"><tbody><tr><td/></tr></tbody></table>
<div id="pager"></div>
</div>
</body>
</html>
Upvotes: 0
Reputation: 1561
I solved this by hooking into dataEvents on the searchOptions, which as far as I can tell, is called during a change event of the the filter dropdown. I had to rebuild the unique values that would go into the filter dropdown for each column and then rebuild each html select:
function setSearchSelect(columnName) {
grid.jqGrid('setColProp', columnName, {
stype: 'select',
searchoptions: {
sopt: ['eq', 'ne'],
value: buildSearchSelect(getUniqueNames(columnName))
, attr: { multiple: 'multiple', size: 2 }
, dataInit: function (elem) {
setTimeout(function () {
$(elem).multiselect({
minWidth: 100,
height: "auto",
selectedList: 4,
checkAllText: "all",
uncheckAllText: "clear",
noneSelectedText: "All",
open: function () {
var $menu = $(".ui-multiselect-menu:visible");
$menu.width("auto");
return;
}
});
}, 50);
}
, dataEvents: [
{
type: "change",
fn: function (e) {
setTimeout(function () {
var columnNamesArr = columns.split(',');
for (i = 0; i < columnNamesArr.length; i++) {
if (columnNamesArr[i].toString() != columnName) {
htmlForSelect = ""; // = '<option value="">All</option>';
var un = getUniqueNames(columnNamesArr[i]);
var $select = $("select[id='gs_" + columnNamesArr[i] + "']");
for (j = 0; j < un.length; j++) {
val = un[j];
htmlForSelect += '<option value="' + val + '">' + val + '</option>';
}
$select.find('option').remove().end().append(htmlForSelect);
$select.multiselect('refresh');
setTimeout(function () {
$select.multiselect('destroy').multiselect({
minWidth: 100,
height: "auto",
selectedList: 4,
checkAllText: "all",
uncheckAllText: "clear",
noneSelectedText: "All",
open: function () {
var $menu = $(".ui-multiselect-menu:visible");
$menu.width("auto");
return;
}
});
}, 50);
}
}
}, 500);
}
}
]
}
});
}
If you have any questions, about this, I'll try my best to answer.
Upvotes: 2