I would like to create a customized dropdown to filter an HTML table.
The primary goal is to update the hidden state of each row.
However, a single update involves a significant number of requests, leading to slow page updates, particularly when updating all rows.
Does anyone have suggestions for improving performance?
Note: I chose to use html.Table
instead of dash_table
due to specific customization requirements.
import dash
from dash import html, dcc
from dash.dependencies import Input, Output, ALL, State
import pandas as pd
import random
# Sample DataFrame with 99rows
df = pd.DataFrame({
'Name': [f'Person {i%3}' for i in range(99)],
'Age': [25 + random.randint(0,3) for _ in range(99)],
'City': ['City A', 'City B', 'City C'] * 33 # Three unique values repeated
})
# Initialize the Dash app
app = dash.Dash(__name__)
setting_init = {'Name': 'ALL', 'Age': 'ALL', 'City': 'ALL'}
def create_table():
header = [html.Tr([
html.Th([col,
dcc.Dropdown(value=setting_init[col],
options=[{'label': val, 'value': val} for val in df[col].unique().tolist()+['ALL']],
id={'type': 'dropdown', 'col': col})
], style={'border': '1px solid'}) for col in df.columns])]
content = [html.Tr([html.Td(df.iloc[i][col],
style={'border': '1px solid'}) for col in df.columns],
id={'type': 'row', 'row': i}) for i in range(len(df))]
table = html.Table(header + content, style={'border': '1px solid'})
return table
table = create_table()
# Define the layout of the app
app.layout = html.Div([
table,
dcc.Store(id='setting-save', data=setting_init)])
# Callback to update the table based on the selected dropdowns
@app.callback(
Output({'type': 'row', 'row': ALL}, 'hidden'),
Output('setting-save', 'data'),
Input({'type': 'dropdown', 'col': ALL}, 'value'),
State('setting-save', 'data'),
prevent_initial_call = True
)
def filter_table(filter, setting_save):
Name, Age, City = filter[0], filter[1], filter[2]
idx_all = ['Name', 'Age', 'City']
for idx in idx_all:
if eval(idx)!=setting_save[idx]:
idx_change = idx
dic_display = {setting_save[idx_change]: True, eval(idx_change): False} #hide old option and display new option
#setting hidden state
list_hidden = []
idx_check = [idx for idx in idx_all if idx!=idx_change]
if setting_save[idx_change]!='ALL':
if eval(idx_change)!='ALL':
for i in range(99):
if df.iloc[i][idx_change] in dic_display.keys():
list_hidden.append(dic_display[df.iloc[i][idx_change]])
else:
list_hidden.append(dash.no_update)
else:
for i in range(99):
if df.iloc[i][idx_change] in dic_display.keys():
list_hidden.append(dash.no_update)
else:
#check other dropdowns meet setting
flag = False
for idx in idx_check:
if eval(idx)!='ALL' and df.iloc[i][idx]==eval(idx):
list_hidden.append(False)
flag = True
break
if flag == False:
list_hidden.append(dash.no_update)
else: #if previous option is 'ALL'
for i in range(99):
if df.iloc[i][idx_change]==eval(idx_change):
list_hidden.append(dash.no_update)
else:
list_hidden.append(True)
#save new option to record
setting_save[idx_change] = eval(idx_change)
return list_hidden, setting_save
# Run the app
if __name__ == '__main__':
app.run_server(debug=True)