New in dash 2.9.2
Itβs now possible to update the URL in a callback to navigate to a new page of a multi-page app without refreshing the page
NEW β dcc.Location(refresh="callback-nav")
- No page refresh!
OLD β dcc.Location(refresh=True)
Note the screen flash:
To see these examples (and more!) check out:
Background
With Dash Pages, the routing callback is under-the-hood, which reduces the amount of boilderplate code you need to write.
The best way to navigate is to use components such as the dcc.Link
or dbc.Button
. When the user clicks on these
links, it will navigate to the new page without refreshing the page, making the navigation very fast. And the best part? No callback required!
This works well when you have static links. However, at times, you may want to navigate based on an input field, ropdown, or clicking on a figure etc. There are two options:
- Update href of
dcc.Location
in a callback. Not recommended in Dash<2.9.2 because it refreshes the page. - Update the link in a callback. Best practice!
New in dash 2.9.2 dcc.Location(refresh="callback-nav")
- navigate without refreshing the page.
Hereβs an example of navigating to a new page when clicking on a figure:
- app.py
- pages
|-- flight_status.py
|-- home.py
app.py
from dash import Dash, dcc, page_container
import dash_bootstrap_components as dbc
app = Dash(__name__, use_pages=True, external_stylesheets=[dbc.themes.BOOTSTRAP])
navbar = dbc.NavbarSimple(
dbc.Button("Home", href="/", color="secondary", className="me-1"),
brand="Multi Page App Demo",
color="primary",
dark=True,
className="mb-2",
)
app.layout = dbc.Container(
[
dcc.Location(id="url", refresh="callback-nav"),
navbar, page_container,
], fluid=True
)
if __name__ == "__main__":
app.run_server(debug=True)
pages/home.py
import dash
from dash import dcc, html, Input, Output, callback, register_page
import plotly.express as px
import pandas as pd
register_page(__name__, path="/")
df_airports = pd.read_csv(
"https://raw.githubusercontent.com/plotly/datasets/master/2011_february_us_airport_traffic.csv"
)
fig = px.scatter_mapbox(
df_airports,
lat="lat",
lon="long",
hover_data=["iata", "airport", "city", "state", "cnt"],
size="cnt",
color="cnt",
zoom=3,
title="Airport Traffic Data"
)
fig.update_layout(mapbox_style="open-street-map")
layout = html.Div(dcc.Graph(id="graph", figure=fig))
@callback(
Output("url", "href"),
Input("graph", "clickData"),
prevent_initial_callback=True
)
def generate_chart(clickdata):
if not clickdata:
return dash.no_update
airport_code = clickdata["points"][0]["customdata"][0]
return f"/flight-status/{airport_code}"
pages/flight_status.py
from dash import html, register_page
register_page( __name__, path_template="/flight-status/<airport>")
def layout(airport=None, **other_unknown_query_strings):
return html.H3(f"Arrivals and Departures for: {airport}")