Visibility of whole nested DropdownMenu and its Items shall disappear after click on nested item & string issue

Hi all,
Using DropDownMenu and -Item via navbar I have the problem that after click on nested item that menu area disappears, but the parent doesn’t. So it is still there together with new page content, which shall not be the case.

Part of that coding is:

dbc.DropdownMenu(
            id='decimal_dynasties',
            children=[
                dbc.DropdownMenuItem(
                    name,
                    id=name,
                    n_clicks=0,
                    href='/pages/'.join([name.replace(' ', '_').lower(), '/']),
                ) for name in decimal_dynasty_names
            ],
            label='10th Dynasties',
            toggle_style={
                # Tints of french grey
                "background": '#E1DFD6', 
                'color': 'black',
            },
            className="mt-1 px-1",
            align_end=True,
        ),

Furthermore, if I click on one of the nested items the first time, the content of the 404 page appears, after second click on the same item the correct page is shown.
As root cause I investigated the string-join coding line, because when I change that line to

href='/pages/' + name.replace(' ', '_').lower() + '/',

such issue does not appear. But in general, join is the better option for string concatination.
I am confused, why does this happen? Is the join method to fast?

In advance, thanks for help!
Ilona

Hi @Ilo2023

I’m not sure I understand the issue with the DropdownMenu, but the reason the link isn’t working is the string in string.join(iterable) is the separator.

So for example:

name="page1"
href='/pages/'.join([name.replace(' ', '_').lower(), '/'])

results in:

 page1/pages//

@AnnMarieW
Thanks for the hint:
I changed it to

href=''.join(['/pages/', name.replace(' ', '_').lower(), '/']),

Regarding the dropdown issue, only the nested area disappeared but the parent dropdown area is still there, it only disappears if I click on another point of the screen.

On the screenshot, if I click on ‘First Dynasty’ the area including the ‘Second Dynasty’, ‘Third Dynasty’, … disappears after this click, but the parent dropdown framed in blue and its background area will not disappear.

dropdown_issue

Hi @Ilo2023

That looks odd – but I can’t tell what’s going on by the image. Could you make a complete minimal example that duplicates the issue that I can run?

Hi @AnnMarieW

Thank you very much for your help!
Here is the coding example. If you click on the ‘Start’ dropdown you see an item ‘All’ and another dropdown ‘2nd nested dropdown’. There 2 items are included, ‘Item 1’ and ‘Item 2’.

Description of 2 workflows for testing after having clicked on ‘Start’ to see the menu:

  • if you click on ‘All’ everything is fine: text in page changes and dropdown area is not visible anymore
  • if you click on ‘2nd nested dropdown’ and there e.g. on ‘Item 1’: it is not as expected: text is changing but only the lowest level of visible dropdown area (the one with ‘Item 1’ and ‘Item 2’ included) disappears, the parent page with ‘All’ and ‘2nd nested dropdown’ is still there - expected is that this area disappears as well

Coding:

# nested dropdown visibility check
# Python 3.12.0, Plotly 5.17.0, Dash 2.13.0

##########################
# imports
##########################

from dash import (
    Dash, html, ctx,
    Input, Output, callback,
)

import dash_bootstrap_components as dbc

##########################
# coding
##########################

# initialise app
app = Dash(
    __name__,
    external_stylesheets=[dbc.themes.BOOTSTRAP],
)


# create components
dropdown_items = [
    dbc.DropdownMenuItem(
        'All',
        id='all_items',
        n_clicks=0,
    ),
    dbc.DropdownMenu(
        id='second_nested',
        children=[
            dbc.DropdownMenuItem(
                'Item 1',
                id='item_one',
                n_clicks=0),
            dbc.DropdownMenuItem(
                'Item 2',
                id='item_two',
                n_clicks=0),
        ],
        label='2nd nested dropdown',
        className="mt-1 px-1",
    ),
]

nested_dropdown = dbc.DropdownMenu(
    id='first_dropdown',
    children=dropdown_items,
    label="Start",
    in_navbar=True,
),

nav_bar = navbar = dbc.Navbar(
    dbc.Container(
        children = [
            dbc.Col(
                children = [
                    html.Br(),
                    html.H2("Nested dropdown visibility check ...", style={'color': 'white'}),
                    html.Br(),
                    dbc.Col(
                        children=[
                            dbc.NavbarToggler(id="navbar-toggler", n_clicks=0),
                            dbc.Collapse(
                                nested_dropdown,
                                id="navbar-collapse",
                                navbar=True,
                            ),
                        ],
                        className="mb-2",
                    ),
                ],
            ),
        ],
    ),
    color="black",
    dark=True,
)


# app layout
app.layout = dbc.Container(
    children = [
        navbar,
        html.Br(),
        html.H4(id='text_change'),
        html.Br(),
    ],
    fluid=True,
    style={
        'background-color': '#f7f7f4',
        'background-size': '100%',
        'padding': 5,
    },
)


# add controls to build the interaction
@callback(
    Output("text_change", "children"),
    Input("all_items", "n_clicks"),
    Input("item_one", "n_clicks"),
    Input("item_two", "n_clicks"),
)
def update_txt_input(click_all, click_one, click_two):
    item_clicked = ctx.triggered_id
    return f'''You have clicked dropdown item with ID {item_clicked}
            ''' if item_clicked else '''You haven't clicked any dropdown item yet'''


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

Hi @Ilo2023

Thanks for the excellent example! I see the issue now.

The dbc.DropdownMenu component does not officially support nested dropdowns. The state of a nested DropdownMenu does not update the state of the parent. There is probably some css or JavaScript that could be used as a workaround, but I haven’t been able to figure it out.

I don’t know of any Dash components that supports nested dropdowns.

Instead of doing nested dropdowns, another workaround could be to format the menu items into groups. See the menu content example in the dbc docs.

Sorry I couldn’t be more helpful on this one, but if you find a good solution, please feel free to share it :four_leaf_clover:

Hi @AnnMarieW
I found a workaround for my customised CSS file not using click events, but hover functionality with

/* add media part being clickable on mobile */
@media (min-width: 576px) { 
    .dropdown:hover > .dropdown-menu {
        display: block;
        margin-top: 0;
    }
}

For me that solution is sufficient. A menu item with a lot of groups was not a nice visualisation, so, I was happy to see this working :slight_smile:
Hope it helps someone else too.