Popping a modal when clicking on a bar of a Bar chart

I have a bar chart graph with labels that pop up when we change colors and I would like to get rid of these things when I hover and create a Modal when I click on the bar chart. Do you know how I can handle that? I tried something but nothing appears.

I knew how to do it with a datatable. But here I have a Bar chart, I added a Modal object at the end of the layout but I’m not able to make it pop up despite …

Here is part of my source code for a minimal reproducible example:

def layout():
    """
    The layout of the attributes webpage
    :return: dash_html_components.Div
    """
    return html.Div([
        # Dropdown with all the required items and a default value.
        dcc.Dropdown(
            id='perfume-dropdown',
            options=[{'label': x, 'value': x} for x in data.keys()],
            value='My Burberry - Eau de Parfum'
        ),
        html.Div(id='dd-output-container'),
        # graph of the proportion of attributes in claimed and perceived benefits.
        html.Div([
            dcc.Graph(id='graph-attributes')
        ]),
        dbc.Modal(
            [
                dbc.ModalHeader("Header"),
                dbc.ModalBody("This is the content of the modal"),
                dbc.ModalFooter(
                    dbc.Button("Close", id="close", className="ml-auto")
                ),
            ],
            size="xl",
            id="modal",
        ),
        # calling necessary script for colors
        mathjax_script
    ])


@app.callback(
    Output(component_id='graph-attributes', component_property='figure'),
    [Input(component_id="perfume-dropdown", component_property="value")]
)
def update_graph(my_dropdown):
    """
    Plot the graph of the presence of attributes of product with the name my_dropdown selected in the dropdown.
    :param my_dropdown: the name of the product.
    :return: a figure.
    :rtype: plotly.graph_objs
    """
    data_dropdown = {item: data.get(item)for item in [my_dropdown]} # data.get(my_dropdown, default=None) {item:data.get(item)for item in my_dropdown}
    traces = []
    ticks = []
    colors = []
    d_product = {key: value for (key, value) in data_dropdown[my_dropdown].items()
                 if key not in ['TotalResults', 'Description', 'ReviewTexts']}
    # d_product = sorted(d_product.items(), reverse=True, key=lambda x: x[1].get("perceived_benefit", 0.0))
    d_product = {key: value for (key, value) in sorted(d_product.items(), key=lambda e: e[1]["perceived_benefit"])}
    for key, value in d_product.items():
        if key != 'TotalResults':
            trace_claimed = go.Bar(y=[key], x=[value['perceived_benefit']],
                                   name=key + ' Perceived', orientation='h')
            tick = key

            if value['claimed_benefit'] > 0:
                color = 'red'
            else:
                color = 'blue'

            ticks.append(tick)
            colors.append(color)
            traces.append(trace_claimed)

    keys = dict(zip(ticks, colors))
    ticktext = [get_color(v, k) for k, v in keys.items()]

    figure = go.Figure(data=traces,
                       layout=go.Layout(title='Score des parfums sur les attributs',
                                        barmode='stack')
                       )

    figure.update_layout(
        yaxis=dict(tickmode='array', ticktext=ticktext, tickvals=ticks),
        xaxis = dict(
            showgrid=False,
            ticks='',
            showticklabels=False,
        )
    )

    figure.update_layout(
        title="Présence des attributs dans les commentaires du produit",
        xaxis_title="Occurence",
        legend_title="Attributs",
    )

    return figure

def get_comments(word, my_dropdown):
    return [comment for comment in data[my_dropdown]['ReviewTexts'] if word in comment]


@app.callback(Output('modal', 'children'),
              [Input('graph-attributes', 'clickData'),
               Input(component_id="perfume-dropdown", component_property="value")],
              # [State('modal', 'is_open')]
              )
def set_content(clickData, my_dropdown):
    print(clickData)
    word = clickData['points'][0]['y']

    return [
        dbc.ModalHeader(word),
        dbc.ModalBody(
            html.Div([
                html.Div([
                    html.H6('Sales', style={'textAlign': 'center', 'padding': 10}),
                    html.P(get_comments(word, my_dropdown), id="comments", style={'textAlign': 'center', 'padding': 10})
                ], className='pretty_container four columns'),
            ])),
        dbc.ModalFooter(dbc.Button("Close", id="close"))
    ]

But no modal shows up, and no error either …

Here is a small sample for data:

{
  "My Burberry - Eau de Parfum": {
    "TotalResults": 59,
    "Description": "Inspir\u00e9e du trench coat, de l'h\u00e9ritage stylistique et de la tradition artisanale britanniques, My Burberry capture le parfum d\u2019un jardin londonien apr\u00e8s la pluie. Grand parfum floral r\u00e9v\u00e9lant une signature britannique contemporaine, la fragrance s'\u00e9panouit autour d'un d\u00e9licat c\u0153ur de rose rehauss\u00e9 d\u2019une pointe originale de feuille de g\u00e9ranium. Les notes de t\u00eate compos\u00e9es de pois de senteur et de bergamote se fondent dans un c\u0153ur de g\u00e9ranium, de coing dor\u00e9 et de freesia adoucies par les notes de fond de patchouli et de roses damascena et centifolia rafra\u00eechies par la pluie.",
    "ReviewTexts": [
      "Si vous cherchez qqch floral et pas du tout sucr\u00e9 - voil\u00e0 , MY Burberry est pour vous! Surtout en version EDP ! J'ai achet\u00e9 deja la troisieme pour l'hiver :) uniquement.",
      "J\u2019adore ce parfum, appr\u00e9ci\u00e9 aussi de tout mon entourage, il me fait me sentir f\u00e9minine, \u00e9l\u00e9gante et myst\u00e9rieuse. Il sent toute la journ\u00e9e sans \u00eatre capiteux. Parfait pour les jeunes femmes !",
      "Jai sentie ce parfum il y a quelques ann\u00e9es, d\u00e9j\u00e0. J'adorais son odeur j'ai fini par craqu6er il y a quelques ann\u00e9es et depuis c'est devenu mon top 1. Mon parfum doudou qui me r\u00e9conforte en toute circonstance. Un must have \u00e0 avoir dans sa salle de bain.",
      "My Burberry  tient longtemps et l'odeur est tout simplement sublime! Sensuel, doux et glamour mais tr\u00e8s frais \u00e0 la fois. mettez ce parfum et vous serez combl\u00e9es. Ce parfum tient toute la journ\u00e9e"
    ],
    "je me sens bien": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.0
    },
    "romantique": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.0
    },
    "me convient bien": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.01694915254237288
    },
    "f\u00e9minin": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.03389830508474576
    },
    "sensuel / sexy": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.0
    },
    "nettoyer": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.0
    },
    "facile a porter": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.22033898305084745
    },
    "haute qualite": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.0
    },
    "elegante / sophistiquee": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.0
    },
    "jeune / juvenile": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.15254237288135594
    },
    "moderne": {
      "claimed_benefit": 1,
      "perceived_benefit": 0.11864406779661017
    },
    "sucr\u00e9": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.0847457627118644
    },
    "naturel": {
      "claimed_benefit": 1,
      "perceived_benefit": 0.13559322033898305
    },
    "pour le soir / nuit": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.288135593220339
    },
    "frais": {
      "claimed_benefit": 1,
      "perceived_benefit": 0.288135593220339
    },
    "doux": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.423728813559322
    },
    "lumi\u00e8re": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.2542372881355932
    },
    "classique": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.0
    },
    "chaud": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.11864406779661017
    },
    "audacieux": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.0
    },
    "humide": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.0
    },
    "poudreux": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.0
    },
    "herbes aromatiques": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.0
    },
    "a du caractere": {
      "claimed_benefit": 1,
      "perceived_benefit": 0.1864406779661017
    },
    "sportif": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.0
    },
    "aquatique / marine": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.0
    },
    "floral": {
      "claimed_benefit": 1,
      "perceived_benefit": 0.03389830508474576
    },
    "nouveau / jamais respire avant": {
      "claimed_benefit": 1,
      "perceived_benefit": 0.15254237288135594
    },
    "savonneux": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.0
    },
    "pour la journee": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.0
    },
    "n'oublier": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.0
    },
    "vanille": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.0
    },
    "fruit\u00e9": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.0
    },
    "masculin": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.0
    },
    "citronn\u00e9": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.01694915254237288
    },
    "enfum\u00e9": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.0
    },
    "vert / herbe-like": {
      "claimed_benefit": 1,
      "perceived_benefit": 0.06779661016949153
    },
    "oriental": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.0
    },
    "\u00e9pic\u00e9": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.0
    },
    "alimentaire": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.0
    },
    "bois\u00e9": {
      "claimed_benefit": 0,
      "perceived_benefit": 0.0
    }
  }
}

I tried with a smaller example there, but I’m stull not able to pop up anything:

enter image description here

Here is a minimal reproducible example:

import dash
import dash_core_components as dcc
import dash_bootstrap_components as dbc
import dash_html_components as html
import plotly.graph_objs as go
import pandas as pd
from dash.dependencies import Input, Output

df = pd.read_excel("https://github.com/chris1610/pbpython/blob/master/data/salesfunnel.xlsx?raw=True")
pv = pd.pivot_table(df, index=['Name'], columns=["Status"], values=['Quantity'], aggfunc=sum, fill_value=0)

trace1 = go.Bar(x=pv.index, y=pv[('Quantity', 'declined')], name='Declined')
trace2 = go.Bar(x=pv.index, y=pv[('Quantity', 'pending')], name='Pending')
trace3 = go.Bar(x=pv.index, y=pv[('Quantity', 'presented')], name='Presented')
trace4 = go.Bar(x=pv.index, y=pv[('Quantity', 'won')], name='Won')

app = dash.Dash()

app.layout = html.Div(children=[
    html.H1(children='Sales Funnel Report'),
    html.Div(children='''National Sales Funnel Report.'''),
    dcc.Graph(
        id='graph',
        figure={
            'data': [trace1, trace2, trace3, trace4],
            'layout':
                go.Layout(title='Order Status by Customer', barmode='stack')
        }),
    dbc.Modal(
        [
            dbc.ModalHeader("Header"),
            dbc.ModalBody("This is the content of the modal"),
            dbc.ModalFooter(
                dbc.Button("Close", id="close", className="ml-auto")
            ),
        ],
        size="xl",
        id="modal",
    )
])


@app.callback(
    Output('modal', 'children'),
    [Input('graph', 'clickData')])
def display_click_data(clickData):
    print("clickData: ", clickData)
    return [
        dbc.ModalHeader("Test"),
        dbc.ModalBody(
            html.Div([
                html.Div([
                    html.H6('Sales', style={'textAlign': 'center', 'padding': 10}),
                    html.P("Bitch", id="sales_stocks", style={'textAlign': 'center', 'padding': 10})
                ], className='pretty_container four columns'),
                html.Div([
                    html.H5('Current ratio', style={'textAlign': 'center', 'padding': 10})
                ], className='pretty_container seven columns')
            ])),
        dbc.ModalFooter(dbc.Button("Close", id="close"))
    ]


# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    app.run_server(debug=True)