✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
🧬 Learn how to build RNA-Seq data apps with Python & Dash. Register for the May 20 Webinar!

How to keep selected legend data persistent through callback

I’m using Dash to plot some data. I currently have a clustered bar chart with two data sets (one for each bar in the clusters.) These data sets have their name and the corresponding color of the bars displayed in the top, left-hand corner of the figure. They can be clicked to be toggled on and off, which will remove their corresponding bars from the chart.

Separately, I have a checklist of items that can be displayed in the chart. I am using a callback to update the graph so that it only displays what the user has checked. This updates the graph as expected, however, it also resets the bars/datasets such that both are enabled. Ie. if you select only one of the bars, then select some new checklist items, it will display the new checklist items and both of the bars.

My thinking is that the logical way to do this is to pass some variable as a second input to the callback function, then set up the outputted figure within the function to only display the proper bars. However, I can’t seem to find a variable that contains this data.

From what I can tell, the accessible properties of the Plotly graph object are ‘id’, ‘clickData’, ‘clickAnnotationData’, ‘hoverData’, ‘clear_on_unhover’, ‘selectedData’, ‘relayoutData’, ‘figure’, ‘style’, ‘className’, ‘animate’, ‘animation_options’, ‘config’, and ‘loading_state’.

I’ve investigated all of these, and it seems that none hold the data that I am looking for. Does anyone know of an easy way to access this data?

This is how my callback is working right now:

    @app.callback(
        dash.dependencies.Output('theGraph', 'figure'),
        [dash.dependencies.Input('theChecklist','values'),
        dash.dependencies.Input('theGraph', 'clickData')
        ]
    )
    def updateGraph(checklistValues, figureInput):

        #print to see what the variables hold
        print(checklistValues)
        print(figureInput)

        figure=go.Figure(
            data = [
                go.Bar(
                    x = df[df['MyColumnName'].isin(checklistValues)].groupby('MyColumnName').size().index,
                    y = df[df['MyColumnName'].isin(checklistValues)].groupby('MyColumnName').size().values,
                    name = 'Bar 1'
                ),
                go.Bar(
                    x = df[df['MyColumnName'].isin(checklistValues)].groupby('MyColumnName')['# cores'].sum().reset_index()['MyColumnName'],
                    y = df[df['MyColumnName'].isin(checklistValues)].groupby('MyColumnName')['# cores'].sum().reset_index()['MyOtherColumnName'],
                    name = 'Bar 2'
                )
            ],
            layout=go.Layout(
                title='The Title',
                showlegend=True,
                legend=go.layout.Legend(
                    x=0,
                    y=1.0
                ),
                margin=go.layout.Margin(l=40, r=40, t=40, b=110)
            )
        )

        return figure

I believe that UI Revision should do the trick here: 📣 Preserving UI State, like Zoom, in `dcc.Graph`