Dash ag-grid tooltip

Hi, I’m trying to create custom tootip on the dash ag-grid column names with similar style as a dbc.Tooltip. Here is what I’ve tried following the example on this link Tooltips | Dash for Python Documentation | Plotly, however, the arrow is above the box (misaligned). Any help would be appreciated!

var dagcomponentfuncs = window.dashAgGridComponentFunctions = window.dashAgGridComponentFunctions || {};

dagcomponentfuncs.CustomTooltip = function (props) {
if (props.rowIndex === undefined) {
return React.createElement(
‘div’,
{className: ‘fade show tooltip bs-tooltip-end’},
React.createElement(‘div’,{className: ‘tooltip-arrow’}, ),
React.createElement(‘div’,{className: ‘tooltip-inner’}, props.value)
);}
};

1 Like

Hello @kcamlegin,

Welcome to the community!

Did you know, you can just use the dbc.tooltip?

In your code, where you create the react element, instead of “div”, put window.dash_bootstrap_components.Tooltip.

Thanks, I didn’t know that! I’ve now tried the following which shows the tooltip but not when I hover over the column name but appears at the side of the table (the ID of the datatable is datatable-interactivity). I’m not sure why?

dagcomponentfuncs.CustomTooltip = function (props) {
if (props.rowIndex === undefined) {
return React.createElement(
window.dash_bootstrap_components.Tooltip,
{target: ‘datatable-interactivity’},
props.value)
;}
};

I think this should be:

dagcomponentfuncs.CustomTooltip = function (props) {
if (props) {
    return React.createElement(
        window.dash_bootstrap_components.Tooltip,
        {},
        props.value)
    }
};

You shouldnt have to worry about the location, but maybe you do. XD

Thanks, unfortunately that’s the first thing I tried before putting a target in the curly brackets… And nothing shows up initially.

Use console log on the params and see if there is an element in there that you can target.

Hi @jinnyzor, thanks but this is too complicated for me, I think I need to work around it.

Can you give me an example app to work with, to see if I can get it working for you?

Here, give this a shot:

js file:

var dagcomponentfuncs = window.dashAgGridComponentFunctions = window.dashAgGridComponentFunctions || {};


dagcomponentfuncs.CustomTooltip = function (props) {
    info = [
        React.createElement('h4', {}, props.data.ticker),
        React.createElement('div', {}, props.data.company),
        React.createElement('div', {}, props.data.price),
    ];

    return React.createElement('div',{},[React.createElement(
        window.dash_bootstrap_components.Tooltip,
        {
            target: `ticker_${props.value}`,
            placement: 'bottom'
        },
        info
    ),
    React.createElement(
        "div",
        {
            id: `ticker_${props.value}`,
        },
        props.value
    )])
};

app.py:

import dash_ag_grid as dag
from dash import Dash, html, dcc
import pandas as pd
import dash_bootstrap_components as dbc

data = {
    "ticker": ["AAPL", "MSFT", "AMZN", "GOOGL"],
    "company": ["Apple", "Microsoft", "Amazon", "Alphabet"],
    "price": [154.99, 268.65, 100.47, 96.75],
}
df = pd.DataFrame(data)

columnDefs = [
    {
        "headerName": "Stock Ticker",
        "field": "ticker",
        "cellRenderer": "CustomTooltip"

    },
    {
        "headerName": "Company",
        "field": "company",
    },
    {
        "headerName": "Last Close Price",
        "field": "price",
        "valueFormatter": {"function": """d3.format("($,.2f")(params.value)"""},
        "editable": True,
    },
]


grid = dag.AgGrid(
    id="tooltip-simple-example",
    columnDefs=columnDefs,
    rowData=df.to_dict("records"),
    columnSize="sizeToFit",
    defaultColDef={"editable": False},
)


app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])

app.layout = html.Div(
    [dcc.Markdown("Example of custom tooltip"), grid],
    style={"margin": 20},
)

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

Thanks a lot man, it’s an ingenious solution creating an artificial div with id where the dbc Tooltip can target (from what I understand). I tried the following and while it shows the correct text under each column, the styling of the tooltip seems to be different from what I’d expect (dark background with white text, at the moment it’s just text with a transparent background).

dagcomponentfuncs.CustomTooltip = function (props) {
if (props.rowIndex === undefined) {
return React.createElement(
‘div’,
{},
[React.createElement(
window.dash_bootstrap_components.Tooltip,
{target: 'ticker_{props.value}',placement: 'top'}, props.value), React.createElement( "div", { id: `ticker_{props.value}`,
},
props.value
)])
;}
};

1 Like

Nice example @jinnyzor

This one would be a good example for the dag-docs too. Just need to make sure the id and the target are using unique ids :slight_smile:

2 Likes

Make sure you are importing the dbc stylesheet in the external_stylesheets. :slight_smile:

Hi @jinnyzor,

Sorry to bother you again, when I run your example app, the tooltip clearly works (with the right format etc.). However, when I modify your example app as follows, the tooltip is not showing the way it’s intended (and it is similiar to how it showed on my app). Would you have a look please?

app.py

import dash_ag_grid as dag
from dash import Dash, html, dcc
import pandas as pd
import dash_bootstrap_components as dbc

data = {
    "ticker": ["AAPL", "MSFT", "AMZN", "GOOGL"],
    "company": ["Apple", "Microsoft", "Amazon", "Alphabet"],
    "price": [154.99, 268.65, 100.47, 96.75],
}
df = pd.DataFrame(data)

columnDefs = [
    {
        "headerName": "Stock Ticker",
        "field": "ticker",
        'headerTooltip': "This is stock ticket"

    },
    {
        "headerName": "Company",
        "field": "company",
        'headerTooltip': "This is Company name"
    },
    {
        "headerName": "Last Close Price",
        "field": "price",
        'headerTooltip': "This is last close price",
        "valueFormatter": {"function": """d3.format("($,.2f")(params.value)"""},
        "editable": True,
    },
]


grid = dag.AgGrid(
    id="tooltip-simple-example",
    columnDefs=columnDefs,
    rowData=df.to_dict("records"),
    columnSize="sizeToFit",
    dashGridOptions = {'pagination':True,"tooltipShowDelay": 0},
    defaultColDef={"editable": False,"tooltipComponent": "CustomTooltip"},
)


app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])

app.layout = html.Div(
    [dcc.Markdown("Example of custom tooltip"), grid],
    style={"margin": 20},
)

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

js file


var dagcomponentfuncs = window.dashAgGridComponentFunctions = window.dashAgGridComponentFunctions || {};


dagcomponentfuncs.CustomTooltip = function (props) {
    
    if (props.rowIndex === undefined) {
    return React.createElement('div',{},[React.createElement(
        window.dash_bootstrap_components.Tooltip,
        {
            target: `ticker_${props.value}`,
            placement: 'bottom'
        },
        props.value
    ),
    React.createElement(
        "div",
        {
            id: `ticker_${props.value}`,
        },
        props.value
    )])
};
};

Hello @kcamlegin,

The defaultColDef needs to have cellRenderer not tooltipComponent. What we made was the component that has a div and the tooltip targeting the div. :grin:

Thanks @jinnyzor, I changed the tooltipComponent in defaultColDef to cellRenderer but it throws an error, then I tried changing the headerToolTip in Column def to cellRenderer too, but the tooltip didn’t show. Feeling a bit dumb, but would you mind to amend my code directly please?

Sure, you need to adjust your tooltip component as such:

dagcomponentfuncs.CustomTooltip = function (props) {
    if (typeof props.rowIndex !== 'undefined') {
        return React.createElement('div',{},[React.createElement(
            window.dash_bootstrap_components.Tooltip,
            {
                target: `ticker_${props.value}`,
                placement: 'bottom'
            },
            props.value
        ),
        React.createElement(
            "div",
            {
                id: `ticker_${props.value}`,
            },
            props.value
        )])
    };
    return null;
};
1 Like

Hi @jinnyzor , in your code you wrote props.rowIndex !== ‘undefined’ but I think I actually want props.rowIndex === ‘undefined’. Sorry if I misunderstood you but I’m targeting the header rather than the rows. For the rest of the js code, it’s very similar to the code I posted previously. The reason I include headertooltip initially, I was trying to mimic the example on this page JavaScript Data Grid: Tooltip Component (ag-grid.com), under “Header Tooltip with Custom Tooltip”, but this is not in Dash and I fail to replicate it. Given that we’ve come so far, I’d really like to be able to solve this problem. Would you please help again? :pray:

You want the header to display the text that you are wanting?

That will not be with the tooltip… or the cellRenderer.

Yes @jinnyzor, I’d like the header to display the text thanks.

Here, try this:

dagcomponentfuncs.CustomTooltip = function (props) {
    if (typeof props.rowIndex === 'undefined') {
        return React.createElement('div',{},[React.createElement(
            window.dash_bootstrap_components.Tooltip,
            {
                target: `ticker_${props.value}`,
                placement: 'bottom',
                is_open: true,
            },
            props.value
        ),
        React.createElement(
            "div",
            {
                id: `ticker_${props.value}`,
                style: {height: '0px'}
            },
        )])
    };
    return null;
};

Still kinda glitchy, but seems to work. :stuck_out_tongue: