Search code examples
pythonnavbarmulti-page-application

Dash Bootstrap Components NavLink not triggering callback


I am creating a multi-page application and I have created a navbar with links to different pages(URLs) which has mysteriously stopped working as of recently. I have tried reverting all code to the last known good state and it did not repair the issue. Currently, this is only broken on my development machine and the live application still works but due to this issue I cannot publish new releases. I have included code snippets below for all relevant code and would appreciate a fresh set of eyes on this problem, thanks.

It may be worth noting that if I change the dbc.NavLink to dbc.Link everything works fine but it does not layout correctly or have the active button appearance when in a page so this is not the desired option.

Here are my versions

dash-bootstrap-components 0.7.1
dash-core-components 1.8.0
dash-html-components 1.0.2

app.py

import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html

from server import app

app.layout = htm.Div([
    html.Link(rel='shortcut icon', href='assets/images/favicon/ico'),
    dcc.Store(id='session-store', storage_type='session'),
    dcc.Location(id='url', refresh=False),
    html.Nav(id='navbar-container'),
    html.Div(id='page-content')
])

navbar.py

import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html

def navbar():
    layout = html.Nav([
        dbc.Nav([
            dbc.NavItem(dbc.NavLink('Home', id='home-link', href='/')),
            dbc.NavItem(dbc.NavLink('Employees', id='employee-link', href='/employees')),
            dbc.NavItem(dbc.NavLink('Programs', id='programs-link', href='/programs')),
            dbc.NavItem(dbc.NavLink('Capacity', id='capacity-link', href='/capacity'))
            ],
            pills=True,
            id='navbar')
    ])

callbacks.py

from dash.dependencies import Output, Input, State
from pages import home, employees, programs, capacity
from assets.navbar import navbar

page_list = '', 'employees', 'programs', 'capacity']


@app.callback(Output('page-content', 'children'),
             [Input('url', 'pathname')],
             [State('session-store', 'data')])
def display_page(pathname, data):
    if pathname == '/':
        return home.home_page_layout(data)
    if pathname == '/employees':
        return employees.employee_page_layout(data)
    if pathname == '/programs':
        return programs.program_page_layout()
    if pathname == '/capacity':
        return capacity.capacity_page_layout()

@app.callback([Output('navbar-container', 'children'),
               Output('home-link', 'active'),
               Output('employees-link', 'active'),
               Output('programs-link', 'active'),
               Output('capacity-link', 'active')],
              [Input('url', 'pathname')],
              [State('navbar-container', 'children')])
def navbar_state(pathanem, data):
    active_link = ([pathname == f'/{i}' for i in page_list])
    return navbar(data), active_link[0], active_link[1], active_link[2], active_link[3]

Solution

  • After looking into the available arguments for the dbc.NavLink item it appears for some reason it was unable to auto-negotiate the link type anymore. I added the argument external_link=True to the links themselves and everything started working again.