I have one select widget on the sidebar to control what is displayed in main section.
When going through the options, the main content changes accordingly. However, when I refresh the dashboard, the select value resets to the first value. Is it possible to preserve the selection on refresh?
Here is a demo code to showcase the situation:
import panel as pn
import pandas as pd
pn.extension("tabulator")
def create_report(stage):
demo_df = pd.DataFrame(
data={
'Steps': [f'Step {stage}{i + 1}' for i in range(10)],
'Actions': [f'Perform step {stage}{i + 1}' for i in range(10)],
'Info 1': [f'Info 1 regarding step {stage}{i + 1}' for i in range(10)],
'Info 2': [f'Info 2 regarding step {stage}{i + 1}' for i in range(10)],
'Info 3': [f'Info 3 regarding step {stage}{i + 1}' for i in range(10)],
'Info 4': [f'Info 4 regarding step {stage}{i + 1}' for i in range(10)],
'Info 5': [f'Info 5 regarding step {stage}{i + 1}' for i in range(10)],
'Info 6': [f'Info 6 regarding step {stage}{i + 1}' for i in range(10)],
},
index=[i + 1 for i in range(10)]
)
df_table = pn.widgets.Tabulator(
demo_df,
layout='fit_data_table',
header_align='center',
text_align='center',
selectable=False,
theme='simple',
show_index=False,
)
stage_report = pn.Column(
f'## Report stage {stage}',
df_table
)
return stage_report
select = pn.widgets.Select(name='Select stage', options=['A', 'B', 'C', 'D'])
report = pn.bind(create_report, stage=select)
template = pn.template.FastListTemplate(
site="Staging reports",
title="",
theme_toggle=False,
header_background="rgb(95,158,209)",
sidebar=[select],
main=[report]
)
template.servable()
For instance if I have selected stage “C” on refresh it gets to stage “A”.
If you want to persist state across sessions (refresh) you need to store the state somewhere. Panel provides a really elegant and beautiful solution for that sync location. I just it
Sync location will sync the state of your select widget with the urlarguments if you add pn.state.location.sync(select, {'value': 'stage'})
import panel as pn
import pandas as pd
pn.extension("tabulator")
def create_report(stage):
demo_df = pd.DataFrame(
data={
'Steps': [f'Step {stage}{i + 1}' for i in range(10)],
'Actions': [f'Perform step {stage}{i + 1}' for i in range(10)],
'Info 1': [f'Info 1 regarding step {stage}{i + 1}' for i in range(10)],
'Info 2': [f'Info 2 regarding step {stage}{i + 1}' for i in range(10)],
'Info 3': [f'Info 3 regarding step {stage}{i + 1}' for i in range(10)],
'Info 4': [f'Info 4 regarding step {stage}{i + 1}' for i in range(10)],
'Info 5': [f'Info 5 regarding step {stage}{i + 1}' for i in range(10)],
'Info 6': [f'Info 6 regarding step {stage}{i + 1}' for i in range(10)],
},
index=[i + 1 for i in range(10)]
)
df_table = pn.widgets.Tabulator(
demo_df,
layout='fit_data_table',
header_align='center',
text_align='center',
selectable=False,
theme='simple',
show_index=False,
)
stage_report = pn.Column(
f'## Report stage {stage}',
df_table
)
return stage_report
select = pn.widgets.Select(name='Select stage', options=['A', 'B', 'C', 'D'])
report = pn.bind(create_report, stage=select)
pn.state.location.sync(select, {'value': 'stage'})
template = pn.template.FastListTemplate(
site="Staging reports",
title="",
theme_toggle=False,
header_background="rgb(95,158,209)",
sidebar=[select],
main=[report]
)
template.servable()
This makes it possible to bookmark the specific state of your app as well as share it with colleagues, customers and friends.
Thank you, @Marc - this worked like a charm.
I wish there would be some section in the documentation for such behavior (unless there is and I missed it).
“How to preserve widgets values/parameters” or something where concrete examples could be added.
@Marc , your help and examples are being very useful across holoviz organization, thank you!
However, the solution you provided here is a bit cumbersome to be used in my case.
My application has about 20-25 variables which define it’s state. Having such a big URL would make it clunky to manage and also a bit abusing the “location” parameters.
The idea I had in mind is quite simple:
User is going through auth (so I have unique ID)
New session is created
The values for the widgets are chosen by the user - which is triggering some rendering of some plots
It also triggers some implementation which allows me to persist choices made by the user somewhere
User leaves application (closing the tab/browser)
Next day user visits the same URL
Application identifies that it’s not the first-time usage and fetching arguments from the last choice made by the user
Application set’s values for the widgets based on saved last session values - which brings user back to the place he/she left it at yesterday.
How would you implement it and is there any way to simplify it using panel functionality?