0
votes

I am trying to create tooltip for a dash data_table using callback. But my multiple attempts are unsuccessful.

I have seen examples where tooltip is create by reading a csv from a path. But in my case dataframe is created within the callback function and returned after clicking a submit button. Below is the code I am using

display_cols=["col1","col2","col3","col4"]
columns_property=[{"name": i, "id": i, "deletable": False, "selectable": True, "renamable":True, "hideable":True} for i in display_cols]
dash_table.DataTable(id="table",
                columns=columns_property,data=[],fill_width=True,
                           export_columns="all",export_format="xlsx", sort_action="native",is_focused=True,
                              sort_mode="multi",export_headers ="names",editable=True,tooltip_data=tooltip,## Tootlip is returned from callback as options
                              style_cell={'textAlign': 'left','border': '1px solid grey', 
                                          'whiteSpace':'normal','height':'auto'},
                              style_header={'backgroundColor': 'white','fontWeight': 'bold',
                                            'border': '1px solid black'},
                              style_table={'fontFamily': 'Open Sans',
                                      'textAlign': 'right',
                                      'whiteSpace': 'no-wrap',                                                         
                                      'overflowX': 'scroll',
                                      'minWidth': '100%',
                                      'height': '600px', 
                                      'overflowY': 'scroll'})



@app.callback([Output('table', 'data'),Output("tooltip", "options")   ],        
            
        [Input('submit3', 'n_clicks')],                
        [
        State('input1', 'value'),
        State('input2', 'value')
        ]
)
def update_output(clicked, input1, input2):
if clicked:        
    input_file=input1
    model_path=input2

    """ Some Code for Generatng DF"""
              
    df=df[["col1","col2","col3","col4"]] 
    
    tooltip_data= [{c:{'type': 'text', 'value': f'{r},{c}'} for c in df.columns} for r in df[df.columns].values]
    
return list(df.to_dict("index").values()), tooltip_data
1

1 Answers

0
votes

So if when you have a question, it is helpful if the code you provide can be run on its own. Looks like the code you provided was part of a larger project and was missing many required calls and boilerplate type stuff to work.

By making your code into a runable Dash app, I may have fixed issues inadvertently. Also, I find that having each function argument to dash_table.DataTable() on its own line makes it easier to read, troubleshoot, and verify. As there are about a bazillion arguments, it can get pretty crazy.

I've found the Dash DataTable documentation to be pretty good. I recommend reading through this to see various ways to use and setup tooltips:

https://dash.plotly.com/datatable/tooltips

You've provided a use case where the tooltips are dependent on a callback. Callbacks can be complicated as they are triggered off a change in the page (changing typically meaning input from the user). Callbacks are run on initial app start up and then every time the specified input changes.

Although callbacks are run on app start, you cannot have the output of the callback listed in the object definition. So, this portion:

dash_table.DataTable(#...
tooltip_data=tooltip,## Tootlip is returned from callback as options
#...

Results in a syntax error as tooltip is not defined. The callback configuration will specify where the callback return value(s) go. In this case you have no tooltips to start with, so the dash_table.DataTabl() should not have the argument specified.

Here's a version of your code tweaked to run and show tooltips.

import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import pandas as pd
import numpy as np
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output, State
import dash_table

app = dash.Dash(__name__)

display_cols=["col1","col2","col3","col4"]
columns_property=[{"name": i, "id": i, "deletable": False, "selectable": True, "renamable":True, "hideable":True} for i in display_cols]
app.layout = html.Div(children=[
    html.Div(
        dcc.Input(
            id="submit3",
            type='number'
        )
    ),
    dash_table.DataTable(id="table",
                         columns=columns_property,
                         data=[],
                         fill_width=True,
                         export_columns="all",
                         export_format="xlsx",
                         sort_action="native",
                         is_focused=True,
                         sort_mode="multi",
                         export_headers ="names",
                         editable=True,
                         style_cell={'textAlign': 'left','border': '1px solid grey', 
                                     'whiteSpace':'normal','height':'auto'},
                         style_header={'backgroundColor': 'white','fontWeight': 'bold',
                                       'border': '1px solid black'},
                         style_table={'fontFamily': 'Open Sans',
                                      'textAlign': 'right',
                                      'whiteSpace': 'no-wrap',
                                      'overflowX': 'scroll',
                                      'minWidth': '100%',
                                      'height': '600px',
                                      'overflowY': 'scroll'})
])

@app.callback([Output('table', 'data'),
               Output("table", "tooltip_data")],
              [Input('submit3', 'value')]
)
def update_output(input1):
    """ Some Code for Generatng DF"""
    df=pd.DataFrame(np.random.randint(0,10,size=(10, 4)), columns=['col1', 'col2', 'col3', 'col4'])
    
    # tooltips
    tooltip_data= [{c:{'type': 'text', 'value': f'{r},{c}'} for c in df.columns} for r in df[df.columns].values]
    
    return list(df.to_dict("index").values()), tooltip_data

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