Hello everyone, first post here. I’m trying to build a simple multipage app where app.py
contains the navigation bar and html.Div(id=‘page-content’) which will be filled with the layout of the different pages.
index.py:
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
from app import app
from apps import app0, app1, app2
navbar = dbc.Navbar(
[
dbc.Row(
[
dbc.Col(dbc.NavbarBrand("Security Solution Tuning Suite")),
dbc.Col(dbc.NavLink("Main", href="/")),
dbc.Col(dbc.NavLink("Toolbox", href="/app1")),
dbc.Col(dbc.NavLink("Tuning", href="/app2")),
],
align="center",
no_gutters=True,
style={'column-gap': '20px'}
),
],
)
app.layout = html.Div(
[
dcc.Location(id='url', refresh=False),
navbar,
html.Div(id='page-content')
],
)
@app.callback(
Output('page-content', 'children'),
Input('url', 'pathname'),
prevent_initial_call=True
)
def display_page(pathname):
if pathname == '/':
return app0.layout
if pathname == '/app1':
return app1.layout
elif pathname == '/app2':
return app2.layout
else:
return '404'
if __name__ == '__main__':
app.run_server(
debug=True,
# threaded=True
)
app.py:
import dash
import dash_bootstrap_components as dbc
app = dash.Dash(
__name__,
# suppress_callback_exceptions=True,
external_stylesheets=[dbc.themes.BOOTSTRAP]
)
server = app.server
app0.py
import dash_core_components as dcc
import dash_bootstrap_components as dbc
import dash_html_components as html
from dash.dependencies import Input, Output
from app import app
layout = html.Div(
[
dbc.InputGroup(
[
dbc.InputGroupAddon("@", addon_type="prepend"),
dbc.Input(placeholder="Username"),
],
className="mb-3",
),
dbc.InputGroup(
[
dbc.Input(placeholder="Recipient's username"),
dbc.InputGroupAddon("@example.com", addon_type="append"),
],
className="mb-3",
),
dbc.InputGroup(
[
dbc.InputGroupAddon("$", addon_type="prepend"),
dbc.Input(placeholder="Amount", type="number"),
dbc.InputGroupAddon(".00", addon_type="append"),
],
className="mb-3",
),
dbc.InputGroup(
[
dbc.InputGroupAddon("With textarea", addon_type="prepend"),
dbc.Textarea(),
],
className="mb-3",
),
dbc.InputGroup(
[
dbc.Select(
options=[
{"label": "Option 1", "value": 1},
{"label": "Option 2", "value": 2},
]
),
dbc.InputGroupAddon("With select", addon_type="append"),
]
),
]
)
app1.py
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from app import 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'),
dcc.Link('Go to App 2', href='/apps/app2')
])
@app.callback(
Output('app-1-display-value', 'children'),
Input('app-1-dropdown', 'value'),
prevent_initial_call=True
)
def display_value(value):
return 'You have selected "{}"'.format(value)
app2.py
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from app import app
layout = html.Div([
html.H3('App 2'),
dcc.Dropdown(
id='app-2-dropdown',
options=[
{'label': 'App 2 - {}'.format(i), 'value': i} for i in [
'NYC', 'MTL', 'LA'
]
]
),
html.Div(id='app-2-display-value'),
dcc.Link('Go to App 2', href='/apps/app2')
])
@app.callback(
Output('app-2-display-value', 'children'),
Input('app-2-dropdown', 'value'),
prevent_initial_call=True
)
def display_value(value):
return 'You have selected "{}"'.format(value)
My issue is that I get 4 callback error coming from the display_value function both in app1 & app2:
Errors (4)
×
ID not found in layout
18:15:11
Attempting to connect a callback Input item to component:
“app-2-dropdown”
but no components with that id exist in the layout.
If you are assigning callbacks to components that are
generated by other callbacks (and therefore not in the
initial layout), you can suppress this exception by setting
suppress_callback_exceptions=True
.
This ID was used in the callback(s) for Output(s):
app-2-display-value.children
ID not found in layout
18:15:11
Attempting to connect a callback Input item to component:
“app-1-dropdown”
but no components with that id exist in the layout.
If you are assigning callbacks to components that are
generated by other callbacks (and therefore not in the
initial layout), you can suppress this exception by setting
suppress_callback_exceptions=True
.
This ID was used in the callback(s) for Output(s):
app-1-display-value.children
ID not found in layout
18:15:11
Attempting to connect a callback Output item to component:
“app-2-display-value”
but no components with that id exist in the layout.
If you are assigning callbacks to components that are
generated by other callbacks (and therefore not in the
initial layout), you can suppress this exception by setting
suppress_callback_exceptions=True
.
This ID was used in the callback(s) for Output(s):
app-2-display-value.children
ID not found in layout
18:15:11
Attempting to connect a callback Output item to component:
“app-1-display-value”
but no components with that id exist in the layout.
If you are assigning callbacks to components that are
generated by other callbacks (and therefore not in the
initial layout), you can suppress this exception by setting
suppress_callback_exceptions=True
.
This ID was used in the callback(s) for Output(s):
app-1-display-value.children
At the moment I’m deliberately NOT using suppress_callback_exceptions=True
(you can see it commented out) as I want to see callback errors and suppressing those would make it much harder to debug, moreover, to me it does look more like a hack than a definitive solution.
I had a read online and I noticed how someone proposed using flask.has_request_context():
to circumvent the issue, but I can’t figure out how to make it work, any chance someone can guide me?