Dash DataTable筛选后tooltip显示原始数据问题求助
Dash DataTable原生筛选后Tooltip显示原始数据的问题
问题现象
开发的Dash应用中,DataTable整体功能正常,但使用原生筛选(filter_action='native')后,tooltip显示的是筛选前的原始数据,而非当前单元格的实际数据。例如:
- 未筛选时,鼠标悬停在某列第一行,tooltip显示与单元格一致的“Acima de 120 dias”;
- 筛选后,该位置单元格变为“Acima de 90 dias”,但tooltip仍显示“Acima de 120 dias”。
数据样例
dff={'Primary Value': {0: 250025.0, 1: 25.0, 2: 25.0, 3: 100.0, 4: 100.0, 5: 0.0, 6: 0.0, 7: 0.0, 8: 0.0, 9: 0.0}, 'FarolAging': {0: 'vermelho', 1: 'vermelho', 2: 'vermelho', 3: 'vermelho', 4: 'vermelho', 5: 'vermelho', 6: 'vermelho', 7: 'vermelho', 8: 'vermelho', 9: 'vermelho'}, 'Contrato': {0: '703', 1: '106', 2: '101', 3: '101', 4: '1011', 5: '102', 6: '106', 7: '102', 8: '102', 9: '1020'}, 'Dias Pendentes': {0: 'Acima de 120 dias', 1: 'Acima de 120 dias', 2: 'Acima de 120 dias', 3: 'Acima de 120 dias', 4: 'Acima de 120 dias', 5: 'Acima de 120 dias', 6: 'Acima de 120 dias', 7: 'Acima de 120 dias', 8: 'Acima de 120 dias', 9: 'Acima de 120 dias'}, 'Produto': {0: 'Financeiro', 1: 'Financeiro', 2: 'Financeiro', 3: 'Financeiro', 4: 'Financeiro', 5: 'Credito', 6: 'Credito', 7: 'Financeiro', 8: 'Financeiro', 9: 'Credito'}, 'Cliente': {0: 'CAMERA', 1: 'CAMERA', 2: 'CAMERA', 3: 'CAMERA', 4: 'CAMERA', 5: 'SANTOS', 6: 'LBB', 7: 'MAURO', 8: 'MAURO', 9: 'MAURO'}, 'Cliente Grupo': {0: 'DARCI CAMERA', 1: 'CAMERA', 2: 'CAMERA', 3: 'CAMERA', 4: 'CAMERA', 5: 'GENERICO', 6: 'GENERICO', 7: 'GENERICO', 8: 'GENERICO', 9: 'GENERICO'}, 'XXX': {0: 953, 1: 953, 2: 953, 3: 953, 4: 953, 5: 168, 6: 107, 7: 888, 8: 888, 9: 888}, 'Abertura': {0: '25/02/2021', 1: '01/04/2019', 2: '22/10/2019', 3: '23/09/2019', 4: '20/09/2019', 5: '13/06/2022', 6: '12/07/2022', 7: '26/09/2022', 8: '26/09/2022', 9: '26/09/2022'}, 'Tipo': {0: 'Tipo 1 – 4790', 1: 'Tipo 1', 2: 'Tipo 2', 3: 'Tipo 3', 4: 'Tipo 3', 5: 'Tipo 4', 6: 'Tipo 4', 7: 'Tipo 5', 8: 'Tipo 4', 9: 'Tipo 4'}, 'Descrição Garantia': {0: 'Sem Descrição', 1: 'Sem Descrição', 2: 'Sem Descrição', 3: 'Sem Descrição', 4: 'Sem Descrição', 5: 'Sem Descrição', 6: 'Sem Descrição', 7: 'Sem Descrição', 8: 'Sem Descrição', 9: 'Sem Descrição'}, 'Observacao': {0: 'Sem Observação', 1: 'Sem observação', 2: 'Sem observação', 3: 'Sem observação', 4: 'Sem observação', 5: 'Sem Observações', 6: 'Sem observação', 7: 'Sem observação', 8: 'Cobrado', 9: 'Aguardando'}, 'Data de Vencimento': {0: '01/01/9999', 1: '01/04/2020', 2: '30/03/2020', 3: '30/04/2020', 4: '30/04/2020', 5: '11/06/2027', 6: '11/07/2029', 7: '21/09/2023', 8: '27/09/2027', 9: '27/09/2027'}, 'Data': {0: 'unknown', 1: '19/03/2021', 2: '30/03/2020', 3: '15/04/2020', 4: '23/09/2019', 5: 'unknown', 6: 'unknown', 7: 'unknown', 8: 'unknown', 9: 'unknown'}, 'Início': {0: '25/02/2021', 1: '01/04/2019', 2: '22/10/2019', 3: '23/09/2019', 4: '20/09/2019', 5: '13/06/2022', 6: '12/07/2022', 7: '26/09/2022', 8: '26/09/2022', 9: '26/09/2022'}, 'Data Fim': {0: '25/03/2021', 1: '10/04/2019', 2: '26/12/2019', 3: '26/11/2019', 4: '25/11/2019', 5: '16/08/2022', 6: '14/09/2022', 7: '01/12/2022', 8: '01/12/2022', 9: '01/12/2022'}, 'Moeda': {0: 'BRL', 1: 'USD', 2: 'BRL', 3: 'BRL', 4: 'BRL', 5: 'BRL', 6: 'USD', 7: 'BRL', 8: 'BRL', 9: 'BRL'}, 'Valor': {0: '0,00', 1: '4.500', 2: '2.350', 3: '19.450.00', 4: '20.917', 5: '25.000', 6: '500', 7: '12.000', 8: '30.000', 9: '32.340'}, 'Rating': {0: 'B', 1: 'A', 2: 'C', 3: 'F', 4: 'G', 5: 'A', 6: 'B', 7: 'A', 8: 'C', 9: 'A'}, 'Nível': {0: 'A', 1: 'E', 2: 'A', 3: 'A', 4: 'A', 5: 'A', 6: 'A', 7: 'A', 8: 'A', 9: 'A'}, 'Valor2': {0: 'unknown', 1: 'unknown', 2: 'unknown', 3: 'unknown', 4: 'unknown', 5: '12000', 6: '2100', 7: '2030', 8: '2520', 9: '2520'}, 'Caracteristicas': {0: 'Ativas', 1: 'Ativas', 2: 'Ativas', 3: 'Ativas', 4: 'Ativas', 5: 'Ativas', 6: 'Ativas', 7: 'Ativas', 8: 'Ativas', 9: 'Ativas'}, 'Officer': {0: 'SILVA', 1: 'SILVA', 2: 'SILVA', 3: 'SILVA', 4: 'SILVA', 5: 'RENATO', 6: 'JOAO', 7: 'MATHEUS', 8: 'MATHEUS ', 9: 'MATHEUS'}, 'Segmento': {0: 'Clients 01', 1: 'Clients 01', 2: 'Clients 01', 3: 'Clients 01', 4: 'Clients 01', 5: 'Clients 01', 6: 'Clients 01', 7: 'Clients 01', 8: 'Clients 01', 9: 'Clients 01'}, 'Pré/Pós': {0: 'Pré', 1: 'Pré', 2: 'Pré', 3: 'Pré', 4: 'Pré', 5: 'Pré', 6: 'Pré', 7: 'Pré', 8: 'Pré', 9: 'Pré'}, 'Coordenador': {0: 'Coordenação Diversa', 1: 'Coordenação Diversa', 2: 'Coordenação Diversa', 3: 'Coordenação Diversa', 4: 'Coordenação Diversa', 5: 'Coordenação Clientes 01', 6: 'Coordenação Clientes 01', 7: 'Coordenação Clientes 01', 8: 'Coordenação Clientes 01', 9: 'Coordenação Clientes 01'}, 'Analista': {0: 'Analistas Diversos', 1: 'Analistas Diversos', 2: 'Analistas Diversos', 3: 'Analistas Diversos', 4: 'Analistas Diversos', 5: 'Thai', 6: 'Amorim', 7: 'Motta', 8: ' Motta', 9: 'Motta'}}
原始代码
app = Dash(__name__, external_stylesheets=external_stylesheets, prevent_initial_callbacks=True) app.layout = html.Div(children=[ html.Div([ html.Div([dash_table.DataTable( id="tablef", style_data={ 'maxWidth': 710, 'textOverflow': 'ellipsis', }, style_table={ 'overflowX': 'scroll', "maegin-top": "15px", }, columns=[{"name": i, "id": i, 'deletable': True} for i in dff.columns], data=dff.to_dict('records'), filter_action='native', style_cell={ 'textAlign': 'left' }, tooltip_data=[{ column: {'value': str(value), 'type': 'markdown'} for column, value in row.items() } for row in dff.to_dict('records')], tooltip_delay=0, tooltip_duration=None, page_size=25, ), ], className='col-md-10'), ], className='row') ])
问题原因
tooltip_data是基于原始数据集dff静态生成的,当使用原生筛选后,DataTable仅在前端渲染筛选后的数据,但tooltip仍然绑定原始行的对应数据,未随筛选结果动态更新。
解决方案
通过Dash回调监听DataTable的derived_virtual_data属性(该属性存储筛选、分页后的当前显示数据),动态生成对应的tooltip_data。
修改后的完整代码
import dash from dash import html, dash_table, Input, Output, State import pandas as pd # 假设dff是读取Excel后的DataFrame dff = pd.DataFrame(dff) external_stylesheets = [] app = Dash(__name__, external_stylesheets=external_stylesheets) app.layout = html.Div(children=[ html.Div([ html.Div([dash_table.DataTable( id="tablef", style_data={ 'maxWidth': 710, 'textOverflow': 'ellipsis', }, style_table={ 'overflowX': 'scroll', "margin-top": "15px", # 修正拼写错误maegin→margin }, columns=[{"name": i, "id": i, 'deletable': True} for i in dff.columns], data=dff.to_dict('records'), filter_action='native', style_cell={ 'textAlign': 'left' }, # 初始化tooltip_data tooltip_data=[{ column: {'value': str(value), 'type': 'markdown'} for column, value in row.items() } for row in dff.to_dict('records')], tooltip_delay=0, tooltip_duration=None, page_size=25, ), ], className='col-md-10'), ], className='row') ]) @app.callback( Output('tablef', 'tooltip_data'), Input('tablef', 'derived_virtual_data'), prevent_initial_call=False ) def update_tooltip_data(derived_data): if derived_data is None: # 无筛选数据时返回原始tooltip return [{ column: {'value': str(value), 'type': 'markdown'} for column, value in row.items() } for row in dff.to_dict('records')] # 根据当前显示数据生成tooltip return [{ column: {'value': str(value), 'type': 'markdown'} for column, value in row.items() } for row in derived_data] if __name__ == '__main__': app.run_server(debug=True)
关键说明
- 监听
derived_virtual_data:该属性实时返回DataTable当前显示的所有数据(包含筛选、分页、排序后的结果)。 - 动态生成tooltip_data:回调函数根据当前显示的数据重新生成tooltip,确保tooltip内容与单元格显示内容一致。
- 修正拼写错误:原始代码中
style_table里的maegin-top改为margin-top,避免样式失效。
内容的提问来源于stack exchange,提问作者Lucas Brecht Fernandes
相关产品推荐
相关产品推荐

