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

AgGrid Dash表格行颜色渐变不显示问题求助

Dash AgGrid行颜色渐变失效问题排查

问题描述

需求:在Dash框架的AgGrid表格中,基于下拉框筛选后的数据,根据Raised to Date与Years in Operation的合计值为行添加颜色渐变(合计值越高,蓝色越深)。但运行代码后表格未显示任何颜色效果。

原代码

import dash
from dash import dcc, html, Input, Output
import dash_ag_grid as dag
import pandas as pd
import numpy as np

# Example data for the DataFrame 'df'
data = {
    "Company name": ["Company {}".format(i) for i in range(1, n_rows + 1)],
    "Years in Operation": np.random.randint(1, 20, n_rows),
    "Raised to Date": np.random.uniform(1, 100, n_rows).round(2),
    "Product": np.random.choice(["Product A", "Product B", "Product C"], n_rows),
    "Bucket": np.random.choice(["Bucket 1", "Bucket 2", "Bucket 3"], n_rows),
}

df = pd.DataFrame(data)

# Initialize the Dash app
app = dash.Dash(__name__)

# Define the layout
app = dash.Dash(__name__)

# Define the layout
app.layout = html.Div([
    html.H1("Valuation Table"),
    dcc.Dropdown(id='product-dropdown', options=[{'label': 'Product A', 'value': 'Product A'}, {'label': 'Product B', 'value': 'Product B'}], value='Product A'),
    dcc.Dropdown(id='bucket-dropdown', options=[{'label': 'All', 'value': 'All'}, {'label': 'Bucket 1', 'value': 'Bucket 1'}, {'label': 'Bucket 2', 'value': 'Bucket 2'}], value='All'),
    dag.AgGrid(
        id='valuation-table',
        columnDefs=[
            {"headerName": "Company Name", "field": "Company name"},
            {"headerName": "Years in Operation (yr)", "field": "Years in Operation"},
            {"headerName": "Raised to Date ($m)", "field": "Raised to Date"},
            {"headerName": "Product", "field": "Product"},
            {"headerName": "Bucket", "field": "Bucket"},
        ],
        style={'height': '400px', 'width': '100%'},
    ),
    html.Div(id='table-heading')
])

# Callback to update the ag-Grid table
@app.callback(
    [Output('valuation-table', 'rowData'),
     Output('table-heading', 'children')],
    [Input('product-dropdown', 'value'),
     Input('bucket-dropdown', 'value')]
)
def update_table(selected_product, selected_bucket):
    if selected_bucket == 'All':
        filtered_df = df[df['Product'] == selected_product]
    else:
        filtered_df = df[(df['Bucket'] == selected_bucket) & (df['Product'] == selected_product)]

    # Calculate a combined value for color gradient
    filtered_df['Combined Value'] = filtered_df['Raised to Date'] + filtered_df['Years in Operation']
    max_combined_value = filtered_df['Combined Value'].max()

    # Preprocess the DataFrame to include HTML style tags in the cell values
    for col in filtered_df.columns:
        if col != 'Combined Value':
            filtered_df[col] = filtered_df.apply(lambda row: f'<div style="background-color: rgba(0, 123, 255, {row["Combined Value"]/max_combined_value});">{row[col]}</div>', axis=1)

    # Create rowData for ag-Grid
    row_data = filtered_df.to_dict('records')

    return row_data, html.Div(f"Filtered by Product: {selected_product}, Bucket: {selected_bucket}")

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

问题原因

  1. HTML解析未开启:AgGrid默认不会解析单元格中的HTML内容,即使给单元格套了<div>加样式,也只会显示纯文本,不会渲染样式。
  2. 实现方式错误:修改单元格内容为HTML是低效且不符合AgGrid设计逻辑的方式,AgGrid提供了专门的样式回调API来设置行/单元格样式。
  3. 未定义变量:代码中n_rows未赋值,运行时会直接抛出NameError,导致程序无法正常启动。

修复方案

使用AgGrid官方推荐的getRowStyle客户端回调函数来实现整行颜色渐变,同时修正变量未定义的问题:

修复后的完整代码

import dash
from dash import dcc, html, Input, Output
import dash_ag_grid as dag
import pandas as pd
import numpy as np

# 定义行数,避免NameError
n_rows = 20

# Example data for the DataFrame 'df'
data = {
    "Company name": ["Company {}".format(i) for i in range(1, n_rows + 1)],
    "Years in Operation": np.random.randint(1, 20, n_rows),
    "Raised to Date": np.random.uniform(1, 100, n_rows).round(2),
    "Product": np.random.choice(["Product A", "Product B", "Product C"], n_rows),
    "Bucket": np.random.choice(["Bucket 1", "Bucket 2", "Bucket 3"], n_rows),
}

df = pd.DataFrame(data)

# Initialize the Dash app
app = dash.Dash(__name__)

# Define the layout
app.layout = html.Div([
    html.H1("Valuation Table"),
    dcc.Dropdown(
        id='product-dropdown', 
        options=[{'label': p, 'value': p} for p in df['Product'].unique()],
        value='Product A'
    ),
    dcc.Dropdown(
        id='bucket-dropdown', 
        options=[{'label': 'All', 'value': 'All'}] + [{'label': b, 'value': b} for b in df['Bucket'].unique()],
        value='All'
    ),
    dag.AgGrid(
        id='valuation-table',
        columnDefs=[
            {"headerName": "Company Name", "field": "Company name"},
            {"headerName": "Years in Operation (yr)", "field": "Years in Operation"},
            {"headerName": "Raised to Date ($m)", "field": "Raised to Date"},
            {"headerName": "Product", "field": "Product"},
            {"headerName": "Bucket", "field": "Bucket"},
        ],
        # 开启客户端行样式回调,根据Combined Value计算背景色
        getRowStyle={
            "function": """
                function(params) {
                    const maxVal = params.api.getRowModel().rowsToDisplay.reduce((max, row) => {
                        return row.data['Combined Value'] > max ? row.data['Combined Value'] : max;
                    }, 0);
                    const opacity = params.data['Combined Value'] / maxVal;
                    return { backgroundColor: `rgba(0, 123, 255, ${opacity})` };
                }
            """
        },
        style={'height': '400px', 'width': '100%'},
        rowData=[],
    ),
    html.Div(id='table-heading')
])

# Callback to update the ag-Grid table
@app.callback(
    [Output('valuation-table', 'rowData'),
     Output('table-heading', 'children')],
    [Input('product-dropdown', 'value'),
     Input('bucket-dropdown', 'value')]
)
def update_table(selected_product, selected_bucket):
    if selected_bucket == 'All':
        filtered_df = df[df['Product'] == selected_product].copy()
    else:
        filtered_df = df[(df['Bucket'] == selected_bucket) & (df['Product'] == selected_product)].copy()

    # 计算合计值,保留在rowData中供客户端回调使用
    filtered_df['Combined Value'] = filtered_df['Raised to Date'] + filtered_df['Years in Operation']

    # 直接返回原始数据,不修改单元格内容
    row_data = filtered_df.to_dict('records')

    return row_data, html.Div(f"Filtered by Product: {selected_product}, Bucket: {selected_bucket}")

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

关键修改点

  1. 定义n_rows:赋值为20,解决变量未定义的报错。
  2. 使用getRowStyle客户端回调:通过JS函数在客户端计算每行的背景色,无需修改单元格内容,符合AgGrid设计逻辑。
  3. 保留原始数据:回调仅返回过滤后的数据及新增的Combined Value字段,不修改单元格的原始值。
  4. 动态生成下拉选项:从DataFrame中动态获取Product和Bucket的唯一值,避免硬编码。

内容的提问来源于stack exchange,提问作者user2940774

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 13:19:51