How to store the parameters from a path_template in a dcc.Store?

Hi,

My all application is build on 2 main parameters: the geometry name and the crop name. Everything downstream is piloted from these 2 values.

To simplify let’s only focus on the cropname for now. I have a dash application with a dcc.Store object ich is the Input of every graph in the application.

My application have multiple page so to access the crop page I go to the “/crop/<crop_name>/” name url and from my application I use the following:

 dash.register_page(
    __name__, 
    path_template="/crop/<crop_name>", 
    name="Crop", layout=CropPage()
)

How could I pass the crop_name to any component in the layout ? (in this case a dcc.Store) ?

Hey @12rambau welcome to the forums.

If I am not n¡mistaken, you can find an example of how to achieve this here:

1 Like

thanks for your suggestion, I’m well aware of this documentation page. I’m actually looking for a fonctionality that looks like " Additional Inputs to the Pages Routing" but I would need it to be page related instead of application related.

In this case I do not understand what you want to do. Could you create a minimal reproducible example?

Sure thing,

I’m working with the following super simple application:

# app.py

import dash
from dash import html

app = dash.Dash(__name__, use_pages=True)

# set a title and a store in the layout
app.layout = html.Div([
    html.H1('Displaying store content'),
    dash.page_container
])

app.run_server(debug=True)

And the following parametrized page:

# pages/page1.py
import dash
from dash import html
from dash import dcc, Input, Output

app = dash.get_app()

content = html.H2("Nothing to see here.", id="title")
layout = html.Div([
    content,
    dcc.Store(id='store', data=None),
])

@app.callback(
    Output(content.id, "children"),
    [Input("store", "data")]
)
def display_store_data(data):
    return html.Pre(repr(data))


dash.register_page(__name__, path_template="/crop/<crop_name>", name="Crop")

I want to find a mechanism to feed the “crop_name” value to the dcc.Store object when I reach the page. I need to use a dcc store object because it’s in my real case used to trigger all the downstream page modifications.

What exactly do you mean by that?

You want to save a string in the dcc.Store(id="store") ?

If I understand the question, you need to add a dcc.Location() component to your layout and use it to trigger callbacks whenever the URL changes

Does this code do what you want?

app.py

import dash
from dash import html, dcc, Input, Output

app = dash.Dash(__name__, use_pages=True)
app.layout = html.Div([
    html.H1('Displaying store content'),
    dcc.Location(id='location'),
    dcc.Store(id='store', data=None),
    dash.page_container
])

@app.callback(
    Output("store","data"),
    Input("location", "pathname")
)
def populate_store(pathname):
    return pathname

app.run_server(debug=True)

pages/page1.py

import dash
from dash import html
from dash import dcc, Input, Output

app = dash.get_app()

content = html.H2("Nothing to see here.", id="title")
layout = html.Div([
    content,
])

@app.callback(
    Output(content.id, "children"),
    [Input("store", "data")]
)
def display_store_data(data):
    return html.Pre(repr(data))

dash.register_page(__name__, path_template="/crop/<crop_name>", name="Crop")

1 Like

My objective is to avoid use of the dcc.Location object as I have other part of my application writing the same thing to it. Also We have multiple url redirection depending on the deployment mechanism and registe_page was transparent when it comes to url parsing when dcc.Location needs to know if a prefix is applied.

I thinkwhat I’m trying to achieve is simply not possible in Dash, that’s the first time I deal with a stateless dashboarding tool and it’s very complicated to migrate what I know.

Thank you very much for your answer and I hope it will be useful to someone else!

@12rambau, You could do something like this to omit the dcc.Location():

app.py:

import dash
from dash import html, dcc

app = dash.Dash(__name__, use_pages=True)

app.layout = html.Div([
    dcc.Store(id='store', data=None),
    dash.page_container
])

if __name__ == "__main__":
    app.run(debug=True)

in the pages folder:

home:

import dash
from dash import html, callback, Input, Output

dash.register_page(__name__, path="/")

layout = html.Div(id="home_container"),

@callback(
    Output("home_container", "children"),
    Input("store", "data"),
)
def show_global_store_data(global_store_data):
    return f"value stored in global store: {global_store_data}"

crop.py:

import dash
from dash import html, dcc, callback, Input, Output

dash.register_page(__name__, path_template="/crop/<crop_name>", name="Crop")

def layout(crop_name=None, **kwargs):
    return [
        html.Div("Nothing to see here.", id="page_container"),
        dcc.Link("go to home", href="/"),
        dcc.Store(id="dummy", data=crop_name)
    ]

@callback(
    Output("store", "data"),
    Input("dummy", "data")
)
def update_global_store(crop_name):
    return crop_name
1 Like

@12rambau
It’s not a problem to have multiple dcc.Location components in an app. They should be in app.py rather than on the other pages.

1 Like