Show last retained value in the navigation bar

Hi all,

I have created a navigation page containing two nav bars.
The role of nav bars is to plot scatter chart and bar chart for page 1 and page2 respectively.
But everytime I am switching back and forth , the page displays the chart for initial values (dcc.Dropdown(value)) I set rather than the last chart I have made.
How can I show the last chart that the user made with different features?

import dash
from dash.dependencies import Input, Output, State
from dash import dcc, html, dash_table

import pandas as pd
import seaborn as sns

dd=sns.load_dataset('anscombe')

import dash_bootstrap_components as dbc
import matplotlib.pyplot as plt
import plotly.express as px
from jupyter_dash import JupyterDash
import dash_ag_grid as dag

df=px.data.gapminder()
df.head()

x=list(df.select_dtypes(include='number').columns)

app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP])

# the style arguments for the sidebar. We use position:fixed and a fixed width
SIDEBAR_STYLE = {
    "position": "fixed",
    "top": 0,
    "left": 0,
    "bottom": 0,
    "width": "16rem",
    "padding": "2rem 1rem",
    "background-color": "#f8f9fa",
}

# the styles for the main content position it to the right of the sidebar and
# add some padding.
CONTENT_STYLE = {
    "margin-left": "18rem",
    "margin-right": "2rem",
    "padding": "2rem 1rem",
}

sidebar = html.Div(
    [
        html.H2("Sidebar", className="display-4"),
        html.Hr(),
        html.P(
            "A simple sidebar layout with navigation links", className="lead"
        ),
        dbc.Nav(
            [
                dbc.NavLink("Home", href="/", active="exact"),
                dbc.NavLink("Page 1", href="/page-1", active="exact"),
                dbc.NavLink("Page 2", href="/page-2", active="exact"),
            ],
            vertical=True,
            pills=True,
        ),
    ],
    style=SIDEBAR_STYLE,
)

content = html.Div(id="page-content", style=CONTENT_STYLE)

app.layout = html.Div([dcc.Location(id="url"), sidebar, content])

#page1 layout
page1= html.Div([
    
    html.H2("Page1", style={"textAlign": "center"}),
    
    dbc.Row([
        
        dbc.Col([dbc.Label("feature1"),dcc.Dropdown(id='d1',options=x,value=x[0])],width=4),
        
        dbc.Col([dbc.Label("feature2"), dcc.Dropdown(id='d2',options=x,value=x[1])], width=4)
    ]),
    
    html.Div([dcc.Graph(id='out1')])
    
    
    
]),

# page2 layout
page2= html.Div([
    
    html.H2("Page2", style={"textAlign": "center"}),
    
    dbc.Row([
        
        dbc.Col([dbc.Label("feature1"),dcc.Dropdown(id='d3',options=x,value=x[0])],width=4),
        
        dbc.Col([dbc.Label("feature2"), dcc.Dropdown(id='d4',options=x,value=x[1])], width=4)
    ]),
    
    html.Div([dcc.Graph(id='out2')])
    
]),

#navigation bar callback
@app.callback(Output("page-content", "children"), [Input("url", "pathname")])
def render_page_content(pathname):
    if pathname == "/":
        return html.P("Main Page. Select other tabs to see the results")
    elif pathname == "/page-1":
        return page1
    elif pathname == "/page-2":
        return page2
    # If the user tries to reach a different page, return a 404 message
    return html.Div(
        [
            html.H1("404: Not found", className="text-danger"),
            html.Hr(),
            html.P(f"The pathname {pathname} was not recognised..."),
        ],
        className="p-3 bg-light rounded-3",
    )
#page1 callback

@app.callback(Output('out1','figure'),[Input('d1','value'),Input('d2','value')])

def fun(a,b):
    fig=px.scatter(data_frame=df,x=a,y=b)
    
    return fig

#page2 callback

@app.callback(Output('out2','figure'),[Input('d3','value'),Input('d4','value')])

def fun(a,b):
    fig=px.bar(data_frame=df,x=a,y=b)
    
    return fig
    
if __name__=='__main__':
    app.run_server(port='8347')





Hello @varun007 and welcome to the forum!

What are you looking for are persistence props for your dropdowns. You can learn more here: Persisting User Preferences & Control Values | Dash for Python Documentation | Plotly

2 Likes

Thank you Martin for the help. This is exactly what I was looking for but it seems like persistence doesn’t work with AG grids.

How can I do the same with ag grid or with HTML tags? Thanks for the help in advance.

I didn’t tried setting persistence for AG Grid yet but there is also the whole section of documentation for that. Dash
If you will have some more specific questions about it I believe @AnnMarieW will be able to help you further :slight_smile:

Also other libraries like dash bootstrap components or dash mantine components have persistence props implemented. And if you want to go beyond and persist some layouts instead check dcc.Store component :slight_smile:

A post was split to a new topic: Upload DataFrame and store the data for use in Callback

Hi ,
I have made a new app just like the last one (the nav. bar) in which I am using dcc.Upload component to take data in csv format, storing it using dcc.Store and then showing the data table using dash ag grid on that page. I have set persistence=True yet the table disappears after switching back and forth.

backend part of the table

@app.callback(Output('tab','children'),[Input('store','data')])

def f(stored_data):
    df = pd.read_json(stored_data, orient='split')
    
    table = dag.AgGrid(
                              
                id="my-table",
                rowData=df.to_dict("records"),                                                          # **need it
                columnDefs=[{"field": i} for i in df.columns],                                          # **need it
                defaultColDef={"resizable": True, "sortable": True, "filter": True, "minWidth":115},
                columnSize="sizeToFit",
                dashGridOptions={"pagination": True, "paginationPageSize":7},
                className="ag-theme-alpine",  # https://dashaggrid.pythonanywhere.com/layout/themes,
                persistence=True,persistence_type='memory'
            )
    return html.Div([
        dbc.Row([
                dbc.Col([table],width=8,style={"margin": 20,'margin-left': 300},)
            ])
            
        ])      
        
  #backend part of the navigation page
@app.callback(Output("page-content", "children"), [Input("url", "pathname")])
def render_page_content(pathname):
    if pathname == "/":
        return homepage
    elif pathname == "/page-1":
        return html.P("page01")
    elif pathname == "/page-2":
        return html.P("Oh cool, this is page 2!")
    # If the user tries to reach a different page, return a 404 message
    return html.Div(
        [
            html.H1("404: Not found", className="text-danger"),
            html.Hr(),
            html.P(f"The pathname {pathname} was not recognised..."),
        ],
        className="p-3 bg-light rounded-3",
    )

  

Seems like since I am displaying the data using html.Div() , the layout changes everytime and sets to default. Persistence argument is available only for dash table and dcc components. How can I show the last displayed layout.





Can you please provide code for homepage? :slight_smile:

Hello @varun007,

It looks like you need to have persistence on your dcc.Store and not the grid, since the store is what provides the grid’s rowData

Here is the code for homepage:

#home page
homepage = html.Div([
    dcc.Upload(
        id='upload-data',
        children=html.Div([
            'Drag and Drop or ',
            html.A('Select Files')
        ]),
        style={
            'width': '100%',
            'height': '60px',
            'lineHeight': '60px',
            'borderWidth': '1px',
            'borderStyle': 'dashed',
            'borderRadius': '5px',
            'textAlign': 'center',
            'margin': '10px'
        },
    ),
    dcc.Store(id='store',storage_type='session'),
    html.Div(id='output-data-upload'),
    
    html.Div(id='tab'),
    dbc.Container(id='qw')
])


It is almost same as given in the example of dash documentation of dcc.upload- Displaying Uploaded Spreadsheet Contents

But dcc.Store doesn’t have persistence as an argument.
It only accepts these arguments:
dcc.Store(
id=required,
storage_type=undefined,
data=undefined,
clear_data=undefined,
modified_timestamp=undefined,
**kwargs,
)

Kwargs = key word arguments. Which means that persistence is available.

Pass

persistence=True

And then give it a try.

dcc.Store(id=‘store’,storage_type=‘session’,persistence=True)

After adding persistence=True, I am getting a type error.

TypeError: The dcc.Store component (version 2.9.2) with the ID “store” received an unexpected keyword argument: persistence
Allowed arguments: clear_data, data, id, modified_timestamp, storage_type

try passing as a dictionary.

**{'persistence': True}

Hmm. Maybe the store is persistence, haha. Oops.

Ok.

I think the issue is with your callback, you are only generating the grid when the data changes since the data isn’t changing when you switch back to the page. It will never load the grid.

You can have the grid in the layout all the time to make it easier. Once you add the grid to be there all the time, add to the callback:

input(‘my-table’,’id’)

This will trigger the grid to load data any time the component is added to the layout. You’ll need to check to make sure that there is data loaded into the dcc.Store or not.

Or, you could just add to the callback:

Input(‘tab’,’id’)

Without changing your layout and add the id statement:

if stored_data:
    # execute the rest of the callback and return the grid
1 Like

@varun007 Just out of curiosity, were you able to make it work? :slight_smile: If yes, could you post what was the solution for you?