Black Lives Matter. Please consider donating to Black Girls Code today.
https://www.blackgirlscode.com

How to pass values between pages in dash

Hi, I am trying to create a dash where I have different pages. I am selecting one value on page 1. Then a message gets displayed- You have selected Value. Now I want that value to gets passed to Page 2, so that it says- You selected Value (Value on Page 1 using dropdown). But I am not able to do that. On running the dash, till Page 1, it works fine, but then on coming to Page 2, it shows updating.

Here is the code-

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output

print(dcc.__version__)

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.config.suppress_callback_exceptions = True

app.layout = html.Div([
    dcc.Location(id='url', refresh=False),
    html.Div(id='page-content')
])


index_page = html.Div([
    dcc.Link('Go to Page 1', href='/page-1'),
    html.Br(),
    dcc.Link('Go to Page 2', href='/page-2'),
])


page_1_layout = html.Div([
    html.H1('Page 1'),
    dcc.Dropdown(
        id='page-1-dropdown',
        options=[{'label': i, 'value': i} for i in ['LA', 'NYC', 'MTL']],
        value='LA'
    ),
    html.Div(id='page-1-content'),
    html.Br(),
    dcc.Link('Go to Page 2', href='/page-2'),
    html.Br(),
    dcc.Link('Go back to home', href='/'),
])

@app.callback(dash.dependencies.Output('page-1-content', 'children'),
              [dash.dependencies.Input('page-1-dropdown', 'value')])
def page_1_dropdown(value):
    return 'You have selected "{}"'.format(value)



page_2_layout = html.Div([
    html.H1('Page 2'),
    html.Div(id='page-2-content'),
    html.Br(),
    dcc.Link('Go to Page 1', href='/page-1'),
    html.Br(),
    dcc.Link('Go back to home', href='/')
])

@app.callback(Output('page-2-content', 'children'),
              [Input('page-1-dropdown', 'value')])
def page_2(value):
    return 'You selected "{}"'.format(value)


# Update the index
@app.callback(dash.dependencies.Output('page-content', 'children'),
              [dash.dependencies.Input('url', 'pathname')])
def display_page(pathname):
    if pathname == '/page-1':
        return page_1_layout
    elif pathname == '/page-2':
        return page_2_layout
    else:
        return index_page


if __name__ == '__main__':
    app.run_server(debug=False,port=1244,host = '0.0.0.0')

I want to know how to go about this. Is there some way to store the value and make it accessible to page 2 because declaring the value as global in Page 1 is not helping. Please help.

Reading from and writing to a JSON or CSV file is what I’ve been doing, dash is pretty good with that

Try this:

index_page = html.Div(
# I added this id attribute
id='index_page',
children = [
    dcc.Link('Go to Page 1', href='/page-1'),
    html.Br(),
    dcc.Link('Go to Page 2', href='/page-2'),
],
# I added this style attribute
style={'height': '0px'}
)

page_1_layout = html.Div(
# I added this id attribute
id='page_1_layout',
children = [
    html.H1('Page 1'),
    dcc.Dropdown(
        id='page-1-dropdown',
        options=[{'label': i, 'value': i} for i in ['LA', 'NYC', 'MTL']],
        value='LA'
    ),
    html.Div(id='page-1-content'),
    html.Br(),
    dcc.Link('Go to Page 2', href='/page-2'),
    html.Br(),
    dcc.Link('Go back to home', href='/'),
],
# I added this style attribute
style={'height': '0px'}

)

page_2_layout = html.Div(
# I added this id attribute
id='page_2_layout',
children = [
    html.H1('Page 2'),
    html.Div(id='page-2-content'),
    html.Br(),
    dcc.Link('Go to Page 1', href='/page-1'),
    html.Br(),
    dcc.Link('Go back to home', href='/'),
],
# I added this style attribute
style={'height': '0px'}
)


app.layout = html.Div([
    dcc.Location(id='url', refresh=False),
    html.Div(id='page-content',
                       # I added this children attribute 
                       children=[index_page, page_1_layout, page_2_layout]
                )
])

# Update the index
@app.callback(
              [dash.dependencies.Output(page, 'children') for page in ['index_page', 'page_1_layout', 'page_2_layout']], # I turned the output into a list of pages
              [dash.dependencies.Input('url', 'pathname')])
def display_page(pathname):
    
    return_value = [{'height': '0px'} for _ in range(3)]

    if pathname == '/page-1':
        return_value[1] = {'height': 'auto'}
        return return_value
    elif pathname == '/page-2':
        return_value[2] = {'height': 'auto'}
        return return_value
    else:
        return_value[0] = {'height': 'auto'}
        return return_value

@app.callback(dash.dependencies.Output('page-1-content', 'children'),
              [dash.dependencies.Input('page-1-dropdown', 'value')])
def page_1_dropdown(value):
    return 'You have selected "{}"'.format(value)


@app.callback(Output('page-2-content', 'children'),
              [Input('page-1-dropdown', 'value')])
def page_2(value):
    return 'You selected "{}"'.format(value)

Basically, what I did here is that I loaded the pages all at once, and just hid the other pages by setting their div ‘height’ to 0.

Added benefit of this approach is that you won’t have to reload every page element when switching between pages. Also, all your selections in pages are retained.

Just inform me should this not work for you.

1 Like

Hi Thomas please tell me the code for the same.
Also the dash that I am building will have many users. So a lot of json and CSV files will not be feasible. Therefore is there any way by which the json/csv file gets generated upon selecting from the dropdown and then they are read at page 2. Furthermore, upon going back to dropdown on page 1, the previous json/csv file gets deleted ?

Hey Marlon,
The code doesn’t seems to work. Looks like the text got superimposed. please help.

Oww. Apologies. Try this:

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output

print(dcc.__version__)

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.config.suppress_callback_exceptions = True

index_page = html.Div(
    # I added this id attribute
    id='index_page',
    children=[
                dcc.Link('Go to Page 1', href='/page-1'),
                html.Br(),
                dcc.Link('Go to Page 2', href='/page-2'),
            ],
    # I added this style attribute
    style={'display': 'block', 'line-height':'0', 'height': '0', 'overflow': 'hidden'}
)

page_1_layout = html.Div(
    # I added this id attribute
    id='page_1_layout',
    children=[
        html.H1('Page 1'),
        dcc.Dropdown(
            id='page-1-dropdown',
            options=[{'label': i, 'value': i} for i in ['LA', 'NYC', 'MTL']],
            value='LA'
        ),
        html.Div(id='page-1-content'),
        html.Br(),
        dcc.Link('Go to Page 2', href='/page-2'),
        html.Br(),
        dcc.Link('Go back to home', href='/'),
    ],
    # I added this style attribute
    style={'display': 'block', 'line-height': '0', 'height': '0', 'overflow': 'hidden'}

)

page_2_layout = html.Div(
    # I added this id attribute
    id='page_2_layout',
    children=[
        html.H1('Page 2'),
        html.Div(id='page-2-content'),
        html.Br(),
        dcc.Link('Go to Page 1', href='/page-1'),
        html.Br(),
        dcc.Link('Go back to home', href='/'),
    ],
    # I added this style attribute
    style={'display': 'block', 'line-height': '0', 'height': '0', 'overflow': 'hidden'}
)

app.layout = html.Div([
    dcc.Location(id='url', refresh=False),
    html.Div(id='page-content',
             # I added this children attribute
             children=[index_page, page_1_layout, page_2_layout]
             )
])


# Update the index
@app.callback(
    [dash.dependencies.Output(page, 'style') for page in ['index_page', 'page_1_layout', 'page_2_layout']],
    # I turned the output into a list of pages
    [dash.dependencies.Input('url', 'pathname')])
def display_page(pathname):
    return_value = [{'display': 'block', 'line-height': '0', 'height': '0', 'overflow': 'hidden'} for _ in range(3)]

    if pathname == '/page-1':
        return_value[1] = {'height': 'auto', 'display': 'inline-block'}
        return return_value
    elif pathname == '/page-2':
        return_value[2] = {'height': 'auto', 'display': 'inline-block'}
        return return_value
    else:
        return_value[0] = {'height': 'auto', 'display': 'inline-block'}
        return return_value


@app.callback(dash.dependencies.Output('page-1-content', 'children'),
              [dash.dependencies.Input('page-1-dropdown', 'value')])
def page_1_dropdown(value):
    return 'You have selected "{}"'.format(value)


@app.callback(Output('page-2-content', 'children'),
              [Input('page-1-dropdown', 'value')])
def page_2(value):
    return 'You selected "{}"'.format(value)


if __name__ == '__main__':
    app.run_server(debug=True, port=1244, host='0.0.0.0')


I hope you got the idea. :slight_smile:

4 Likes

It looks like you remain in the same page with three layouts and activate only one layout at a time based on the url.

I don’t think reloading pages helps at all. So, yours might be the only approach.