
Does anyone know if it's possible to have a single button in the grid header that lets me pick which columns to show/hide rather than having it in the column menu on each column???
https://dojo.telerik.com/etIbIvOC
10 Answers, 1 is accepted

This is some more detail based on our testing...
I need to have a grid where I can sort my columns by clicking on the text in the column header, filter a column using the little funnel icon on each column and then have a separate icon outside the grid that pops up the column selector.
This is the best example I can come up with that has the filtering and sorting....
https://dojo.telerik.com/ukicufEd
Question
is how can I add a single button to the page that when clicked brings
up the column selector. The only way we have been able to do it is to
enable the column menu ... This lets us have a button on the page to
bring up the column menu but this also replaces the funnel icon on each
column with the 3 dots for the column menu.
Any help would be
appreciated.... Maybe it's possible to "enable" the column menu but
disable it for every column so that we get the normal funnel icon but
our single column selector button still works?
"Ourmockup" attached is screenshot from our application where we have set "columnMenu: true" and have an icon that brings up the column selector. But this also changes each column to also have the column menu. We don't want this...
"DesiredResult" attached is a screenshot showing how
we want the columns to look with just the filter menu and we achieve
this by setting "columnMenu: false" but then our icon to bring up the
column selector no longer works...
Any help would be appreciated....
Tommy
The Kendo UI ColumnMenu is an internal widget. This means that it is possible for it to change in the future without notice and also, there is no documentation about it. Its source is in the kendo.columnmenu.js file so you can look at the source if necessary.
If you would like to use it, you can add it to the toolbar and initialize it like this:
var
grid = $(
"#grid"
).data(
"kendoGrid"
);
$(
"#elementID"
).kendoColumnMenu({
sortable:
false
,
filterable:
false
,
columns:grid.columns,
dataSource : grid.dataSource,
owner: grid,
});
Here is a runnable Dojo:
https://dojo.telerik.com/@bubblemaster/UNoWeHiX
Alternatively, you could create your own menu and use the grid's showColumn() and hideColumn() methods accordingly.
Regards,
Alex Hajigeorgieva
Progress Telerik

Hi, Marouane,
Is there something about the provided solution that you need changing?
https://dojo.telerik.com/@bubblemaster/UNoWeHiX/2
Kind
Regards,
Alex Hajigeorgieva
Progress Telerik
Our thoughts here at Progress are with those affected by the outbreak.

Hello, Lee,
I have just recently created one such example for another client of ours.
The Kendo UI suite has an internal widget that is used for multi-check filtering in the context of the grid.
I adapted it to be used as a column chooser like this:
- get the grid columns to serve as a data source
- change the messages from "Filter" to "Done"
- change the icon from filter to columns
- add a refresh event handler that uses the grid hideColumn()/showColumn() to toggle the columns' visibility
You can see the result in this runnable Dojo:
https://dojo.telerik.com/EMAGeCIF/2
I hope this helps.
Kind Regards,
Alex Hajigeorgieva
Progress Telerik
Our thoughts here at Progress are with those affected by the outbreak.
I couldn't figure out how to insert the title field on its own so I used the itemTemplate. I also created a new variable called includedColumns and filter out anything with menu: false to prevent adding columns that are not hideable to the menu (see my comment below for that feature). I had to modify the refresh function to account for that too. This is my code that seems to be working. Do you see any potential issues with it or do you have a better suggestion?
/*
* If you want to exclude a column from the show/hide menu set the column's menu
* property to false when defining the grid. If you do not set the property or set it to anything
* other than boolean false it will appear in the select columns list.
*
* gridId is the ID of the grid. Do not include the hash tag.
*
* columnSelectorContainer is the ID of the container you want the button placed in. Use this
* if you want the button in a specific place.
* If you do not include a columnSelectorContainer one will be created for you above the grid.
*/
function initKendoGridColumnSelector(gridId, columnSelectorContainer) {
if (!columnSelectorContainer) {
$(`#${gridId}`).before(`<div id="columnChooser_${gridId}" class="column-selector"></div>`);
columnSelectorContainer = `columnChooser_${gridId}`;
}
let grid = $(`#${gridId}`).data("kendoGrid");
let visibleColumns = grid.columns.map(function (col) {
if (!col.hidden) {
return {
value: col.field, operator: "eq", field: "field"
};
}
});
let includedColumns = grid.columns.filter(function (item) {
let showItem = true;
if (Object.prototype.hasOwnProperty.call(item, "menu")) {
showItem = false;
}
return showItem;
});
let chooserDs = new kendo.data.DataSource({
data: includedColumns,
filter: {
filters: visibleColumns,
logic: "or"
}
});
$(`#${columnSelectorContainer}`).kendoFilterMultiCheck({
field: "field",
itemTemplate: function (e) {
if (e.field == "all") {
return "<li class='k-item'><label class='k-label'><strong><input type='checkbox' /><span>#= all#</span></strong></label></li>";
}
return "<li class='k-item #= data.menu === false ? '' : ''#'><label class='k-label'><input type='checkbox' name='" + e.field + "' value='#=field#'/><span>#= title #</span></label></li>";
},
dataSource: chooserDs,
search: true,
messages: {
filter: translateText("Done", "Global"),
selectedItemsFormat: "{0} " + translateText("Columns Selected", "Global"),
clear: translateText("Hide All", "Global")
},
refresh: function (e) {
if (e.sender.dataSource.filter()) {
var columnsToShow = e.sender.getFilterArray();
$.each(includedColumns, function (i, col) {
if (columnsToShow.indexOf(col.field) > -1) {
grid.showColumn(col.field);
} else {
grid.hideColumn(col.field);
}
});
} else {
var columns = includedColumns;
$.each(columns, function (index, col) {
grid.hideColumn(col.field);
});
}
}
})
.find(".k-i-filter")
.removeClass("k-i-filter")
.addClass("k-i-columns");
$(`#${columnSelectorContainer}`).find(".k-grid-filter").attr("title", translateText("select Columns", "Global"));
$(`#${columnSelectorContainer}`).find(".k-grid-filter").attr("aria-label", translateText("select Columns", "Global"));
$(`#${columnSelectorContainer}`).find(".k-grid-filter").append(translateText("Select Columns", "Global"));
}


I'm actually running into a bit of an issue. My columns are grouped. I have the following structure:
ID
Group1:
- Sales
- Costs
Group2:
- Sales
- Costs
Totals:
- Sales
- Costs
In the grid's header ID, Group1, Group2, Totals appear in the top row. (ID spans 2 rows in the header). Sales and Costs appear under each of the headings in the second header row. When I follow your example I get 4 "columns" returnd: id, undefined, undefined, and undefined. How do I get the Sales and Costs columns for each group and create an option. I'm also going to want the user to be able to uncheck sales and have all three sales columns hidden.

Below is the idea of how my columns are set up - nested.
let columnSettings = [
{
field: "itemID",
title: "Item ID",
locked: true,
lockable: false,
width: 200
}, {
title: "Group 1",
headerTemplate: "<span class=\"col-group-header\">Group 1</span>",
columns: [{
field: "metrics[0].value",
title: "Sales",
template: `<span>#=kendo.format("${formatStrings.get(metric.unit) || "{0:n}"}", metrics[${index}].value) #</span>`,
width: "100px"
}, {
field: `metrics[1].value`,
title: "Costs",
template: `<span>#=kendo.format("${formatStrings.get(metric.unit) || "{0:n}"}", metrics[${index}].value) #</span>`,
width: "100px"
}]
}, {
title: "Group 2",
headerTemplate: "<span class=\"col-group-header\">Group 1</span>",
columns: [{
field: "metrics[2].value",
title: "Sales",
template: `<span>#=kendo.format("${formatStrings.get(metric.unit) || "{0:n}"}", metrics[${index}].value) #</span>`,
width: "100px"
}, {
field: `metrics[3].value`,
title: "Costs",
template: `<span>#=kendo.format("${formatStrings.get(metric.unit) || "{0:n}"}", metrics[${index}].value) #</span>`,
width: "100px"
}]
}, {
title: "Totals",
headerTemplate: "<span class=\"col-group-header\">Group 1</span>",
columns: [{
field: "metrics[4].value",
title: "Sales",
template: `<span>#=kendo.format("${formatStrings.get(metric.unit) || "{0:n}"}", metrics[${index}].value) #</span>`,
width: "100px"
}, {
field: `metrics[5].value`,
title: "Costs",
template: `<span>#=kendo.format("${formatStrings.get(metric.unit) || "{0:n}"}", metrics[${index}].value) #</span>`,
width: "100px"
}]
}
];
Hello,
When the columns are grouped you will need to flatten the structure and get the leaf columns. Please try something like the following.
var visibleColumns = leafColumns(grid.columns).map(function(col) {
if(!col.hidden){
return { value: col.field, operator: "eq", field: "field" }
}
});
function leafColumns(columns) {
var result = [];
for (var idx = 0; idx < columns.length; idx++) {
if (!columns[idx].columns) {
result.push(columns[idx]);
continue;
}
result = result.concat(leafColumns(columns[idx].columns));
}
return result;
}
var chooserDs = new kendo.data.DataSource({
data:leafColumns(grid.columns),
filter:{
filters: visibleColumns,
logic: "or"
}
});
Regards,
Angel Petrov
Progress Telerik
Our thoughts here at Progress are with those affected by the outbreak.