Building a dropdown of dash pages

I am building a multipage app. I want to have users access the individual pages via a dropdown. I have seen this code:

html.Div(
[
html.Div(
dcc.Link(f"{page[‘name’]}", href=page[“path”]),
)
for page in page_registry.values()
]

that populates a DIV on a page and provides an entry for each record in the page_registry_values() list.
Are there any examples of using the entries in the page_registry_values() list to build a dropdown?

TIA

Hey @abick here an example where I create a dropdown in a Navbar:

            dbc.DropdownMenu(
                [
                    dbc.DropdownMenuItem(
                        children=page['name'],
                        href=page['path']
                    )
                    for page in dash.page_registry.values()
                    if page['name'] != 'Not found 404'
                ],
                align_end=True,
                label='Menu',
                color='primary',
                style={'marginLeft': '15px'},
            )

Full MRE:

import dash
from dash import html
import dash_bootstrap_components as dbc


external_stylesheets = [
    dbc.themes.SLATE,
    dbc.icons.FONT_AWESOME,
]

# initiate app
app = dash.Dash(
    __name__,
    use_pages=True,
    external_stylesheets=external_stylesheets,
)


# create a navbar. Includes logo and menu drop down
navbar = dbc.Navbar(
    id='navbar',
    children=[
        dbc.NavbarBrand(
            html.A(
                [
                    html.I(
                        className="fa-brands fa-github d-inline",
                        style={'color': 'white', 'height': '50px'}
                    ),
                ],
                href="https://github.com",
                target="_blank",
                className='align-items-center text-decoration-none text-black',
            ),
            className="me-auto",  # me-auto pushes other elements to the right
            style={"margin-left": "10px"},

        ),
        dbc.Nav(
            dbc.DropdownMenu(
                [
                    dbc.DropdownMenuItem(
                        children=page['name'],
                        href=page['path']
                    )
                    for page in dash.page_registry.values()
                    if page['name'] != 'Not found 404'
                ],
                align_end=True,
                label='Menu',
                color='primary',
                style={'marginLeft': '15px'},
            ),
            navbar=True,
        ),
    ],
    color='primary',
    className='mb-0',
    # ^^ no margin on bottom
    style={'height': '50px'}
)

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

if __name__ == "__main__":
    app.run(debug=True)
2 Likes

Hi @AIMPED
Thanks for the reply. One thing I need to do is replace the filename value (page[‘name’]) with a more descriptive name and use a dcc.Link command. So my code looks like this:

#the function that provides the descriptive name, one entry for each registry value
def topic_list(namep) :
if(namep == ‘Topic00’ ) : titlep = ‘Select Topic’
if(namep == ‘Topic01’ ) : titlep = ‘Population by Age’
if(namep == ‘Topic02’ ) : titlep = ‘Unemployment Rate’
if(namep == ‘Topic03’ ) : titlep = ‘Population by Federal Poverty Level’
if(namep == ‘Topic04’ ) : titlep = ‘Educational Attainment by Federal Poverty Level’
if(namep == ‘Topic05’ ) : titlep = ‘Age by Federal Poverty Level’
if(namep == ‘Topic06’ ) : titlep = ‘Age by Federal Poverty Level Trend’
if(namep == ‘Topic07’ ) : titlep = ‘Age by Federal Poverty Level for Persons with Disabilities’
if(namep == ‘Topic08’ ) : titlep = ‘Families by Type and Poverty Status’
if(namep == ‘Topic09’ ) : titlep = ‘Housing Tenure by Poverty Status’
if(namep == ‘Topic10’ ) : titlep = ‘Supplemental Nutrition Assistance Program (SNAP)’
if(namep == ‘Topic11’ ) : titlep = ‘Women Infants and Children (WIC)’
if(namep == ‘Topic12’ ) : titlep = ‘Health Insurance by Age and Poverty Level’
return titlep

#the code for the dropdown box
topic_drop = dcc.Dropdown(
id=‘topicdl’,
options= [
dcc.Link(topic_list(page[‘name’]), href=page[‘relative_path’]) for page in dash.page_registry.values()
],
className=‘profiletext’, disabled=False)

This code generates an error:

Invalid argument options passed into Dropdown with ID “topicdl”.
Expected one of type [object].
Value provided:
[
{
“props”: {
“children”: “Select Topic”,
“href”: “/topic00”
},
“type”: “Link”,
“namespace”: “dash_core_components”
}, …

Any idea how to make this work?
TIA

Hi @abick

The value in the dropdown options must be a string, number or a boolean, so providing a dcc.Link component is causing the error. The label can be a component, and you can find an example here:

Having a link in a dcc.Dropdown can be a awkward UI. (The dbc.DropdownMenu component that @AIMPED suggested works better). If you want to keep the dcc.Dropdown then It might be better to use a callback to switch pages based on the value of the dropdown and not put a .dcc.Link` in the label.

You can find an example here:


Also, one cool feature of Pages is that you can add arbitrary data to the dash.page_registry. This would make your topic_list function unnecessary.

For example, if you want to add more descriptive names for your dropdown, when you register the page, you can do this:

dash.register_page(__name__, dropdown_name="Population by Age")

Then you can loop through the dash.page_registry like this:

options = [
   page["dropdown_name"]
   for page in dash.page_registry.values()
   if page["name"] != "Not found 404"
]

1 Like