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)
问题原因
- HTML解析未开启:AgGrid默认不会解析单元格中的HTML内容,即使给单元格套了
<div>加样式,也只会显示纯文本,不会渲染样式。 - 实现方式错误:修改单元格内容为HTML是低效且不符合AgGrid设计逻辑的方式,AgGrid提供了专门的样式回调API来设置行/单元格样式。
- 未定义变量:代码中
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)
关键修改点
- 定义
n_rows:赋值为20,解决变量未定义的报错。 - 使用
getRowStyle客户端回调:通过JS函数在客户端计算每行的背景色,无需修改单元格内容,符合AgGrid设计逻辑。 - 保留原始数据:回调仅返回过滤后的数据及新增的
Combined Value字段,不修改单元格的原始值。 - 动态生成下拉选项:从DataFrame中动态获取Product和Bucket的唯一值,避免硬编码。
内容的提问来源于stack exchange,提问作者user2940774
相关产品推荐
相关产品推荐

