68
Views
5
Comments
Solved
[OutSystems Data Grid] Column picker that can hide/unhide all columns
outsystems-data-grid
Reactive icon
Forge asset by OutSystems
Application Type
Reactive
Service Studio Version
11.53.43 (Build 62091)

Column picker that can hide/unhide all columns

I would like to add a column picker that can hide/unhide all columns. Is there any way to do this?

2022-11-12 11-28-30
Gonçalo Martins
Staff
Solution

Hello @Haruka Arakawa 

It was quite complex but I figured out a way to implement this (note that some use cases might be missing and this is unsupported code).

  1. In the Grid Initialize event add the following code:
    function createColumnPickerSelectAll() {
        // Create the main container
        const columnPickerContainer = document.createElement('div');
        columnPickerContainer.style.display = 'none';
        columnPickerContainer.classList.add('column-picker-container');
    
        // Create the column picker element
        const columnPicker = document.createElement('div');
        columnPicker.id = 'theColumnPicker';
        columnPicker.classList.add('column-picker');
        columnPickerContainer.appendChild(columnPicker);
    
        // Create the column picker data element
        const columnPickerData = document.createElement('div');
        columnPickerData.classList.add('column-picker-data');
        columnPickerContainer.appendChild(columnPickerData);
    
        // Create the checkbox and label
        const checkbox = document.createElement('input');
        checkbox.type = 'checkbox';
        checkbox.classList.add('selectChk');
    
        const label = document.createElement('label');
        label.textContent = 'All';
    
        columnPickerData.appendChild(checkbox);
        columnPickerData.appendChild(label);
    
        return columnPickerContainer;
    }
    
    var theGrid = OutSystems.GridAPI.GridManager.GetGridById($parameters.GridWidgetId);
    
    // Check if the FlexGrid instance is valid
    if (theGrid) {
    
        var theColumnPicker = theGrid.features.columnPicker._theColumnPicker;
        var columnsToBeDisplayedOnColumnPicker = theGrid.features.columnPicker._getColumnsToBeDisplayedOnColumnPicker();
        theColumnPicker.itemsSource = columnsToBeDisplayedOnColumnPicker;
    
        const topLeftCell = theGrid.provider.hostElement.querySelector('.wj-topleft');
    
        topLeftCell.addEventListener('mousedown', (event) => {
      
            const target = event.target;
            if (!wijmo.hasClass(target, 'column-picker-icon')) return;
    
            let spanPrev = theGrid.provider.hostElement.querySelector('.column-picker-icon');
            spanPrev.outerHTML = spanPrev.outerHTML; // This removes all events
    
            const columnPickerHost = theColumnPicker.hostElement;
            const isColumnPickerVisible = columnPickerHost.offsetHeight > 0;
    
            if (!isColumnPickerVisible) {
    
                const alreadyHaveSelectAll = columnPickerHost.querySelector('.column-picker-data') !== null
                const elemSelectAll = alreadyHaveSelectAll ? columnPickerHost.querySelector('.column-picker-data') : createColumnPickerSelectAll();
                const columnPickerDataElement = elemSelectAll.querySelector('.column-picker-data');
    
                if (columnPickerDataElement && !alreadyHaveSelectAll) {
                    const selectCheckbox = columnPickerDataElement.querySelector('.selectChk');
    
                    // Insert the 'selectAll' checkbox element into the column picker host
                    selectCheckbox.checked = true;
                    
                    columnPickerHost.insertBefore(columnPickerDataElement, columnPickerHost.firstChild);
    
                    // Handle checkbox change event
                    selectCheckbox.addEventListener('change', (ev) => {
                    const isChecked = ev.target.checked;
                    theColumnPicker.checkedItems = isChecked
                        ? theColumnPicker.collectionView.items
                        : [];
                    });
    
                    // Check 'SelectAll' checkbox when clicked on it's item(optional)
                    columnPickerHost.addEventListener('click', (ev) => {
                    const target = ev.target;
                    if (
                        wijmo.closestClass(target, 'column-picker-data') && !wijmo.hasClass(target, 'selectChk')
                    ) {
                        if (selectCheckbox.indeterminate) {
                            selectCheckbox.indeterminate = false;
                            selectCheckbox.checked = true;
                            theColumnPicker.checkedItems = theColumnPicker.collectionView.items;
                        } else {
                        selectCheckbox.checked = !selectCheckbox.checked;
                        theColumnPicker.checkedItems = selectCheckbox.checked 
                            ? theColumnPicker.collectionView.items
                            : [];
                        }
                    }
                    });
                }
                // Show the popup and focus on the column picker
                wijmo.showPopup(columnPickerHost, topLeftCell, false, true, false);
                theColumnPicker.focus();
            } 
            else {
                // Hide the popup and refocus on the grid
                wijmo.hidePopup(columnPickerHost, true, true);
                theGrid.provider.focus();
            }
            // Prevent default behavior
            event.preventDefault();
        });
    
    } 
                     
    		


  2. To make it look nicer you can add this custom CSS to your theme:

    .wj-listbox.column-picker {
      display: grid;
      grid-template-columns: repeat(1, 1fr);
      grid-gap: 0 10px;
      columns: 1; /* IE fallback */
      padding: 12px;
      margin-left: 12px;
      margin-top: 26px;
      box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);
    }
    .wj-listbox .wj-listbox-item > label {
      display: block;
      margin: 0 0 3px 0;
    }
    .wj-listbox .wj-listbox-item.wj-state-selected {
      background: transparent;
      color: inherit;
    }
    .wj-listbox .wj-listbox-item:hover {
      background: rgba(0, 0, 0, 0.05);
    }
    .wj-listbox .drop-marker {
      position: absolute;
      background: #0085c7;
      opacity: 0.5;
      pointer-events: none;
      z-index: 1000;
    }
    
    .column-picker-data {
      padding: 4px 6px 3px 6px;
    }
    
    .column-picker-data .selectChk {
      margin: 4px;
    }
                    

Here's the result:


Hope it helps!

Cheers,
GM

UserImage.jpg
Haruka Arakawa

Thank you. I tried the method described in that link, but it did not work.

2022-11-12 11-28-30
Gonçalo Martins
Staff
Solution

Hello @Haruka Arakawa 

It was quite complex but I figured out a way to implement this (note that some use cases might be missing and this is unsupported code).

  1. In the Grid Initialize event add the following code:
    function createColumnPickerSelectAll() {
        // Create the main container
        const columnPickerContainer = document.createElement('div');
        columnPickerContainer.style.display = 'none';
        columnPickerContainer.classList.add('column-picker-container');
    
        // Create the column picker element
        const columnPicker = document.createElement('div');
        columnPicker.id = 'theColumnPicker';
        columnPicker.classList.add('column-picker');
        columnPickerContainer.appendChild(columnPicker);
    
        // Create the column picker data element
        const columnPickerData = document.createElement('div');
        columnPickerData.classList.add('column-picker-data');
        columnPickerContainer.appendChild(columnPickerData);
    
        // Create the checkbox and label
        const checkbox = document.createElement('input');
        checkbox.type = 'checkbox';
        checkbox.classList.add('selectChk');
    
        const label = document.createElement('label');
        label.textContent = 'All';
    
        columnPickerData.appendChild(checkbox);
        columnPickerData.appendChild(label);
    
        return columnPickerContainer;
    }
    
    var theGrid = OutSystems.GridAPI.GridManager.GetGridById($parameters.GridWidgetId);
    
    // Check if the FlexGrid instance is valid
    if (theGrid) {
    
        var theColumnPicker = theGrid.features.columnPicker._theColumnPicker;
        var columnsToBeDisplayedOnColumnPicker = theGrid.features.columnPicker._getColumnsToBeDisplayedOnColumnPicker();
        theColumnPicker.itemsSource = columnsToBeDisplayedOnColumnPicker;
    
        const topLeftCell = theGrid.provider.hostElement.querySelector('.wj-topleft');
    
        topLeftCell.addEventListener('mousedown', (event) => {
      
            const target = event.target;
            if (!wijmo.hasClass(target, 'column-picker-icon')) return;
    
            let spanPrev = theGrid.provider.hostElement.querySelector('.column-picker-icon');
            spanPrev.outerHTML = spanPrev.outerHTML; // This removes all events
    
            const columnPickerHost = theColumnPicker.hostElement;
            const isColumnPickerVisible = columnPickerHost.offsetHeight > 0;
    
            if (!isColumnPickerVisible) {
    
                const alreadyHaveSelectAll = columnPickerHost.querySelector('.column-picker-data') !== null
                const elemSelectAll = alreadyHaveSelectAll ? columnPickerHost.querySelector('.column-picker-data') : createColumnPickerSelectAll();
                const columnPickerDataElement = elemSelectAll.querySelector('.column-picker-data');
    
                if (columnPickerDataElement && !alreadyHaveSelectAll) {
                    const selectCheckbox = columnPickerDataElement.querySelector('.selectChk');
    
                    // Insert the 'selectAll' checkbox element into the column picker host
                    selectCheckbox.checked = true;
                    
                    columnPickerHost.insertBefore(columnPickerDataElement, columnPickerHost.firstChild);
    
                    // Handle checkbox change event
                    selectCheckbox.addEventListener('change', (ev) => {
                    const isChecked = ev.target.checked;
                    theColumnPicker.checkedItems = isChecked
                        ? theColumnPicker.collectionView.items
                        : [];
                    });
    
                    // Check 'SelectAll' checkbox when clicked on it's item(optional)
                    columnPickerHost.addEventListener('click', (ev) => {
                    const target = ev.target;
                    if (
                        wijmo.closestClass(target, 'column-picker-data') && !wijmo.hasClass(target, 'selectChk')
                    ) {
                        if (selectCheckbox.indeterminate) {
                            selectCheckbox.indeterminate = false;
                            selectCheckbox.checked = true;
                            theColumnPicker.checkedItems = theColumnPicker.collectionView.items;
                        } else {
                        selectCheckbox.checked = !selectCheckbox.checked;
                        theColumnPicker.checkedItems = selectCheckbox.checked 
                            ? theColumnPicker.collectionView.items
                            : [];
                        }
                    }
                    });
                }
                // Show the popup and focus on the column picker
                wijmo.showPopup(columnPickerHost, topLeftCell, false, true, false);
                theColumnPicker.focus();
            } 
            else {
                // Hide the popup and refocus on the grid
                wijmo.hidePopup(columnPickerHost, true, true);
                theGrid.provider.focus();
            }
            // Prevent default behavior
            event.preventDefault();
        });
    
    } 
                     
    		


  2. To make it look nicer you can add this custom CSS to your theme:

    .wj-listbox.column-picker {
      display: grid;
      grid-template-columns: repeat(1, 1fr);
      grid-gap: 0 10px;
      columns: 1; /* IE fallback */
      padding: 12px;
      margin-left: 12px;
      margin-top: 26px;
      box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);
    }
    .wj-listbox .wj-listbox-item > label {
      display: block;
      margin: 0 0 3px 0;
    }
    .wj-listbox .wj-listbox-item.wj-state-selected {
      background: transparent;
      color: inherit;
    }
    .wj-listbox .wj-listbox-item:hover {
      background: rgba(0, 0, 0, 0.05);
    }
    .wj-listbox .drop-marker {
      position: absolute;
      background: #0085c7;
      opacity: 0.5;
      pointer-events: none;
      z-index: 1000;
    }
    
    .column-picker-data {
      padding: 4px 6px 3px 6px;
    }
    
    .column-picker-data .selectChk {
      margin: 4px;
    }
                    

Here's the result:


Hope it helps!

Cheers,
GM

2026-02-16 06-54-31
Sathish Kumar

Hi @Gonçalo Martins 

Could you kindly edit the script? It seems that 'mygrid' is mentioned incorrectly, and I believe 'theGrid' should be used instead. 

If I deselect a any column name in the column picker, the 'Select All' checkbox does not get unchecked. 

Thanks,

Sathish R

2022-11-12 11-28-30
Gonçalo Martins
Staff

Hi @Sathish Kumar 

Yes, it was a typo while copying and pasting but it's fixed.

Regarding the logic to control the SelectAll based on the other, I didn't implement it since the hardest part was adding the SelectAll logic so it's expected for you to fine-tune the logic that is quite simpler.

Cheers,
GM

Community GuidelinesBe kind and respectful, give credit to the original source of content, and search for duplicates before posting.