0

I am desperately looking for a way to make sub dropdowns. I'll explain.

I have a datatable, and I want to have different display parameters (like full, simplified and custom) : they are all 3 selected in a dropdown. But when custom is selected, I want a second dropdown to appear just under the first one in which I can select the specific rows I want.

Everything works except the way to hide/show this second dropdown. Because if I use one additional callback that display it if 'custom' is chosen, I have an error telling me that this dynamic dropdown does not exists. Does someone knows how to do it ? Thanks in advance ! The pseudo code used to show you this scenario :

from dash import Dash, html, dcc, Input, Output, dash_table
from dash_bootstrap_components import themes
from tools.visual import colors
import pandas as pd


data = [['A', 10, 19, 21], ['B', 15, 54, 12], ['C', 14, 5, 9], ['D', 14, 5, 9], ['E', 14, 5, 9]]
dashboard = pd.DataFrame(data, columns=['Mat', '1', '2', '3'])


app = Dash(external_stylesheets=[themes.BOOTSTRAP])


app.layout = html.Div(style={'backgroundColor': colors['background']}, children=[
    html.Div(children=[
        dcc.Dropdown(id='chosen-mat', multi=False, value='All',
                     options=['All', 'Custom'])
    ]),

    html.Div(id='custom-mat', children=[
        dcc.Dropdown(id='chosen-custom-mat', multi=True, value=[],
                     options=dashboard.iloc[0:, 0].to_list())
    ]),

    html.Div([
        dash_table.DataTable(
            data=dashboard.to_dict('records'),
            columns=[{"name": i, "id": i} for i in dashboard.columns],
            id='tbl')
    ], style={'margin-left': '20px', 'margin-right': '20px'}),

    html.Div(id='datatable-interactivity-container', style={'text-align': 'center'})
])


@app.callback(Output('tbl', 'data'),
              Output('tbl', 'columns'),
              Input('chosen-mat', 'value'),
              Input('chosen-custom-mat', 'value'))
def actualize_db(type_layout, mat_list):
    if type_layout == 'All':
        db = dashboard
    else:
        if mat_list is None:
            listt = []
        else:
            listt = mat_list
        db = dashboard[dashboard['Mat'].isin(listt)]
    return db.to_dict('records'), [{"name": i, "id": i} for i in db.columns]


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

And what I need to do is this :

If CUSTOM selected : enter image description here

If another option (here ALL) is selected : enter image description here

5
  • You should provide your explanation with a piece of code! Commented Apr 26, 2022 at 14:22
  • You can provide a dummy code only for this specific example Commented Apr 26, 2022 at 14:41
  • So, it is kind of filtering the rows of table based on different selection of dropdown list? Commented Apr 26, 2022 at 15:39
  • Yes but this, I know how to do it, the thing I don’t is how to filter rows of table with a drop down that appears dynamically (depending on the choice in the previous drop down) Commented Apr 27, 2022 at 16:28
  • You can style your second dropdown with hidden attribute and control it by the first dropdown menu. Commented Apr 27, 2022 at 16:38

1 Answer 1

1

You can do as below code to Hide second dropdown when you choose All and show when you choose Custom. As you see, we will return children based on dropdown.

from dash import Dash, html, dcc, Input, Output, dash_table
from dash_bootstrap_components import themes
import pandas as pd


data = [['A', 10, 19, 21], ['B', 15, 54, 12], ['C', 14, 5, 9], ['D', 14, 5, 9], ['E', 14, 5, 9]]
dashboard = pd.DataFrame(data, columns=['Mat', '1', '2', '3'])


app = Dash(external_stylesheets=[themes.BOOTSTRAP])


app.layout = html.Div(children=[
    html.Div(children=[
        dcc.Dropdown(id='chosen-mat', multi=False, value='All',
                     options=['All', 'Custom'])
    ]),

    html.Div(id='custom-mat'),

    html.Div([
        dash_table.DataTable(
            data=dashboard.to_dict('records'),
            columns=[{"name": i, "id": i} for i in dashboard.columns],
            id='tbl')
    ], style={'margin-left': '20px', 'margin-right': '20px'}),

    html.Div(id='datatable-interactivity-container', style={'text-align': 'center'})
])

@app.callback(Output('custom-mat', 'children'),
              [Input('chosen-mat', 'value')])
def hide_unhide(type_layout):
    if type_layout == 'Custom':    
        return dcc.Dropdown(id='chosen-custom-mat', multi=True, value=[],
                     options=dashboard.iloc[0:, 0].to_list())
    if type_layout == 'All': 
        return []

@app.callback(Output('tbl', 'data'),
              Output('tbl', 'columns'),
              Input('chosen-mat', 'value'),
              Input('chosen-custom-mat', 'value'))
def actualize_db(type_layout, mat_list):
    if type_layout == 'All':
        db = dashboard
    else:
        if mat_list is None:
            listt = []
        else:
            listt = mat_list
        db = dashboard[dashboard['Mat'].isin(listt)]
    return db.to_dict('records'), [{"name": i, "id": i} for i in db.columns]


if __name__ == '__main__':
    app.run_server(debug=False,port='8051')
Sign up to request clarification or add additional context in comments.

2 Comments

Hi ! First of all thanks for your reply. It helps but the only thing is that by doing that it only hides the options, but what I want to do is to hide the whole second drop down, not only the options… do you know how to do it ?
@CesarMaurey: Please check my updated answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.