Hello Everyone ,
I am building a dashboard to get “general” data from a database. I would like to make it possible that when a user wants to view more details of a specific entry, he can click on a button and should be redirected to another details page. I use Query Strings on both the first and second page.
The problem now is the following: I cannot get from, for example,
“http://127.0.0.1:8050/PageAlpha?keyA=valueX”
to
“http://127.0.0.1:8050/PageBeta?keyB=valueY”.
I have already tried it with dozens of variants. To better understand my approach I also have a code example.
app.py
from dash import Dash, html, dcc
import dash
app = Dash(
__name__,
use_pages=True,
suppress_callback_exceptions=True
)
app.layout = html.Div([
html.H1('Multi-page app with Dash Pages'),
html.Div(
[
html.Div(
dcc.Link(
f"{page['name']} - {page['path']}", href=page["relative_path"]
)
)
for page in dash.page_registry.values()
]
),
dash.page_container
])
if __name__ == '__main__':
app.run_server(
debug=True,
port=8051,
)
home.py
import urllib
import dash
from dash import html, dcc, callback, Input, Output, State
dash.register_page(__name__, path='/')
def layout(options=False, **other_unknown_query_strings):
return html.Div(
children=[
dcc.Location(id='currentLocation'),
html.H1(children='Page Home'),
html.Button(
id='showFruitsButton',
children='Show Fruits?',
),
html.Div(id='showFruitsRedirectDiv'),
html.Hr(),
html.Div(
children=[
html.P('Select Fruit'),
dcc.RadioItems(id='showOptionsRadioItems'),
html.Button('Show Fruit Details', id='goToFruitDetailsButton')
]
),
html.Div(id='redirectToDetailsDiv')
]
)
# Disable/Enable Buttons Logic
@callback(
Output('showFruitsButton', 'disabled'),
Output('goToFruitDetailsButton', 'disabled'),
Input('currentLocation', 'search'),
prevent_initial_call=False
)
def check_if_button_is_needed(search):
# Convert '?options=True' to '{'options': ['True']}'
param = urllib.parse.parse_qs(urllib.parse.urlparse(search).query)
# This means basically:
# If 'a URL-Parameter Exists':
# 'return this Parameter'
# else:
# 'return False'
showFruitsButton_bool = eval(param['options'][0]) if bool(param) else False
goToFruitDetailsButton_bool = not showFruitsButton_bool
return showFruitsButton_bool, goToFruitDetailsButton_bool
# Set URL Parameter: options
@callback(
Output('showFruitsRedirectDiv', 'children'),
Input('showFruitsButton', 'n_clicks'),
prevent_initial_call=True
)
def show_fruits_redirect(button_click):
return dcc.Location(
id='someIdDoesntMatter',
pathname='/',
search='?options=True'
)
# Listen to URL and do/don't show RadioButtons
@callback(
Output('showOptionsRadioItems', 'options'),
Output('showOptionsRadioItems', 'value'),
Input('currentLocation', 'search'),
prevent_initial_call=False
)
def show_options(search):
if bool(search):
if eval(urllib.parse.parse_qs(urllib.parse.urlparse(search).query)['options'][0]):
# Example Data...
database_response = ['Apple', 'Banana', 'Peach']
return database_response, database_response[0]
raise dash.exceptions.PreventUpdate
# Redirect to Detail-Page with URL-Parameter 'fruit'
@callback(
Output('redirectToDetailsDiv', 'children'),
Input('goToFruitDetailsButton', 'n_clicks'),
State('showOptionsRadioItems', 'value'),
prevent_initial_call=True
)
def redirect_details(n_clicks, selected_fruit):
# Here is the Error...
location = dcc.Location(
id='someOtherId',
pathname='/details',
search='?fruit={}'.format(selected_fruit)
)
return location
details.py
import dash
from dash import html
dash.register_page(
__name__,
path='/details',
)
def layout(fruit='nothing', **other_unknown_query_strings):
return html.Div(
children=[
html.H1(children='Archive'),
html.P('Show details for {}'.format(fruit))
]
)
It never changes the entire URL. Either only the “pathname” or “search” changes, depending on whether I comment out “search”. I have also tried to access “url” directly, but this usually ends in an unwanted loop. It also makes no difference if I change ‘pathname’ and ‘search’ from a dcc.Location in an output or return a whole dcc.Location in a div.
I’m running out of ideas. Can anyone help me?
Thanks in advance.