How to make graphics interact with each other through clicks?(I need help)

Hello everyone, with this example code I ask someone to help me make the interaction between the chart, the table and the indicator.

import sqlalchemy as sa
from sqlalchemy import asc, create_engine
import fdb
import pandas as pd
import plotly
import plotly.graph_objects as go
import dash 
from dash import Dash, dcc, html, Input, Output, no_update
import dash_bootstrap_components as dbc

filb = ['fil1','fil2','fil3']
estoque = [10,20,25]

tupla_estoque = list(zip(filb,estoque))
df_estoque = pd.DataFrame(tupla_estoque, columns=['fil','estoque'])

filc = ['fil1','fil2','fil3']
cli = [15,30,25]

tupla_cli = list(zip(filc,cli))
df_cli = pd.DataFrame(tupla_estoque, columns=['fil','cli'])


fig_estoque = go.Figure(data=[
    go.Bar(x=df_estoque['fil'], y=df_estoque['estoque'],
           text=df_estoque['estoque'],
           textposition='auto',
           textfont_color='white', 
           marker_color='#00B0FF',
           )   
])
fig_estoque.update_traces(hoverinfo="none", hovertemplate=None)
fig_estoque.update_layout(title='Estoque por Filial Lily Belle',title_y=0.85, title_x=0.1, title_font_color='white', paper_bgcolor='rgba(0,0,0,0)', plot_bgcolor='rgba(0,0,0,0)')
fig_estoque.update_yaxes(showticklabels=False, showgrid=False)
fig_estoque.update_xaxes(tickfont_color='#ffffff', showgrid=False)

fig_table = go.Figure(data=[go.Table(
    header=dict(values=['Filial', 'Clientes novos c/ compra'],
                line_color='darkslategray',
                fill_color='lightskyblue',
                align='left'),
    cells=dict(values=[df_cli['fil'], # 1st column
                       df_cli['cli']], # 2nd column
               line_color='darkslategray',
               fill_color='lightcyan',
               align='left'))
])

fig_table.update_layout( paper_bgcolor='rgba(0,0,0,0)', plot_bgcolor='rgba(0,0,0,0)')

fig_new_clients = go.Figure(data=[go.Indicator(
    mode = "number",
    value = df_cli['cli'].sum(),
    title = {'text': "Novos clientes",'font':{'size': 20}},
    number= {'font': {'size': 18}}
    )])


fig_new_clients.update_layout ( showlegend = False, paper_bgcolor='rgba(0,0,0,0)', plot_bgcolor='white', font={'color':'white'})

      





app = Dash(__name__,external_stylesheets=[dbc.themes.SLATE])

app.layout = html.Div([
    html.H1('Dashboard interação', id='h1'),
        dbc.Col([
            dbc.Row([
                dbc.Col(dcc.Graph(id="graph", figure=fig_estoque, clear_on_unhover=True,style={'width':'75vh','margin-right':'20px'} ),lg=4)
                ]),
                ]),
            dbc.Row(dcc.Graph(id='cli_novo',style={'height':'10vh'},figure=fig_new_clients)),
            dbc.Row(dcc.Graph(id='tabela_clientes_compra',style={'width':'65vh', 'height':'35vh'},figure=fig_table))
            ], style={'margin-top':'55px'})
        
             


    

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

For example, when clicking on one of the bars, the indicator shows new customers only from the branch of the respective bar and the table as well, and if you click on the information in the table, the same effect occurs on the bar chart and the indicator

Hi,

Here are some links and a high-level explanation on how to implement this (I don’t have a complete example with both the table and the barchart).

Firstly, you have to replace go.Table by the dash_table.DataTable component, since the table in graph objects does not support click events (besides the other one is much better). Your table would be simply:

from dash import dash_table

dash_table.DataTable(
    id="tabela_clientes_compra",
    data=df_cli.to_dict("records"),
    columns=[{"id": col, "name": col} for col in df_cli.columns],
    row_selectable="single",
    selected_rows=[],
)

Then I would take a look on this page. clickData is the prop that you need in the figure to trigger the callback. The part under “Generic Crossfiltering Recipe” might also be interesting, as you could use selectedpoints when the filter event comes from the data table.

For the DataTable interaction, I would recommend this example from the documentation, where a row selection highlights the bar in the figure by changing its color. Note that in this example the bars are not really selected in the figure, they simply have a different color. Therefore, instead of changing the bar color on row selection, you can pass the bar index to selectedpoints.

Lastly, I think it is a bit overkill to use go.Indicator to show a simple number, especially if you are using the constructor go.Figure in the callbacks… One way to speed this up is to send State("cli_novo", "figure") (say prev_indicator) to the callbacks, so instead of recreating the figure you can just update prev_indicator, which is a dictionary.

Please let us know if you have problems implementing this. It should be straightforward and you can learn a bunch by trying… :slightly_smiling_face:

2 Likes

Thank you very much, with this path I’m almost done, but I’ve found a new barrier.

The graphics that will interact with each other have dropdown inputs and I’m not able to make the callback work because it uses the same output that is a figure.

Any tips?

Hi @NOVOSYS

That is a common issue. You could include all components in a single callback and use callback context

You could also install the dash-extensions package and use Multiplexer Transform

1 Like