You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)

关键说明

  1. 监听derived_virtual_data:该属性实时返回DataTable当前显示的所有数据(包含筛选、分页、排序后的结果)。
  2. 动态生成tooltip_data:回调函数根据当前显示的数据重新生成tooltip,确保tooltip内容与单元格显示内容一致。
  3. 修正拼写错误:原始代码中style_table里的maegin-top改为margin-top,避免样式失效。

内容的提问来源于stack exchange,提问作者Lucas Brecht Fernandes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 01:54:56