Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multi-Page Dash App Callbacks Not Registering

I am working on my first Dash app (I have experience in Django and very little in Flask, which I know Dash is built on), but I am having trouble with the routing and registering of callbacks for new pages. I have read a few articles on the subject such as: https://dash.plot.ly/urls

Currently I have my main app.py:

from app1 import build as app1

app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
server = app.server
app.config.suppress_callback_exceptions = True


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

app.layout = html.Div([navbar, body])


@app.callback(dash.dependencies.Output('page-content', 'children'),
              [dash.dependencies.Input('url', 'pathname')])
def display_page(pathname):
    if pathname == '/' or pathname == '' or pathname == '/index':
        return build_index_page()
    elif pathname == '/1':
        return app1.layout
    else:
        return html.H3('URL Error!')


if __name__ == '__main__':
    app.run_server(debug=True)

And then I would like to build out sub apps / graphs that will be loaded into the “html.Div(id=‘page-content’)”

App1 is its own sub dir with init.py and build.py where build will generate the layout and callbacks to be loaded. build.py:

from app import app

#layout = build_body()
# initialize_callbacks(app)

layout = html.Div([
    html.H3('App 1'),
    dcc.Dropdown(
        id='app-1-dropdown',
        options=[
            {'label': 'App 1 - {}'.format(i), 'value': i} for i in [
                'NYC', 'MTL', 'LA'
            ]
        ]
    ),
    html.Div(id='app-1-display-value')
])


@app.callback(
    Output('app-1-display-value', 'children'),
    [Input('app-1-dropdown', 'value')])
def display_value(value):
    return 'You have selected "{}"'.format(value)

Eventually I would like to then make 2 other files, one to contain layout and one to contain the callbacks. You can see my original implementation commented out, but I just moved the code into build.py when it did not work. (The functionality was taken directly from the Dash example linked above.)

When I go to my second page, the content loads fine but the callback does not, so selecting an item from the drop down does not populate the div as it is supposed to.It is also supposed to trigger on load to show the initial value, but it does not do that either.

Any help would be greatly appreciated! Thanks!

like image 855
Scott Glascott Avatar asked Jan 24 '20 21:01

Scott Glascott


1 Answers

I figured it out, but I am unsure about the "why"

If I edit app.py to be:

app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
server = app.server
app.config.suppress_callback_exceptions = True

and create index.py to be:

from app1 import build as app1
from app import app


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

app.layout = html.Div([navbar, body])


@app.callback(dash.dependencies.Output('page-content', 'children'),
              [dash.dependencies.Input('url', 'pathname')])
def display_page(pathname):
    if pathname == '/' or pathname == '' or pathname == '/index':
        return build_index_page()
    elif pathname == '/1':
        return app1.layout
    else:
        return html.H3('URL Error!')


if __name__ == '__main__':
    app.run_server(debug=True)

Then the code for build.py works! As I said, I am unsure why this is the case...

like image 145
Scott Glascott Avatar answered Oct 20 '22 20:10

Scott Glascott