Interactive visuals using plotly

I have created two graphs and a dropdown using plotly dash. When I select a value from the dropdown the first graph shows the data based on it and when i hover over the point in the first graph the second bar graph will get filtered based on the hover data from the first graph. I have accomplished this but when I clear the dropdown and reselect a value from the dropdown the second graph still shows the data based on the previous hovered data from the first graph. I want to clear the hovered data from the first graph once i clear the dropdown. Please share the solution for the above issue.

hi @Akshaya
:wave: welcome to the community. That’s a good question.

Maybe you could add Input('dropdown-id', 'value') to the callback that generates the second bar graph. And configure the callback function as:

def create_second_bar_graph(hover_data, value):
    if value is None or len(value)==0:
        fig = remake the px.bar() however you like.
        return fig

Hi @adamschroeder ,
Thank you for your quick response.
I have tried this solution but it isn’t working for me.
It throws an error object of type ‘NoneType’ has no len().
So I removed this condition len(value)==0 and executed the code but still it’s not working. The second graph is showing the data based on the previous hover point until we hover over the new point in the first graph.

Below is my code

@app.callback(
    Output(component_id='Count-Resources-By-Lead',component_property='figure'),
    Input(component_id='Allocation-By-Resource', component_property= 'hoverData'),
    Input(component_id='Resource_dropdown',component_property='value'),
    Input(ThemeSwitchAIO.ids.switch("theme"),"value")
)
def update_Resources_By_Lead_Graph(hoverData,selected_person,toggle):
    template=template_theme2 if toggle else template_theme1
    if selected_person is None:
       line_fig=px.bar(df_Resources,x='Lead',y='Total Resources',title='Count of Resources By Lead',text='Total Resources',template=template)  
    else:
       dff=df_Resources[df_Resources['Lead']==hoverData['points'][0]['customdata']]
       line_fig=px.bar(dff,x='Lead',y='Total Resources',title='Count of Resources By Lead',text='Total Resources',template=template)
      
    return line_fig

Hi @Akshaya
You’re right. I should have separated that line of code. First, we check if the value is None because if the app starts with no value set to the dropdown, the value will be equal to None. Then, we check if len(value)==0, only if your dropdown has multi=True, for when user chooses a value and then clears the dropdown options: that would result in length of value list equaling zero. Try to see if this works:

def update_Resources_By_Lead_Graph(hoverData,selected_person,toggle):
    template=template_theme2 if toggle else template_theme1
    if selected_person is None:
       line_fig=px.bar(df_Resources,x='Lead',y='Total Resources',title='Count of Resources By Lead',text='Total Resources',template=template) 
    if selected_person is not None:
        if len(selected_person)==0:
            line_fig=px.bar(....) # build a default bar graph you want the user to see if dropdown options are cleared
            return line_fig
        if len(selected_person)>0:
            dff=df_Resources[df_Resources['Lead']==hoverData['points'][0]['customdata']]
            line_fig=px.bar(dff,x='Lead',y='Total Resources',title='Count of Resources By Lead',text='Total Resources',template=template)
            return line_fig
      

Hi @adamschroeder ,
I tried the above code. It works when the selected person is None which displays the default graph and if I select a value from the dropdown and hover over the first graph the second graph gets filtered. But once I clear the dropdown the first hover point from the first graph is acting like a cache which gets stored and when a value is selected from the dropdown again it immediately filters the default (second graph) before I hover over the first graph itself.
My Requirement
I want to show the default data in the second graph unless and until I hover over the first graph. Below is my code.

def update_Resources_By_Lead_Graph(hoverData,selected_person,toggle):
    template=template_theme2 if toggle else template_theme1
    if selected_person is None:
       line_fig=px.bar(df_Resources,x='Lead',y='Total Resources',title='Count of Resources By Lead',text='Total Resources',template=template)  
    if selected_person is not None:
        if len(selected_person)==0:
             line_fig=px.bar(df_Resources,x='Lead',y='Total Resources',title='Count of Resources By Lead',text='Total Resources',template=template)  
        if len(selected_person)>0:
            dff=df_Resources[df_Resources['Lead']==hoverData['points'][0]['customdata']]
            line_fig=px.bar(dff,x='Lead',y='Total Resources',title='Count of Resources By Lead',text='Total Resources',template=template)  
    return line_fig

I see what you mean. There might be a few options to tackle this. Have you seen the clear_on_unhover property of the dcc.Graph?
By default, it is equal to False, which means that the hoverData property will be equal to the data from the last point that was hovered over. But if you change it to True, This will set the hoverData to None on unhover.

If you choose to use this, you would need to update your code:

if len(selected_person)>0 and hoverData is not None:
            dff=df_Resources[df_Resources['Lead']==hoverData['points'][0]['customdata']]
            line_fig=px.bar(dff,x='Lead',y='Total Resources',title='Count of Resources By Lead',text='Total Resources',template=template)  
elif len(selected_person)>0 and hoverData is None:
       line_fig=px.bar(df_Resources,x='Lead',y='Total Resources',title='Count of Resources By Lead',text='Total Resources',template=template) 

Let me know if this works for you.

Thank you so much ! It worked . I have applied this condition (hoverData is not None) and set the clear_on_unhover property to True and also modified the code a little as per my requirement. The issue has been resolved.
Thanks again:)

@adamschroeder , Sure! I have marked that post as solution:)

1 Like