# AG Grid - Invoke callbacks from custom header component

**URL:** <https://community.plotly.com/t/ag-grid-invoke-callbacks-from-custom-header-component/78335>\
**Category:** Dash Python\
**Created:** [September 6, 2023, 6:20pm UTC](https://community.plotly.com/t/ag-grid-invoke-callbacks-from-custom-header-component/78335 "2023-09-06T18:20:43Z")\
**Posts on this page:** 1\
**Showing post:** 2

<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:** [September 6, 2023, 6:57pm UTC](https://community.plotly.com/t/ag-grid-invoke-callbacks-from-custom-header-component/78335/2 "2023-09-06T18:57:19Z")

</div>

> [@Emil](#):
>
> Now my question is - is there any workaround to invoke a callback from a column? And/or is there any way to access the ‘setProps’ property of the grid, so that I can set (arbitrary) props myself? That would be neat 🙂

Hello @Emil,

Yes, there are a few workarounds.

The props here gives you access to the grid’s api, so you can use it to trigger another event that you can access.

You can pass the clicks to the sorting:

> **[React Data Grid: Header Components](https://www.ag-grid.com/archive/29.3.5/react-data-grid/component-header/#sorting)**
>
> You can specify what header renderer to use at the column definition level. Download v29 of the best React Data Grid in the world now.

You’d listen to `columnState` or `virtualRowData` for this.

You could also update a cell value on some hidden column in the first row.

You’d listen to `cellValueChanged` for this.

You also have access to the gridOptions, from which you can access some of the grid event listeners:

```auto
dagcomponentfuncs.ButtonHeader = function (props) {
    return React.createElement(
        'button',
        {
            onClick: () => {
            props.api.gridOptionsService.gridOptions.onCellClicked({value: {'headerClicked': props.column.colId},
            column: props.column.colId,
            rowIndex: null, node: []})},
            className: props.className,
            style: props.style,
        },
        props.displayName)
}

```

As far as setting arbitrary props, this isnt a supported way from the grid, this was discussed a little, but the idea was given that Dash would eventually support this. XD

But… I have a workaround for that too:

```auto
function get_setProps(dom, traverseUp = 0) {
    const key = Object.keys(dom).find(key=>{
        return key.startsWith("__reactFiber$") // react 17+
            || key.startsWith("__reactInternalInstance$"); // react <17
    });
    const domFiber = dom[key];
    if (domFiber == null) return null;

    // react <16
    if (domFiber._currentElement) {
        let compFiber = domFiber._currentElement._owner;
        for (let i = 0; i < traverseUp; i++) {
            compFiber = compFiber._currentElement._owner;
        }
        return compFiber;
    }

    // react 16+
    const GetCompFiber = fiber=>{
        //return fiber._debugOwner; // this also works, but is __DEV__ only
        let parentFiber = fiber.return;
        while (typeof parentFiber.type == "string") {
            parentFiber = parentFiber.return;
        }
        return parentFiber;
    };
    let compFiber = GetCompFiber(domFiber);
    for (let i = 0; i < traverseUp; i++) {
        compFiber = GetCompFiber(compFiber);
    }
    if (compFiber.stateNode) {
        if (Object.keys(compFiber.stateNode.props).includes('setProps')) {
            return compFiber.stateNode.props
        }
        if (Object.keys(compFiber.stateNode).includes('setProps')) {
            return compFiber.stateNode
        }
    }
    for (let i = 0; i < 30; i++) {
        compFiber = GetCompFiber(compFiber);
        if (compFiber.stateNode) {
            if (Object.keys(compFiber.stateNode.props).includes('setProps')) {
                return compFiber.stateNode.props
            }
            if (Object.keys(compFiber.stateNode).includes('setProps')) {
                return compFiber.stateNode
            }
        }
    }
    throw new Error("this is not the dom you are looking for")
}

```

Whole thing together:

```auto
function get_setProps(dom, traverseUp = 0) {
    const key = Object.keys(dom).find(key=>{
        return key.startsWith("__reactFiber$") // react 17+
            || key.startsWith("__reactInternalInstance$"); // react <17
    });
    const domFiber = dom[key];
    if (domFiber == null) return null;

    // react <16
    if (domFiber._currentElement) {
        let compFiber = domFiber._currentElement._owner;
        for (let i = 0; i < traverseUp; i++) {
            compFiber = compFiber._currentElement._owner;
        }
        return compFiber;
    }

    // react 16+
    const GetCompFiber = fiber=>{
        //return fiber._debugOwner; // this also works, but is __DEV__ only
        let parentFiber = fiber.return;
        while (typeof parentFiber.type == "string") {
            parentFiber = parentFiber.return;
        }
        return parentFiber;
    };
    let compFiber = GetCompFiber(domFiber);
    for (let i = 0; i < traverseUp; i++) {
        compFiber = GetCompFiber(compFiber);
    }
    if (compFiber.stateNode) {
        if (Object.keys(compFiber.stateNode.props).includes('setProps')) {
            return compFiber.stateNode.props
        }
        if (Object.keys(compFiber.stateNode).includes('setProps')) {
            return compFiber.stateNode
        }
    }
    for (let i = 0; i < 30; i++) {
        compFiber = GetCompFiber(compFiber);
        if (compFiber.stateNode) {
            if (Object.keys(compFiber.stateNode.props).includes('setProps')) {
                return compFiber.stateNode.props
            }
            if (Object.keys(compFiber.stateNode).includes('setProps')) {
                return compFiber.stateNode
            }
        }
    }
    throw new Error("this is not the dom you are looking for")
}

dagcomponentfuncs.ButtonHeader = function (props) {
    return React.createElement(
        'button',
        {
            onClick: () => {get_setProps(event.target.closest('div.ag-theme-alpine')).setProps({'cellClicked': {value: `header clicked ${props.column.colId}`}})},
            className: props.className,
            style: props.style,
        },
        props.displayName)
}

```

app:

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

df = pd.read_csv(
    "https://raw.githubusercontent.com/plotly/datasets/master/ag-grid/olympic-winners.csv"
)

app = Dash( __name__ )
app.layout = html.Div(
    [
        dag.AgGrid(
            id="column-definition-ID",
            rowData=df.to_dict("records"),
            columnDefs=[{
                "field": "athlete",
                "headerName": "Athlete",
                "headerComponent": "ButtonHeader" # select custom component
            }],
            columnSize="sizeToFit",
        ),
        html.Div(id='output')
    ]
)

@app.callback(Output('output', 'children'),
              Input('column-definition-ID', 'cellClicked'))
def sorting(s):
    return json.dumps(s)

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

```

* * *

Now, with all this said, this should technically be an issue on github because it shouldnt be dependent if you have the component in a row. 😃

---

_[View the full topic](https://community.plotly.com/t/ag-grid-invoke-callbacks-from-custom-header-component/78335)._
