I love Dash, the tabs and the interactive tables! I recently saw the new dcc.Store and I trying to use it in place of hidden divs. However, I have not succeeded yet and it causes the app to grind to halt. I have a multi-tab app, the first tab holds the interactive dash table that is fed by the data from the dcc.Store. The user then selects the issue in the table to view the related chart of the data on the next tab.
I had this working using the hidden div but it seems that I needed a separate hidden div for each DF result (the calculation subroutine spits out several DFs) I am only using the first resulting DF for the interactive table in tab 1. Note, that I run the calculation subroutine beforehand and use the DFs to initially populate the rows of the table in tab1, but I need to be able to update the table when I change configurations of the test calculations as well as with new results from the new data feed each day.
When I run the app now using dcc.Store in Jupyter notebook, the interactive table is not filled, and does not fill even after click the ārun_testsā button and/or select from one of the dropdowns. I do see the data in the Session Storage of Chrome under the Application section of developer mode. First it is populated with the data from the dataframe itself since the modified_timestamp is None, then that is overridden and populated by the data.to_dict() after button is pressed. However, the modified_timestamp does not show in the Session Storage. So the data are there but my app does not seem to be able to read it back. The app does not list any errors related to this tab in the feedback pane
I appreciate any insight.
Here is the portion of my code that is relevant to this.
app.layout = html.Div([
dcc.Store(
id='store_data',
storage_type='session'
),
dcc.Tabs(id="tabs", vertical=False, children=[
dcc.Tab(label='Issues', value='tab1', children=[
html.Div([
html.H1('Issues Failing Test Configuration Criteria',style={
'textAlign': 'left', 'margin': '10px', 'fontFamily': 'Sans-Serif','font-size':16}),
]),
html.Div([
dcc.DatePickerRange(id='issues_date_range',
min_date_allowed=DataDF.index.min(),
max_date_allowed=DataDF.index.max(),
initial_visible_month=DataDF.index.max(),
start_date=DataDF.index.max()-timedelta(days=6), #default to the lastest week of data
end_date=DataDF.index.max(),
updatemode='bothdates')
], style = {'display': 'inline-block', 'width': '30%', 'height': '40', 'vertical-align': 'middle', 'float':'right','position': 'relative'}),
html.Div([
html.Button('Run All Tests', id='run_tests_button', n_clicks=0)
], style = {'display': 'inline-block', 'vertical-align': 'middle', 'float':'right','position': 'relative'}),
html.Div([
dcc.Dropdown(
id='issue_type_dropdown',
options=[
{'label': 'a', 'value': 1},
{'label': 'b', 'value': 2},
{'label': 'c', 'value': 3},
{'label': 'd', 'value': 4}
],
value=1',
#placeholder="Select Issue Type",
multi=False)
], style = {'float': 'left', 'position': 'relative','width': '20%', 'vertical-align': 'middle'}),
html.Div([
dcc.Dropdown(
id='group_dropdown',
options=[
{'label': 'Group#1', 'value': 1},
{'label': 'Group#2', 'value': 2},
{'label': 'Group#3', 'value': 3},
{'label': 'Group#4', 'value': 4}
],
value=1,
#placeholder="Select Group",
multi=False)
], style = {'position': 'relative','width': '20%', 'vertical-align': 'middle'}),
html.Div([
dt.DataTable(
rows=[],
columns=[],
column_widths=[],
editable=False,
row_selectable=True,
filterable=True,
sortable=True,
selected_row_indices=[],
max_rows_in_viewport=9,
id='issues_table'
)
])
]),
### more tabs,etc. Here are the related calllbacks ###
@app.callback( ### this runs the subroutine and sends the resulting DF to store_data
Output('store_data', 'data'),
[Input('run_tests_button', 'n_clicks')],
[State('issues_date_range','start_date'),
State('issues_date_range','end_date')])
def update_issues_table(n_clicks,start,end):
global Issues
if n_clicks==0:
DataDict=Issues.to_dict()
else:
RunTests=AllTests(start,end) #calls subroutine from another notebook that returns multiple DFs, for now I am only trying to send the first DF, hence the [0].
DataDict=RunTests[0].to_dict()
return DataDict
@app.callback( ### this pulls the DF from the store_data, manipulates the DF to pull the rows that apply to the two dropdowns and sends the rows to the interactive table
Output('issues_table', 'rows'),
[Input('issue_type_dropdown', 'value'),
Input('group_dropdown', 'value')],
[State('store_data', 'data'),
State('store_data', 'modified_timestamp')])
def subset_issues_table(issue_type,bldg_group,data,data_timestamp):
if data_timestamp is None:
raise dash.exceptions.PreventUpdate
else:
subset=pd.DataFrame()
StoredIssues=data[0]
### slicing of data based on the two dropdowns to produce the "subset" DF ###
subrows=subset.to_dict('records')
return subrows
Also, when I stop the app and restart it again with the data still in the Session Storage, it yields, āError loading dependenciesā and states in the Chrome Application area āRangeError: Maximum call stack size exceededā.