Hello Community,
I am building a multi-page dash app, that pulls data via a REST API from a third-party application.
Here is a scenario of what happens and another one of what I want to happen:
Let’s say I have three pages: page1, page2, page3. page1 has a html.P() element with initial value=“Not Updated” and a push button. When I press the button, the current timestamp gets written in the html.P() element.
What happens:
- I go to page2.
- I go to page1 again, the html.P() element returns to its initial state which is “Not Updated”
What I want to happen:
- I go to page2.
- I go to page 1 again, html.P() element holds the last timestamp that was generated when I last pushed the button.
In conclusion, I want the pages to keep their elements (graphs, paragraphs,…etc.) last state when I navigate the application, not only simple elements like html.P(), graphs also, becuase If I don’t do that, I have to pull the data from the REST API again and again and its lots of data.
Dash Version: 2.7.0
dcc Version: 2.7.0
html Version: 2.0.6
plotly Version: 5.9.0
My Code:
# Python Predefined Modules.
import time
from datetime import datetime
import json
# Data Manipulation Modules.
import numpy as np
import pandas as pd
# Visualization Modules
import plotly.express as px
import plotly.io as pio
# Apply theme to Plotly Dash figures
pio.templates.default = "plotly_dark"
# Dash Modules
import dash
from dash import Dash, dcc, html, State, callback_context
from dash.dependencies import Input, Output
from dash.exceptions import PreventUpdate
import dash_bootstrap_components as dbc
import dash_ag_grid as dag
# Instantiate Dash App.
app = Dash(__name__,external_stylesheets=[dbc.themes.DARKLY])
# Define dropdown menu
dropdown = dbc.DropdownMenu(
label="Operations",
children=[
dbc.DropdownMenuItem("Meters Commissioning", href='/meters-commissioning'),
dbc.DropdownMenuItem("Signal Status", href='/signal-status'),
dbc.DropdownMenuItem("Page-Test", href='/'),
],
direction="start"
)
# Main Page Layout
main_layout = html.Div([
# (Not a Visual Component) capture the text written in the url.
dcc.Location(id='url', refresh=False),
# (Not a Visual Component) (Shared Central Storage of the dataframe as json).
dcc.Store(id='data-store', storage_type='memory'),
# Main Navigation Bar.
dbc.NavbarSimple(
children=[
dbc.NavItem(dropdown),
],
brand="Meter Deployment Center",
brand_href="https://www.linkedin.com/in/shehabeldin-ehab-9344b3199/",
color="dark",
dark=True,
fluid=True,
),
html.Br(),
html.Div(id='page-content')
])
Meter_comsn_layout = html.Div([
html.P(id="last-update", children=["Not Updated"]),
dbc.Button("Sync with Symbiot", id="rerun-button", color="primary", className="mr-1", n_clicks=0),
])
signal_status_layout = html.Div([
html.P(id="second-page-state",
children=["I am at the second pages"])
])
# Define main layout
app.layout = main_layout
# "complete" layout
app.validation_layout = html.Div([
main_layout,
Meter_comsn_layout,
signal_status_layout
])
# Web Pages callbacks
@app.callback(Output('page-content', 'children'),
Input('url', 'pathname'),
)
def display_page(pathname):
if pathname == "/meters-commissioning":
return Meter_comsn_layout
elif pathname == "/signal-status":
return signal_status_layout
else:
return html.Div("What")
# Change Not-updated element to current Date.
@app.callback(Output("last-update", "children"),
Input("rerun-button", "n_clicks"),
prevent_initial_call=True)
def set_current_date(n_clicks):
# Debugging
print("Set Date Callback")
print("Date Callback is triggered", callback_context.triggered)
# If the button is push one time or more.
if n_clicks >= 1 and callback_context.triggered[0]['prop_id'] == 'rerun-button.n_clicks':
print("Button is clicked", callback_context.triggered)
return "Last Update: " + datetime.now().strftime("%Y-%m-%d %H:%M:%S")
if __name__ == "__main__":
app.run_server(port=8047, debug=True)