This is a migrated thread and some comments may be shown as answers.

Column Selector in Grid Header?

10 Answers 879 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Paul White
Top achievements
Rank 1
Paul White asked on 14 Mar 2019, 02:19 AM

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

Sort by
0
Paul White
Top achievements
Rank 1
answered on 14 Mar 2019, 08:41 PM

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

0
Alex Hajigeorgieva
Telerik team
answered on 15 Mar 2019, 09:49 AM
Hello, 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
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Marouane
Top achievements
Rank 1
answered on 31 Mar 2020, 08:58 AM
Hi, did you find a solution to your question ? if yes, could you please share it ?
0
Alex Hajigeorgieva
Telerik team
answered on 02 Apr 2020, 09:32 AM

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

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.
0
Lee
Top achievements
Rank 1
Iron
Iron
Iron
answered on 18 Jun 2020, 05:39 PM
The Dojo in the above reply by Alex is close to what I'm looking for except when the user clicks the menu button it should just show the columns list rather than having to click on columns to see the columns selections.
0
Alex Hajigeorgieva
Telerik team
answered on 18 Jun 2020, 05:46 PM

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

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.
Lee
Top achievements
Rank 1
Iron
Iron
Iron
commented on 05 Jan 2022, 05:11 PM

How do I change the display name of the column to match the grid's display name? Currently it is showing the field name which is something like "Metric1" instead of "Daily Sales".
Martin
Telerik team
commented on 07 Jan 2022, 02:09 PM | edited

If I understand correctly, you wish to change the name of the column to be different than the field it is bound to? if that is the case, you can use the columns.title option.
Lee
Top achievements
Rank 1
Iron
Iron
Iron
commented on 07 Jan 2022, 02:45 PM | edited

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"));
}


Martin
Telerik team
commented on 11 Jan 2022, 12:30 PM

I tested the provided itemTemplate and it indeed seems to work as expected. At this point I am not able to see any issues but you can still do some thorough testing yourself, just to be sure.
0
Lee
Top achievements
Rank 1
Iron
Iron
Iron
answered on 18 Jun 2020, 06:28 PM
Perfect. Thanks!
0
Lee
Top achievements
Rank 1
Iron
Iron
Iron
answered on 19 Jun 2020, 04:22 PM

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. 

0
Lee
Top achievements
Rank 1
Iron
Iron
Iron
answered on 19 Jun 2020, 04:30 PM

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"
        }]
    }
    ];

0
Angel Petrov
Telerik team
answered on 22 Jun 2020, 02:24 PM

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

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.
Lee
Top achievements
Rank 1
Iron
Iron
Iron
commented on 05 Jan 2022, 10:34 PM

I also need to prevent the user from hiding certain columns. How would I do this?
Martin
Telerik team
commented on 07 Jan 2022, 02:10 PM

You can check this How-To article to exclude a column from the menu.
Tags
Grid
Asked by
Paul White
Top achievements
Rank 1
Answers by
Paul White
Top achievements
Rank 1
Alex Hajigeorgieva
Telerik team
Marouane
Top achievements
Rank 1
Lee
Top achievements
Rank 1
Iron
Iron
Iron
Angel Petrov
Telerik team
Share this question
or