Having trouble w/ saving input data from other pages in multi-page app using dcc.store

Hi,

Before I go into the problem, I will show the file structure in case that helps:

app.py
index.py
/apps
       chem_app.py
       ips_app.py
       soil_app.py

And the URL structure is similar to that outlined in the URL/multipage documentation of Dash

I have input boxes in multiple pages (chem_app, ips_app, soil_app)

and I would like to write all the data from these inputs into some files, so in the app.layout in index.py, I put all the dcc.store components corresponding to each input box, looking like this:

app.layout = html.Div([

    dcc.Location(id='URL', refresh=False),

    dcc.Store(id='recycle', storage_type='session'),
    dcc.Store(id='activity', storage_type='session'),
    dcc.Store(id='relmin', storage_type='session'),
    dcc.Store(id='transport', storage_type = 'session'),
# And so on, there are many more inputs, but I just wanted to provide an example

Here’s an example of code where I update the dcc.store values w/ the values from the dcc.input components:

@app.callback(

    Output('species_p', 'data'),
    Output('precip_p', 'data'),
    Output('surface_p', 'data'),
    Output('uz_p', 'data'),
    Output('lz_p', 'data'),

    Output('species_s', 'data'),
    Output('precip_s', 'data'),
    Output('surface_s', 'data'),
    Output('uz_s', 'data'),
    Output('lz_s', 'data'),

    Output('species_mk', 'data'),
    Output('precip_mk', 'data'),
    Output('surface_mk', 'data'),
    Output('uz_mk', 'data'),
    Output('lz_mk', 'data'),
    Output('label_mk', 'data'),
    Output('test_mk', 'data'),

    Input({'type':'speciesP', 'index':ALL}, 'value'),
    Input({'type':'precipP', 'index':ALL}, 'value'),
    Input({'type':'surfaceP', 'index':ALL}, 'value'),
    Input({'type':'uzP', 'index':ALL}, 'value'),
    Input({'type':'lzP', 'index':ALL}, 'value'),

    Input({'type':'speciesS', 'index':ALL}, 'value'),
    Input({'type':'precipS', 'index':ALL}, 'value'),
    Input({'type':'surfaceS', 'index':ALL}, 'value'),
    Input({'type':'uzS', 'index':ALL}, 'value'),
    Input({'type':'lzS', 'index':ALL}, 'value'),

    Input({'type':'speciesMK', 'index':ALL}, 'value'),
    Input({'type':'precipMK', 'index':ALL}, 'value'),
    Input({'type':'surfaceMK', 'index':ALL}, 'value'),
    Input({'type':'uzMK', 'index':ALL}, 'value'),
    Input({'type':'lzMK', 'index':ALL}, 'value'),
    Input({'type':'label', 'index':ALL}, 'value'),
    Input({'type':'test', 'index':ALL}, 'value')

)

def updateStorage(speciesP, precipP, surfaceP, uzP, lzP, 
speciesS, precipS, surfaceS, uzS, lzS, speciesMK, precipMK, surfaceMK, uzMK, lzMK, label, test):

    ctx = dash.callback_context

    ctx_msg = json.dumps({
        'states': ctx.states,
        'triggered': ctx.triggered,
        'inputs': ctx.inputs
    }, indent=2)

    input_id = ctx.triggered[0]['prop_id'].split('.')[0]

    print(ctx_msg)

    return speciesP, precipP, surfaceP, uzP, lzP, speciesS, precipS, surfaceS, uzS, lzS, speciesMK, precipMK, surfaceMK, uzMK, lzMK, label, test

My basic process was to put all the dcc.Stores in the app.layout, then use callbacks in the other pages to update what’s stored (so, the outputs for these callbacks would be the respective dcc.store components and the inputs would be the respective input boxes). I would then use a callback in index.py to save the data in the dcc.Stores to the respective files. For this callback, the output would be the 3 dcc.download components, the input would be the save button that’s defined in index.py, and the states would be all the dcc.stores.

For example…

If I click the “save” button, then I expect that the data in the input boxes would be stored in their respective dcc.store components, and this works as long as I’m on the same page (so in the /ips page and in the “primary” dropdown), but if I pick another option from the dropdown or click on another page, and then press “save,” it doesn’t work.

I’m not sure why this is because the dcc.store components are universal (as in they’re stored in app.layout), so even if I use callbacks in another file to change what’s stored, it should still retain the same value but it seems that dcc.Store components from one page aren’t recognized in another page.

I believe this to be so because when I print the dash_callback_context message for when I press “save” in another page/dropdown option, the “primary” values show up as as blank, even though I have updated them:

Screen Shot 2021-08-25 at 3.41.10 PM

However, when I’m on the same page, it works fine:

Screen Shot 2021-08-25 at 3.42.46 PM

I also tried the “hidden-div” method but that didn’t work- the URL routing stopped working for some reason, and I know this based on the dash_callback_context message.

Please let me know if there’s anything I could elaborate on. Thank you!

Edit:

I also found this piece of information on Stack Overflow, but I’m confused on what it’s trying to say:

Additionally, when you click to a new tab, if you want the data to persist from what you put in your dcc.Store that is in your index.py you’ll need to reload it on the new tab. Look at the “Updates on Page Load” section here (https://dash.plotly.com/live-updates) for about how to structure your layout as a function. That way you can provide the contents of your dcc.Store to it when reloading the tab so you can maintain the data collected from when the user was first on the tab

Would I make the app.layout a function or would I make the layouts for each of the pages a function?

2 Likes