问题
I am trying to add the multi-select filter to my PROVIDER
column in the jqGrid
. I am able to add the select filter but now I am converting it to the multi-select filter. I referred to a few old posts here and tried to do the same. It's not throwing me any error but it is not creating the multi-select filter also. Please let me know what I am doing wrong below.
I am able to get the unique values and able to create the SELECT list, I am guessing something is wrong with function dataInitMultiselect because I tried to console.log(elem) but it's not returning anything, not even undefined but the function is getting called because its not throwing me undefined function error.
$("#home_grid").jqGrid({
url: "/URL_TO_FETCH_DATA",
datatype: "json",
mtype: "GET",
colNames: ["Provider", "Title","Original Publish Time", "Fetch Time"],
colModel:
[
{
name : "PROVIDER",
align : "center",
width : "120%",
search : true
},
{
name : "TITLE",
align : "center",
search : true,
width : "250%",
formatter: Title_Url_Bind
},
{
name : "PUBLISH_TIME",
align : "center",
width : "130%",
search : true,
sorttype : "datetime"
},
{
name : "DB_ENTRY_TIME",
align : "center",
width : "130%",
sortable : true,
sorttype : "datetime"
}
],
pager : "#home_pager",
loadonce : true,
shrinkToFit : true,
rowNum : 10,
autoHeight : true,
rowList : [10, 15, 20, 25, 50],
sortable : true,
viewrecords : true,
toolbar : [true, "top"],
autowidth : true,
beforeProcessing: beforeProcessingHandler1,
});
function beforeProcessingHandler1(data) {
initializeGridFilterValueDem(data);
}
initializeGridFilterValueDem = function (data) {
setSearchSelect("Provider", jQuery("#home_grid"), data);
}
setSearchSelect = function (columnName, grid,data) {
grid.jqGrid('setColProp', columnName,
{
searchoptions: {
clearSearch: false,
sopt: ['eq', 'ne'],
value: buildSearchSelect(getUniqueNames(columnName, data,grid)),
attr: { multiple: 'multiple', size: 7},
dataInit: dataInitMultiselect
}
}
);
}
buildSearchSelect = function (uniqueNames) {
var values = "";
$.each(uniqueNames, function () {
values += this + ":" + this + ";";
});
return values.substring(0, values.length - 1);
}
getUniqueNames = function (columnName, mydata_parm, grid) {
var mydata = grid.jqGrid("getGridParam", "data");
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;
}
dataInitMultiselect = function (elem) {
console.log(elem);
setTimeout(function () {
var $elem = $(elem), id = elem.id,
inToolbar = typeof id === "string" && id.substr(0, 3) === "gs_",
options = {
selectedList: 2,
height: "auto",
checkAllText: "all",
uncheckAllText: "no",
noneSelectedText: "Any",
open: function () {
var $menu = $(".ui-multiselect-menu:visible");
$menu.width("auto");
return;
}
},
$options = $elem.find("option");
if ($options.length > 0 && $options[0].selected) {
$options[0].selected = false; // unselect the first selected option
}
if (inToolbar) {
options.minWidth = 'auto';
}
//$elem.multiselect(options);
$elem.multiselect(options).multiselectfilter({ placeholder: '' });
$elem.siblings('button.ui-multiselect').css({
width: inToolbar ? "98%" : "100%",
marginTop: "1px",
marginBottom: "1px",
paddingTop: "3px"
});
}, 50);
};
Thanks a lot for the response, Yes I am using the free jqGrid. As per the mentioned comment I tried to change the code but still not working for me. Please find below the updated code, I tried to do as mentioned in the jqGrid MultiSelect Demo
But it's throwing me the error Uncaught ReferenceError: multiselectTemplate is not defined
, Please let me know how to resolve this.
Since they have used the local data to load the jqgrid I am finding it difficult to resolve this issue.
//FUNCTION TO POPULATE THE TABLE WITH THE DATA
function Grid_Table_Populator()
{
//Populdate the Datatable with the WEB Feed data
$("#home_grid").jqGrid({
url: "/Web_Feed_Data",
datatype: "json",
mtype: "GET",
colNames: ["ID", "PROVIDER", "Title"],
colModel:
[
{
name : "ID",
align : "center",
search : true,
hidden : true
},
{
name : "PROVIDER",
align : "center",
width : "120%",
type : "text",
search : true,
template: multiselectTemplate
},
{
name : "TITLE",
align : "center",
search : true,
width : "250%",
formatter: Title_Url_Bind
},
],
pager : "#home_pager",
loadonce : true,
shrinkToFit : true,
rowNum : 10,
autoHeight : true,
rowList : [10, 15, 20, 25, 50],
sortable : true,
sortname : "TITLE",
sortorder : "desc",
viewrecords : true,
toolbar : [true, "top"],
autowidth : true,
caption : 'Table Data',
loadComplete: function(data)
{
if (!this.ftoolbar) {
// create filter toolbar if it isn't exist
$(this).jqGrid("filterToolbar", {
defaultSearch: "cn",
beforeClear: function() {
$(this.grid.hDiv)
.find(".ui-search-toolbar button.ui-multiselect")
.each(function() {
$(this).prev("select[multiple]").multiselect("refresh");
});
}
});
$(this).triggerHandler("jqGridRefreshFilterValues");
$(this.grid.hDiv)
.find(".ui-search-toolbar button.ui-multiselect")
.each(function() {
$(this).prev("select[multiple]")
.multiselect("refresh");
});
}
},
});
dataInitMultiselect = function (elem, searchOptions) {
var $grid = $(this);
setTimeout(function() {
var $elem = $(elem),
id = elem.id,
inToolbar = searchOptions.mode === "filter",
options = {
selectedList: 2,
height: "auto",
checkAllText: "all",
uncheckAllText: "no",
noneSelectedText: "Any",
open: function() {
var $menu = $(".ui-multiselect-menu:visible");
$menu.width("auto");
var height = $menu.find(">ul>li").first().outerHeight();
$menu.find(">ul").css("maxHeight", 5 * Math.max(height, 12));
return;
}
},
$options = $elem.find("option");
if ($options.length > 0 && $options[0].selected) {
$options[0].selected = false; // unselect the first selected option
}
if (inToolbar) {
options.minWidth = "auto";
}
$grid.triggerHandler("jqGridRefreshFilterValues");
$elem.multiselect(options);
// replace icons ui-icon-check, ui-icon-closethick, ui-icon-circle-close
// and ui-icon-triangle-1-s to font awesome icons
var $header = $elem.data("echMultiselect").header;
$header.find("span.ui-icon.ui-icon-check")
.removeClass("ui-icon ui-icon-check")
.addClass("fa fa-fw fa-check");
$header.find("span.ui-icon.ui-icon-closethick")
.removeClass("ui-icon ui-icon-closethick")
.addClass("fa fa-fw fa-times");
$header.find("span.ui-icon.ui-icon-circle-close")
.removeClass("ui-icon ui-icon-circle-close")
.addClass("fa fa-times-circle");
$elem.data("echMultiselect")
.button
.find("span.ui-icon.ui-icon-triangle-1-s")
.removeClass("ui-icon ui-icon-triangle-1-s")
.addClass("fa fa-caret-down")
.css({
float: "right",
marginRight: "5px"
});
$elem.siblings("button.ui-multiselect").css({
width: "100%",
margin: "1px 0",
paddingTop: ".3em",
paddingBottom: ".3em"
});
}, 50);
},
multiselectTemplate = {
stype: "select",
searchoptions: {
generateValue: true,
//noFilterText: "Any",
sopt: ["in"],
attr: {
multiple: "multiple",
size: 3
},
dataInit: dataInitMultiselect
}
};
}
I tried declaring it within the function and outside the function but still no luck. Please help me with this issue.
After the lot of help from Oleg I was able to get the Multi-Select but its not working. when I click on it does not expand and show the option. I have posted my code here MY JQGRID CODE@Oleg can you please look at this and provide me with solution.
My jqGrid is looking something like this:
回答1:
From your other questions one can see that you use free jqGrid fork. It supports generating of unique values automatically. Thus one can use
searchoptions: {
generateValue: true,
sopt: ["in"],
attr: { multiple: "multiple", size: 7 },
dataInit: dataInitMultiselect
}
instead of
searchoptions: {
clearSearch: false,
sopt: ['eq', 'ne'],
value: buildSearchSelect(getUniqueNames(columnName, data,grid)),
attr: { multiple: 'multiple', size: 7},
dataInit: dataInitMultiselect
}
It's important that unique values of data in the column will be filled only after loading the data. Then one should create or recreate filterToolbar
after loading the data from the server. One can test this.ftoolbar
inside of loadComplete
for example to detect whether filterToolbar
already exist:
loadComplete: function () {
if (!this.ftoolbar) {
// create filter toolbar if it isn't exist
$(this).jqGrid("filterToolbar", {
defaultSearch: "cn",
beforeClear: function() {
$(this.grid.hDiv)
.find(".ui-search-toolbar button.ui-multiselect")
.each(function() {
$(this).prev("select[multiple]").multiselect("refresh");
});
}
});
$(this).triggerHandler("jqGridRefreshFilterValues");
$(this.grid.hDiv)
.find(".ui-search-toolbar button.ui-multiselect")
.each(function() {
$(this).prev("select[multiple]")
.multiselect("refresh");
});
}
}
The demo https://jsfiddle.net/OlegKi/ty4e68pm/2/ shows a possible implementation of usage multiselect in free jqGrid. The function dataInitMultiselect
has the following implementation:
var dataInitMultiselect = function (elem, searchOptions) {
var $grid = $(this);
setTimeout(function() {
var $elem = $(elem),
id = elem.id,
inToolbar = searchOptions.mode === "filter",
options = {
selectedList: 2,
height: "auto",
checkAllText: "all",
uncheckAllText: "no",
noneSelectedText: "Any",
open: function() {
var $menu = $(".ui-multiselect-menu:visible");
$menu.width("auto");
}
},
$options = $elem.find("option");
if ($options.length > 0 && $options[0].selected) {
$options[0].selected = false; // unselect the first selected option
}
if (inToolbar) {
options.minWidth = "auto";
}
$grid.triggerHandler("jqGridRefreshFilterValues");
$elem.multiselect(options);
// replace icons ui-icon-check, ui-icon-closethick, ui-icon-circle-close
// and ui-icon-triangle-1-s to font awesome icons
var $header = $elem.data("echMultiselect").header;
$header.find("span.ui-icon.ui-icon-check")
.removeClass("ui-icon ui-icon-check")
.addClass("fa fa-fw fa-check");
$header.find("span.ui-icon.ui-icon-closethick")
.removeClass("ui-icon ui-icon-closethick")
.addClass("fa fa-fw fa-times");
$header.find("span.ui-icon.ui-icon-circle-close")
.removeClass("ui-icon ui-icon-circle-close")
.addClass("fa fa-times-circle");
$elem.data("echMultiselect")
.button
.find("span.ui-icon.ui-icon-triangle-1-s")
.removeClass("ui-icon ui-icon-triangle-1-s")
.addClass("fa fa-caret-down")
.css({
float: "right",
marginRight: "5px"
});
$elem.siblings("button.ui-multiselect").css({
width: "100%",
margin: "1px 0",
paddingTop: ".3em",
paddingBottom: ".3em"
});
}, 50);
};
UPDATED: I analysed your demo https://jsfiddle.net/B_AV_B/7ecrmtz4/5/. It contains a lot of error:
- you missing
stype : "select"
in multiselect column. The searching field have to have select type (stype : "select"
) to be able to be displayed as<select>
alement, which can be converted later with respect of multiselect control - I wrote you multiple times about importance inserting only one version of jQuery and other JavaScript libraries. Moreover, it's important to hold the order of inserted JS files based on dependencies. Multiselect widget is plugin to jQuery UI. Thus jQuery UI must be inserted before. In short you should replace
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-ui-multiselect-widget/2.0.2/jquery.multiselect.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
to
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-ui-multiselect-widget/2.0.2/jquery.multiselect.js"></script>
- You should remove
../bootstrap-multiselect/0.9.13/js/bootstrap-multiselect.js
, which overwritemultiselect
registered previously. - JavaScript is case sensitive. It seems that
ID
property of input data specifies unique id of every input item. jqGrid usesid
instead ofID
by default. If you usedatatype: "local"
then you should includelocalReader: { id: "ID" }
parameter. If you usedatatype: "json"
then you should includejsonReader: { id: "ID" }
. In your case you can include both parameters. - You used wrong code of
open
callback (compare your code, with the code from my answer). It's enough to use it asvar $menu = $(".ui-multiselect-menu:visible"); $menu.width("auto");
without additional actions, which makes some other items invisible. - Values of
width
property oncolModel
should be numbers and not strings like"120%"
. Numbers will be interpreted as pixels. If you useautowidth : true
the initialwidth
values will be proportionally increased to make the width of the grid equal to the width of outer element. - Finally I added some CSS rules to your demo
.ui-multiselect-menu .ui-multiselect-header ul,
.ui-multiselect-menu .ui-multiselect-checkboxes li {
font-size: 12px;
}
.ui-multiselect-menu .ui-multiselect-header a:hover {
text-decoration: none;
}
.ui-multiselect-menu .ui-multiselect-close {
margin-right: 3px;
}
You can modify the font-size
on the above rule corresponds to your requirements.
Modified demo is https://jsfiddle.net/OlegKi/teLja6z3/25/
来源:https://stackoverflow.com/questions/56528454/jqgrid-add-multi-select-column-filter-to-a-specific-column