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.
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:
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<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>
../bootstrap-multiselect/0.9.13/js/bootstrap-multiselect.js
, which overwrite multiselect
registered previously.ID
property of input data specifies unique id of every input item. jqGrid uses id
instead of ID
by default. If you use datatype: "local"
then you should include localReader: { id: "ID" }
parameter. If you use datatype: "json"
then you should include jsonReader: { id: "ID" }
. In your case you can include both parameters.open
callback (compare your code, with the code from my answer). It's enough to use it as var $menu = $(".ui-multiselect-menu:visible"); $menu.width("auto");
without additional actions, which makes some other items invisible.width
property on colModel
should be numbers and not strings like "120%"
. Numbers will be interpreted as pixels. If you use autowidth : true
the initial width
values will be proportionally increased to make the width of the grid equal to the width of outer element..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/