Black Lives Matter. Please consider donating to Black Girls Code today.

Dash DataTable - Tooltips

Hey,
Is it possible to add a custom tooltip to a cell or headline of the DataTable?

This isn’t possible now. I’d like to make formatting more generic across Dash by allowing you to pass in components inside properties besides children. This would allow you to pass in dash components as header cells, one of which could be a tooltip. Here’s the PR: https://github.com/plotly/dash-table-experiments/pull/11. There is still quite a bit of work to do here.

Thanks to our commercial customers, this is now available in dash-table (https://dash.plot.ly/datatable).

import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_table as table

import pandas as pd
import textwrap

df = pd.read_csv('./datasets/gapminder.csv')

print(dash.__version__)
print(table.__version__)

app = dash.Dash(__name__)
app.scripts.config.serve_locally = True
app.css.config.serve_locally = True

def create_tooltip(cell):
    try:
        num = float(cell)
        return textwrap.dedent(
            '''
            Tooltip for value **{value:+.2f}**.
            | Multiplier | Value |  Percent |
            |-------|-------|---------------|
            | 1     | {value_1:+.2f}     | {value_1:+.2f}% |
            | 2     | {value_2:+.2f}     | {value_2:+.2f}% |
            | 3     | {value_3:+.2f}     | {value_3:+.2f}% |
            '''.format(
                value=num,
                value_1=num,
                value_2=num * 2,
                value_3=num * 3
            )
        )
    except:
        return textwrap.dedent(
            '''
            Tooltip: **{value}**.
            '''.format(value=cell)
        )


app.layout = html.Div([
    table.DataTable(
        columns = [{'name': i, 'id': i} for i in df.columns],
        data=df.to_dict('rows'),
        tooltips={
            col: [
                {
                    'type': 'markdown',
                    'value': create_tooltip(df.loc[i, col])
                }
                for i in range(len(df))
            ]
            for col in df.columns
        }
    )
])

if __name__ == '__main__':
    app.run_server(debug=True)
9 Likes

Coincidentally, I was looking into this just days ago. Upgraded data_table and voila, everything worked as described. Thank you @chriddyp for Dash and everything that comes with it (like these DataTable tooltips)!!!

1 Like

Hi - extremely handy feature. Is there any way to have conditional tooltips only for the headers?

When I try something like the below, it starts counting from the first data row (which is fair choice, but how can I hit the header instead?):

column_conditional_tooltips=[
            {
                'if': {'column_id': "id1", "row_index": 0},
                "value": "My tooltip",
                "type": "text"
            },
        ]

+1 on this, this would be really useful to explain what the columns are.

Hey @chriddyp, thanks for implementing this. Do you have a more recent example? Seems like tooltip has taken the place of tooltips, and I’m having trouble getting a test example with your code.

Here is a stripped-down version that is not working for me:

tooltip={
    'property':'my_column_name',
    'value':'this is a test tooltip' 
}
2 Likes

I also have this problem. Installing dash 0.39 and running the example with ‘tooltips’ works as expected. However, the latest version of Dash doesn’t render any tooltip by using either ‘tooltip’ or ‘tooltip_data’. Anyone figured it out using dash > 1.0.0?

3 Likes

Hi! According to the documentation, you can make it work like this :

Please note however that it will work only for the first row, you need to iterate if you want specific value on the rest of the column.

Otherwise, you can use the tooltip argument:

4 Likes

Many thanks Titi! Works like a charm.

This is not working for me for tooltip. tooltip_data does work Using dash 1.8.0. Anyone have a working example for multiple columns? I must add I’m looking for the tooltip in the column headings. This tooltip does work the data cell, but I’m using tooltip_data for that.

Hello @chriddyp,

I modified your suggestions to work on dash 1.9.1 for my use case:

tooltip_data= {c:
        [{
            'type': 'text',
            'value': f'{r},{c}'
        } for r in df[df.columns[0]].values]
     for c in df.columns
}

As you can probably see, I am trying to display my row,column names as the tooltips for all elements in the table. However, I get the following error on my web browser:

Can you help please?

Hi @wvw, have you found a way around yet?

@tbillah - The error message looks like it’s telling you that the shape of the data you are passing isn’t right. It’s expecting an array, you passed a dict (object). Try

tooltip_data = [
    {'type': 'text', 'value': f{r},{c}' for r in df[df.columns[0]].values]} 
    for c in df.columns
] 

Do you have any suggestions on how we could make that error message clearer?

Hi @chriddyp, I think the error message is okay. Perhaps I should have mentioned, I also tried with square brackets around learning from the error. However, I tried again with what you provided and ran into the following:

By the way, I had to adjust your suggestion by inserting one missing square bracket:

        tooltip_data = [
            {'type': 'text', 'value': [f'{r},{c}' for r in df[df.columns[0]].values]}
            for c in df.columns
        ]

Hi @chriddyp, here is a better example:

It appears that I had to interchange row and column order:

tooltip_data= [{c:
        {
            'type': 'text',
            'value': f'{r},{c}'
        } for c in df.columns
} for r in df[df.columns[0]].values]

I realized that tooltip_data expects a list of dictionaries where each item in the dictionary is another dictionary for each column.

1 Like

Hello @chriddyp,
Here is my code, I am trying to read a pandas data frame and upload it into dash data table.
I tried to use the Ellipses and Tooltip functionality but somehow tooltip is not working for me.
Please help me in running this (Variable Table is a pandas data frame)

import dash
import dash.dependencies as dd
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
import dash_bootstrap_components as dbc
import dash_table
import pandas as pd

from navbar import Navbar
nav = Navbar()
from app import app

import fig_prep_code

df = pd.DataFrame()

output = dbc.Container(children =[
dbc.Row([
dbc.Col(html.H3(“User Emails”),width=10),
dbc.Col(dbc.Button(“Click Me”,id=‘Emails_submit’,outline=True, color=“dark”),align = ‘right’)
],align = ‘center’),
html.Hr(),
dash_table.DataTable(
id=‘table’,
columns = [{‘name’: i, ‘id’: i} for i in df.columns],
data=df.to_dict(‘records’),
page_size=20,
style_cell={
‘overflow’: ‘hidden’,
‘textOverflow’: ‘ellipsis’,
‘textAlign’: ‘left’,
‘maxWidth’: ‘0’,
},

    tooltip_data=[{
            column: {'value': str(value), 'type': 'markdown'}
            for column, value in row.items()
        } for row in df.to_dict('rows')
    ],
    tooltip_duration=None,
    fixed_rows={'headers': True}


)

])

def MAILS():
layout = html.Div([nav,output])
return layout

@app.callback([Output(‘table’, ‘data’),
Output(‘table’, ‘columns’),
Output(‘table’, ‘rows’)],
[
Input(‘Emails_submit’, ‘n_clicks’)],
[
State(‘select_all’, ‘value’),
State(‘folder_picker’, ‘value’),
State(‘employee_picker’, ‘value’),
State(‘search_string’, ‘value’),
State(‘search_options’, ‘value’),
State(‘NSFW’, ‘value’),
State(‘Money’, ‘value’),
State(‘Order’, ‘value’),
State(‘outside_from’, ‘value’),
State(‘outside_to’, ‘value’),
State(‘group_mail’, ‘value’),
State(‘flag_condition’, ‘value’),
State(‘Sentiment’, ‘value’),
State(‘date_picker’, ‘start_date’),
State(‘date_picker’, ‘end_date’)
])
def update_figure_mail(n_clicks,select_all,folder,selected_employee,search_keyword,search_options,NSFW,Money,Order,outside_from,outside_to,group_mail,flag_condition,Sentiment,start_date, end_date):
Table, Year, DOW, Hour,To, Folder,number_emails,chart_from = fig_prep_code.graph(select_all,folder,selected_employee,search_keyword,search_options,NSFW,Money,Order,outside_from,outside_to,group_mail,flag_condition,Sentiment,start_date, end_date)

Table['Comments'] = ''
df = Table

return Table.to_dict('records'), [{"name": i, "id": i} for i in Table.columns], Table.to_dict('rows')