# Column selection in Dash AG Grid

**URL:** <https://community.plotly.com/t/column-selection-in-dash-ag-grid/81007>\
**Category:** Dash Python\
**Created:** [December 18, 2023, 3:51pm UTC](https://community.plotly.com/t/column-selection-in-dash-ag-grid/81007 "2023-12-18T15:51:27Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![subodhpokhrel7](https://avatars.discourse-cdn.com/v4/letter/s/8c91f0/32.png) [@subodhpokhrel7](https://community.plotly.com/u/subodhpokhrel7)\
**Post date:** [December 18, 2023, 3:51pm UTC](https://community.plotly.com/t/column-selection-in-dash-ag-grid/81007/1 "2023-12-18T15:51:27Z")

</div>

Hi,

is there a way to make Dash AG Grid columns selectable as it is for rows?

---

<div class="post-metadata">

**Author:** ![jinnyzor](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jinnyzor/32/21194_2.png) [@jinnyzor](https://community.plotly.com/u/jinnyzor)\
**Post date:** [December 19, 2023, 1:38am UTC](https://community.plotly.com/t/column-selection-in-dash-ag-grid/81007/2 "2023-12-19T01:38:47Z")

</div>

Hello @subodhpokhrel7,

There isn’t something to select an entire column.

What is your use-case?

---

<div class="post-metadata">

**Author:** ![subodhpokhrel7](https://avatars.discourse-cdn.com/v4/letter/s/8c91f0/32.png) [@subodhpokhrel7](https://community.plotly.com/u/subodhpokhrel7)\
**Post date:** [December 19, 2023, 7:41am UTC](https://community.plotly.com/t/column-selection-in-dash-ag-grid/81007/3 "2023-12-19T07:41:17Z")

</div>

Hi @jinnyzor ,

Thank you.  
I’d like the user to be able to select two (out of multiple) columns for mathematical calculation for each cells in each row. Selecting from the header row should also work, but the whole column being highlighted when selected would make it visually better.

---

<div class="post-metadata">

**Author:** ![jinnyzor](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jinnyzor/32/21194_2.png) [@jinnyzor](https://community.plotly.com/u/jinnyzor)\
**Post date:** [December 19, 2023, 11:40am UTC](https://community.plotly.com/t/column-selection-in-dash-ag-grid/81007/4 "2023-12-19T11:40:31Z")

</div>

You could make the visual change by using cellClassRules styling and headerClass as well. You can add checkboxes as well, then build a dcc.Store that maintains your chosen columns and use that in your class functions.

---

<div class="post-metadata">

**Author:** ![subodhpokhrel7](https://avatars.discourse-cdn.com/v4/letter/s/8c91f0/32.png) [@subodhpokhrel7](https://community.plotly.com/u/subodhpokhrel7)\
**Post date:** [December 20, 2023, 3:39pm UTC](https://community.plotly.com/t/column-selection-in-dash-ag-grid/81007/5 "2023-12-20T15:39:15Z")

</div>

Hi @jinnyzor ,

is there a way to add checkboxes to headers and not make it look like the whole table is selected when any box is selected?  
If not, can a separate row be added with checkboxes?

I’m trying to do the styling of columns on selection here:

```auto
from dash import Dash, html, Input, Output, callback, State
import dash_ag_grid as dag
import pandas as pd
import json

df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/solar.csv")

app = Dash( __name__ )

grid = dag.AgGrid(
    id="cell-selection-simple-click-callback",
    rowData=df.to_dict("records"),
    columnDefs=[{"field": i} for i in df.columns],
    columnSize="sizeToFit",
    getRowId="params.data.State"
)

app.layout = html.Div([grid, html.Pre(id="pre-cell-selection-simple-click-callback")])

@callback(
    Output("pre-cell-selection-simple-click-callback", "children"),
    Input("cell-selection-simple-click-callback", "cellClicked")
)
def display_cell_clicked_on(cell):
    return f"Clicked on cell:\n{json.dumps(cell, indent=2)}" if cell else "Click on a cell"

@callback(
    Output('cell-selection-simple-click-callback', 'columnDefs'),
    Input('cell-selection-simple-click-callback', 'cellClicked'),
    State('cell-selection-simple-click-callback', 'columnDefs'),
    prevent_initial_call=True
)
def change_style(cell, col_def):

    field= cell['colId']

    for item in col_def:
        if item['field'] == field:
            item['cellStyle'] = {'background-color': '#66c2a5'}

        
    

    return col_def
    

if __name__ == " __main__":
    app.run(debug=True)

```

---

<div class="post-metadata">

**Author:** ![jinnyzor](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jinnyzor/32/21194_2.png) [@jinnyzor](https://community.plotly.com/u/jinnyzor)\
**Post date:** [December 20, 2023, 4:36pm UTC](https://community.plotly.com/t/column-selection-in-dash-ag-grid/81007/6 "2023-12-20T16:36:20Z")

</div>

Sure, here you go:

 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/c/e/ce853bb37f65986377fc3f5f9f56df52c5787df9.png)

css file:

```auto
.headerSelected {
    background-color: #66c2a5
}

```

js file:

```auto
const {useImperativeHandle, useRef, useState, useEffect, forwardRef, Component} = React
var dagfuncs = window.dashAgGridFunctions = window.dashAgGridFunctions || {};
var dagcomponentfuncs = window.dashAgGridComponentFunctions = window.dashAgGridComponentFunctions || {};

dagcomponentfuncs.SelectColumn = function (props) {
    const [checked, setChecked] = useState(JSON.parse(localStorage.getItem("headerSelections")).includes(props.column.colId))
    return React.createElement('div',
        {}, [
        React.createElement(
            'input',
            {
                onChange: () => {
                    setChecked(!checked)
                    selects = JSON.parse(localStorage.getItem("headerSelections"))
                    if (!checked) {
                        selects.push(props.column.colId)
                    } else {
                        for (y=0; y<selects.length; y++) {
                            if (selects[y] == props.column.colId) {
                                selects.splice(y, 1)
                                break
                            }
                        }
                    }
                    localStorage.setItem("headerSelections", JSON.stringify(selects))
                    document.getElementById('headerSelections_sync').click()
                    props.api.refreshCells()
                },
                className: props.className,
                style: props.style,
                type: "checkbox",
                checked: checked || false,
            }),
            props.displayName]
        )
}

dagfuncs.testSelections = (params) => {
    selections = JSON.parse(localStorage.getItem('headerSelections'))
    if (selections.includes(params.column.colId)) {
        return true
    }
    return false
}

```

app.py:

```auto
from dash import Dash, html, Input, Output, callback, State, dcc
import dash_ag_grid as dag
import pandas as pd
import json

df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/solar.csv")

app = Dash( __name__ )

grid = dag.AgGrid(
    id="cell-selection-simple-click-callback",
    rowData=df.to_dict("records"),
    columnDefs=[{"field": i, "headerComponent": "SelectColumn", "cellClassRules": {"headerSelected": "testSelections(params)"}} for i in df.columns],
    columnSize="sizeToFit",
    getRowId="params.data.State"
)

app.layout = html.Div([grid, html.Pre(id="pre-cell-selection-simple-click-callback"),
                       dcc.Store(id='headerSelections', storage_type='local', data=[]),
                       html.Button(id='headerSelections_sync', style={'display': 'none'})])

app.clientside_callback(
    """function (n) {
        return JSON.parse(localStorage.getItem('headerSelections'))
    }""",
    Output('headerSelections', 'data'),
    Input('headerSelections_sync', 'n_clicks')
)

if __name__ == " __main__":
    app.run(debug=True)

```

* * *

Only issue with this is that you would technically need to add sort and filter handlers, but only if you use them.

---

<div class="post-metadata">

**Author:** ![subodhpokhrel7](https://avatars.discourse-cdn.com/v4/letter/s/8c91f0/32.png) [@subodhpokhrel7](https://community.plotly.com/u/subodhpokhrel7)\
**Post date:** [December 21, 2023, 8:21am UTC](https://community.plotly.com/t/column-selection-in-dash-ag-grid/81007/7 "2023-12-21T08:21:07Z")

</div>

Hi @jinnyzor ,

It works great. Thank you.  
I have two follow up questions though, is there a way to limit the selections? Let’s say up to 2 columns.  
Also, it is not possible to use the cellClicked property of AG Grid anymore to see the column ID of the selected (and there isn’t a headerClicked or similar). Is there another way how I could see/store the column ID of the selections?

---

<div class="post-metadata">

**Author:** ![jinnyzor](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jinnyzor/32/21194_2.png) [@jinnyzor](https://community.plotly.com/u/jinnyzor)\
**Post date:** [December 21, 2023, 11:42am UTC](https://community.plotly.com/t/column-selection-in-dash-ag-grid/81007/8 "2023-12-21T11:42:22Z")

</div>

> [@subodhpokhrel7](#):
>
> Also, it is not possible to use the cellClicked property of AG Grid anymore to see the column ID of the selected (and there isn’t a headerClicked or similar). Is there another way how I could see/store the column ID of the selections?

The column selections are stored into a dcc.Store that you can access at any time. 😁

And yes, you can make it so only two are selected at a time. You just need to figure out how that is restricted. Does the next click remove one and add the other, etc.

---

<div class="post-metadata">

**Author:** ![subodhpokhrel7](https://avatars.discourse-cdn.com/v4/letter/s/8c91f0/32.png) [@subodhpokhrel7](https://community.plotly.com/u/subodhpokhrel7)\
**Post date:** [December 21, 2023, 12:28pm UTC](https://community.plotly.com/t/column-selection-in-dash-ag-grid/81007/9 "2023-12-21T12:28:26Z")

</div>

I had tried to print the selections after each clicks with `Input('headerSelections_sync', 'n_clicks')`, but it did not work as intended. Adding a continue button worked fine and printing the selections after click works fine. The limit to selections can now be added based of number in dcc.Store.

Thank you very much for your help

---

<div class="post-metadata">

**Author:** ![subodhpokhrel7](https://avatars.discourse-cdn.com/v4/letter/s/8c91f0/32.png) [@subodhpokhrel7](https://community.plotly.com/u/subodhpokhrel7)\
**Post date:** [January 10, 2024, 10:29am UTC](https://community.plotly.com/t/column-selection-in-dash-ag-grid/81007/10 "2024-01-10T10:29:18Z")

</div>

Hi @jinnyzor ,

I want to revisit this as I have run into a slight problem.  
The storage of the selected columns in localStorage causes persistence and also doesn’t work when run in incognito mode (or when cache is cleared or run in a new browser) with `Cannot read properties of null (reading 'includes')` as the error message. Is there a way to solve this issue?

I have tried replacing localStorage with sessionStorage, but to no avail.

---

<div class="post-metadata">

**Author:** ![jinnyzor](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jinnyzor/32/21194_2.png) [@jinnyzor](https://community.plotly.com/u/jinnyzor)\
**Post date:** [January 10, 2024, 12:20pm UTC](https://community.plotly.com/t/column-selection-in-dash-ag-grid/81007/11 "2024-01-10T12:20:56Z")

</div>

Did you try replacing all local in the code with session?

---

<div class="post-metadata">

**Author:** ![subodhpokhrel7](https://avatars.discourse-cdn.com/v4/letter/s/8c91f0/32.png) [@subodhpokhrel7](https://community.plotly.com/u/subodhpokhrel7)\
**Post date:** [January 10, 2024, 1:23pm UTC](https://community.plotly.com/t/column-selection-in-dash-ag-grid/81007/12 "2024-01-10T13:23:32Z")

</div>

Yes, in both of the files as well.

---

<div class="post-metadata">

**Author:** ![jinnyzor](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jinnyzor/32/21194_2.png) [@jinnyzor](https://community.plotly.com/u/jinnyzor)\
**Post date:** [January 10, 2024, 2:39pm UTC](https://community.plotly.com/t/column-selection-in-dash-ag-grid/81007/13 "2024-01-10T14:39:40Z")

</div>

Instead of using a storage, you could always just use a variable on the browser, you lose persistence upon refresh though.

---

<div class="post-metadata">

**Author:** ![jinnyzor](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jinnyzor/32/21194_2.png) [@jinnyzor](https://community.plotly.com/u/jinnyzor)\
**Post date:** [February 5, 2024, 3:01pm UTC](https://community.plotly.com/t/column-selection-in-dash-ag-grid/81007/14 "2024-02-05T15:01:13Z")

</div>

Split this topic on February 5, 2024, 3:01pm UTC

A post was split to a new topic: [Data Selection from AG Grid Column](https://community.plotly.com/t/data-selection-from-ag-grid-column/82109)

---

<div class="post-metadata">

**Author:** ![wowwwn](https://avatars.discourse-cdn.com/v4/letter/w/f07891/32.png) [@wowwwn](https://community.plotly.com/u/wowwwn)\
**Post date:** [April 3, 2024, 11:57am UTC](https://community.plotly.com/t/column-selection-in-dash-ag-grid/81007/15 "2024-04-03T11:57:00Z")

</div>

Hi, Thank you for the guide how to use the “headerComponent”.

However, if I wanted to apply sorting when clicking the column name as before, could you tell me how to do it?

my defaultColDef has set {“sortable”: True}

---

<div class="post-metadata">

**Author:** ![jinnyzor](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jinnyzor/32/21194_2.png) [@jinnyzor](https://community.plotly.com/u/jinnyzor)\
**Post date:** [April 3, 2024, 1:13pm UTC](https://community.plotly.com/t/column-selection-in-dash-ag-grid/81007/16 "2024-04-03T13:13:09Z")

</div>

Hello @wowwwn,

To add a sort handler, there must be an event handler inside the component that will trigger the grids sort to adjust.

You can check out more info here:

[https://www.ag-grid.com/react-data-grid/column-headers/](https://www.ag-grid.com/react-data-grid/column-headers/)

---

<div class="post-metadata">

**Author:** ![wowwwn](https://avatars.discourse-cdn.com/v4/letter/w/f07891/32.png) [@wowwwn](https://community.plotly.com/u/wowwwn)\
**Post date:** [April 4, 2024, 6:54am UTC](https://community.plotly.com/t/column-selection-in-dash-ag-grid/81007/17 "2024-04-04T06:54:01Z")

</div>

Thanks for the reply,

I found out how to apply sorting by clicking on a column header with the help of ChatGPT.

```auto
const {useImperativeHandle, useRef, useState, useEffect, forwardRef, Component} = React
var dagcomponentfuncs = window.dashAgGridComponentFunctions = window.dashAgGridComponentFunctions || {};

dagcomponentfuncs.SelectColumn = function (props) {
    const [checked, setChecked] = useState(JSON.parse(localStorage.getItem("headerSelections")).includes(props.column.colId))

    const [sortState, setSortState] = useState('');

    const onCheckboxChange = () => {
        setChecked(!checked);
        let selects = JSON.parse(localStorage.getItem("headerSelections"));
        if (!checked) {
            selects.push(props.column.colId);
        } else {
            selects = selects.filter(id => id !== props.column.colId);
        }
        localStorage.setItem("headerSelections", JSON.stringify(selects));
        document.getElementById('headerSelections_sync').click();
        props.api.refreshCells();
    };

    const onHeaderClick = (event) => {
        if (event.target.type !== 'checkbox') {

            let currentSort = props.column.getSort();
            let nextSortState;
    
            if (currentSort === 'asc') {
                nextSortState = 'desc';
                setSortState('desc');
            } else if (currentSort === 'desc') {
                nextSortState = null;
                setSortState('none'); 
            } else {
                nextSortState = 'asc';
                setSortState('asc'); 
            }

            props.api.applyColumnState({
                state: [{colId: props.column.colId, sort: nextSortState}],
            });
        }
    };

    const imagePath = (state) => {
        switch(state) {
            case 'asc': return 'assets/icons/bx-sort-up.png';
            case 'desc': return 'assets/icons/bx-sort-down.png';
            case 'none': return '';
            default: return '';
        }
    };

    return React.createElement('div',
        { onClick: onHeaderClick }, [
        React.createElement(
            'input',
            {
                onChange: onCheckboxChange,
                className: props.className,
                style: props.style,
                type: "checkbox",
                checked: checked || false,
            }),
            React.createElement('span', {style: { marginLeft: '8px'}}, props.displayName),
            
            sortState && React.createElement('img', { src: imagePath(sortState), style: { marginLeft: '8px' } }), 
        ]
        )
}

```

But still there is an issue that i’m struggling with.

I want to deselects all column checks, or reset all column sorting options by clicking a button which will trigger dash callback.
