I'm trying to preserve values in a dash_table.DataTable after switching between apps in an multi page Dash app. I've tried with both navlinks (example code below), pages (dash 2.5) and tabs. I want to do this using the persistence argument instead of dcc.Store, and with navlinks/pages instead of tabs.
It seems refreshing the page overrides the persistence keyword, even when set to 'session' or 'local', as using tabs fixes this issue (tabs does not refresh page). I've also tried dcc.Location with refresh=False without success. I've made a small example code to display my issue. From my print statements you can also observe the data beeing reset to 'None' after switching between links/pages.
import pandas as pd
import numpy as np
from dash import Dash, callback, html, dcc, dash_table, Input, Output, dash_table, callback_context as ctx
import dash_bootstrap_components as dbc
df = pd.DataFrame({'test1':np.zeros(3), 'test2':np.zeros(3)})
def get_data():
return df
app = Dash(external_stylesheets=[dbc.themes.BOOTSTRAP], suppress_callback_exceptions= True)
app.layout = dbc.Container([
dcc.Location(id = 'url', refresh = False),
dbc.Row(
dbc.Navbar(
dbc.Nav(children=[
dbc.NavItem(dbc.NavLink("Main", active='exact', external_link=False, href='/'), id = 'main'),
dbc.NavItem(dbc.NavLink("A link", active = 'exact', external_link=False, href="/link"), id = 'alink')
])
)
),
html.Div(id = 'link')
])
main = html.Div([
dbc.Row(
dbc.Col([
dbc.Button("test1 +1", id='btn1', className="me-2", n_clicks = 0),
dbc.Button("test2 +1", id='btn2', className="me-2", n_clicks = 0)
])
),
dbc.Row([
dbc.Col(
dash_table.DataTable(columns = [{'name': x, 'id':x} for x in get_data().columns],
id = 'table',
persistence = True,
persisted_props = ['data'],
persistence_type = 'session')
)
])
])
@app.callback(
Output('link', 'children'),
Input('url', 'pathname')
)
def render_page(path):
print(path)
if path != '/':
layout = html.Div(
dbc.Row(
html.H5(path)
)
)
else:
layout = main
return layout
@app.callback(
Output('table', 'data'),
[
Input('table', 'data'),
Input("btn1", "n_clicks"),
Input("btn2", "n_clicks")
]
)
def render_table(data,b1,b2):
print("Data: ", data)
if data == None:
return get_data().to_dict('records')
df = pd.DataFrame(data)
button_id = ctx.triggered[0]["prop_id"].split(".")[0]
if button_id == 'btn1':
df['test1'] += 1
elif button_id == 'btn2':
df['test2'] += 1
return df.to_dict('records')
app.run_server()