7

Dash has a nice Dropdown component that supports multi-value selection. In my application, the user can do data segmentation via multiple dropdown menus to choose properties "A", "B", "C", "D", and "E". It would be useful to also allow the user to segment based on negations of properties, say "not A" and "not E".

Is there already a Dropdown component available that would support clicking on items (i.e., when a user clicks on the selected property "A", we could make the element turn red to denote "not A" is now selected)? For example, suppose the user clicks on "New York City" in the multi-value dropdown example, and the corresponding "box" containing it changes color.

The Dash documentation explains how to create your own component but this doesn't cover the scenario where you simply want to extend an existing component. If there's no such component available, how would I go about making one?

Further background:

  • There's a discussion on the plotly forum where a user explains how an existing component can be extended. The major downside with this is that one needs to update and rebuild the whole dash-core-components library every time one makes a change to the component or a new dash version is released.

  • There's an issue open on dash-docs for writing a tutorial to cover this case with no apparent progress so far.

Juho
  • 976
  • 1
  • 13
  • 27

1 Answers1

9

There is a way to achieve this in native Dash by effectively making a drop down checklist. This is achieved by using dash_html_components.Details and dash_html_components.Summary. This is native in HTML5.

Sample code:

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

app = dash.Dash(external_stylesheets = [dbc.themes.BOOTSTRAP])
server = app.server

app.layout = dbc.Container(
    children=[
        html.Details([
        html.Summary('Select city...'),
        html.Br(),
        dbc.Col([
            dcc.Checklist(
                options=[
                    {'label': 'New York City', 'value': 'NYC'},
                    {'label': 'Montréal', 'value': 'MTL'},
                    {'label': 'San Francisco', 'value': 'SF'}
                    ],
                value=['NYC', 'MTL'],
                labelStyle = {'display': 'block'}
                )  
            ])
        ])
    ])

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

Dropdown closed

Dropdown open

Tom
  • 651
  • 1
  • 6
  • 13
  • Thanks! It's not obvious to me from your screenshots as to how this solves the problem, but it looks promising. I think I need to try it interactively, if you will. (That is, the checkmarks just look purple, i.e., how can we differentiate between three states "NYC not selected", "NYC selected", and "!NYC selected"?) – Juho Apr 27 '20 at 16:34
  • So in particular, how is this different than using a dropdown with `multi=True`? – Juho Apr 27 '20 at 16:39
  • Hi there. Well from what you described ultimately what you look to be after is a way for a user to know what isn't selected ("It would be useful to also allow the user to segment based on negations of properties, say "not A" and "not E""). So this workaround is achieving that since it allows a user to see at a glance what isn't included. This is the difference with the multi select dropdown - when you deselect with that only the selected is shown – Tom Apr 27 '20 at 16:44
  • Its not perfect (perfect would be what you are after by keeping the deselected items in the multi dropdown and change their colour) but this is the closest I think that can be achieved natively. There is no way to extend a dash component unfortunately. As you say you need to rebuild it and my view is if you are going to do that you might as well just use React from the start as it defeats the purpose of using Dash in the first place Hope this is of some help / interest at least – Tom Apr 27 '20 at 16:46
  • "... allows the user to see at a glance what isn't included." -- this you can also achieve with a Dropdown, i.e., you can list all available options. But nevertheless I upvoted your answer, this might help me down the road. – Juho Apr 27 '20 at 17:02
  • Multi=true has its own problem as soon as you select one value and you have callback attached to the dropdown value, It will call the callback and the callback receives a single value for processing. – pankaj pundir May 24 '21 at 04:41
  • I love you tom! – nmu Oct 28 '22 at 11:05