Callback not working when loading page.layout with Navbar

I have a multipage app that looks like the following:

-index
     -welcome
     -summary
     -[others]
     -test`

In test.py, there is an interactive callback that i’ve taken from here.

When I call test.layout using tabs, test.layout gets loaded and the interactivity in that page works fine:

dcc.Tabs(
    id="tabs",
    style={"height":'autosize',"verticalAlign":"middle"},
    children=[
        dcc.Tab(id="welcome_tab", label="Welcome", value="welcome_tab"),
        dcc.Tab(id="summary_tab", label="Summary", value="summary_tab"), 
        dcc.Tab(id="ppl_in_offences_tab", label="Defendents in", value="ppl_in_offences_tab"),
        dcc.Tab(id="impositions_tab", label="Sentences Imposed", value="impositions_tab"), 
        dcc.Tab(id="sentences_served_tab", label="Sentences Served", value="sentences_served_tab"),
        dcc.Tab(id="post_cc_tab", label="Post Crown Court", value="post_cc_tab"),
        dcc.Tab(id="test_tab", label="test", value="test_tab"),
        ],

html.Div(id='tabs-content-example_0'),


@app.callback(Output('tabs-content-example_0', 'children'),
              [Input('tabs', 'value')])
def render_content(tab):
    if tab == 'welcome_tab':
        return welcome.layout
    elif tab == 'summary_tab':
        return summary.layout
    elif tab == 'ppl_in_offences_tab':
        return ppl_in_offences.layout
    elif tab == 'impositions_tab':
        return impositions.layout
    elif tab == 'sentences_served_tab':
        return sentences_served.layout
    elif tab == 'post_cc_tab':
        return post_cc.layout
    elif tab == 'test_tab':
        return test.layout
    else:
        return '404 error'

However rather than tabs I want to use a navbar.

So I make the index looks as follows:

app.layout = html.Div([

html.Div([
    dcc.Location(id="url"),
    dbc.NavbarSimple(
        children=[
            dbc.NavLink("Welcome", href="/page-1", id="page-1-link"),
            dbc.NavLink("Summary", href="/page-2", id="page-2-link"),
            dbc.NavLink("Defendants", href="/page-3", id="page-3-link"),
            dbc.NavLink("Sentences Imposed", href="/page-4", id="page-4-link"),
            dbc.NavLink("Sentences Served", href="/page-5", id="page-5-link"),
            dbc.NavLink("Post-Crown Court", href="/page-6", id="page-6-link"),
            dbc.NavLink("test", href="/page-7", id="page-7-link"),
        ],
        color="primary",
        dark=True,
    ),
    #dbc.Container(id="page-content", className="pt-4"),
    
    
    ]),

    sidebar,

    html.Div(id='page-content'),

    
])




@app.callback(
[Output(f"page-{i}-link", "active") for i in range(1, 8)],
[Input("url", "pathname")],
)
def toggle_active_links(pathname):
if pathname == "/":
    # Treat page 1 as the homepage / index
    return True, False, False, False, False, False, False
return [pathname == f"/page-{i}" for i in range(1, 8)]


@app.callback(Output("page-content", "children"), [Input("url", "pathname")])
def render_page_content(pathname):
if pathname in ["/", "/page-1"]:
    return welcome.layout
elif pathname == "/page-2":
    return summary.layout
elif pathname == "/page-3":
    return ppl_in_offences.layout
elif pathname == "/page-4":
    return impositions.layout
elif pathname == "/page-5":
    return sentences_served.layout
elif pathname == "/page-6":
    return post_cc.layout
elif pathname == "/page-7":
    return test.layout
# If the user tries to reach a different page, return a 404 message
return dbc.Jumbotron(
    [
        html.H1("404: Not found", className="text-danger"),
        html.Hr(),
        html.P(f"The pathname {pathname} was not recognised..."),
    ]
)

When I do this, test.layout loads, but the interactivity doesn’t work at all. It’s the same case with the interactivity callbacks in the other pages. How should I get this working?

I think the issue is with your toggle_active_links callback. The outputs are

[Output(f"page-{i}-link", "active") for i in range(1, 8)]

(which is 7 links), but initially you return just three values (True, False, False) which is going to cause problems. Also in the code snippets you’ve shared, only links with ids page-1-link, page-2-link and page-7-link exist, but you’re creating a callback referencing e.g. page-4-link. Does that exist elsewhere in your layout? If not, that could be causing the app to hang.

If you haven’t already read it, you might find it helpful to look at the section on multi-page apps in the Dash docs.

Ah sorry, I tried to edit the list of pages in my OP to make it more focused and clear as to what I was referring to, I can see that I only made matters more complicated!

I’ve edited my OP and removed the ‘slim-lining’ edits.

Edit: I’ve made a simple example of my problem in this repo using templates:

In this repo, test.layout gets loaded, but the callback interactivity doesn’t work.

Edit 2: I was thinking that maybe only the layout part of test.py is getting pulled in, and not the callback part, so I tried copying the callback in test.py into index.py, and suppressing callback exceptions, but for some reason when I did that the app refused to run because the callback exceptions are not getting suppressed. I’m quite confused as to why.

Hey @Falc, I looked through your example and submitted a fix as a pull request.

In brief for anyone who is following this thread, the main problem was that there were two dash.Dash instances getting created, and the callbacks getting registered against the first were lost when the second got created and replaced it.

1 Like

Thanks that makes a lot of sense. Hopefully this thread will help other people who encounter the same problem.