0

I'm trying to make a dashtable and its columns will be change dynamically based on dropdowns value.

Below is my sample code:

import pandas as pd
import numpy as np
import plotly.express as px
import dash
from dash import html
from dash import dcc
from dash.dependencies import Input, Output,State
import dash_bootstrap_components as dbc
import plotly.graph_objects as go
from dash import dash_table

df1 = pd.DataFrame({
    'Contract No': ['VN122001','VN122002','VN122003','VN122004','VN122005'],
    'Amount': [22071,20775,20841,21891,22395]})
df1 = df1.set_index('Contract No')

df2 = pd.DataFrame({
    'Contract No': ['VN122001','VN122002','VN122003','VN122004','VN122005'],
    'Cusname': ['A','B','C','D','E'],
    'Branch': ['HN','HCM','HP','BN','DN']})
df2 = df2.set_index('Contract No')

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

app.layout = html.Div([
    dbc.Row([   
            dbc.Col([
                    dcc.Dropdown(id='columns_name',placeholder="Columns name", # Dropdown for heatmap color
                    options=list_column, 
                    value='Cusname',
                    multi=False,
                    disabled=False,
                    clearable=True,
                    searchable=True)    
                    ],width={'size':4,'offset':0,'order':1},style={'padding-top' : 15}),
    ]),
    dbc.Row([
        html.Div(
        id = 'tableDiv',
        className = 'tableDiv'
    )
    ])
])

@app.callback(Output('tableDiv', 'children'),
             [Input('columns_name', 'value')])
              
def update_columns_name(columns):
    col_name = df2[[columns]] 
    df3 = pd.merge(df1, col_name, left_index=True, right_index=True)
    df3 = df3.reset_index()
    mycolumns = [{'name': i, 'id': i} for i in df3.columns]
    return html.Div([
                dash_table.DataTable(
            id='table',
            columns=mycolumns,
            data=df3.to_dict("rows")
         )
        ])
if __name__ == "__main__":
    app.run_server(debug=False,port=1222)

Actually it is working well but when I try to create Tabs and then return it to Tab, nothing show. Below is my code to create Tab.

app.layout = html.Div([dbc.Tabs(
            [dbc.Tab(label="Dashboard", tab_id="dashboard"),
            dbc.Tab(label="Table", tab_id="table"),
            ],
            id="tabs",
            active_tab="dashboard"),
    html.Div(id="tab-content", className="p-4"),
    ])

@app.callback(
    Output("tab-content", "children"),
    [Input("tabs", "active_tab")])

def render_tab_content(active_tab):
    if active_tab == "dashboard":
        return html.Div([dbc.Row([html.H5('Graphs')])])
    elif active_tab == "table":
        return html.Div([
        dbc.Row([
        html.Div(id = 'tableDiv',
        className = 'tableDiv')
    ])
])
    
@app.callback(Output('tableDiv', 'children'),
             [Input('columns_name', 'value')])
              
def update_columns_name(columns):
    col_name = df2[[columns]] 
    df3 = pd.merge(df1, col_name, left_index=True, right_index=True)
    df3 = df3.reset_index()
    mycolumns = [{'name': i, 'id': i} for i in df3.columns]
    return html.Div([
            dash_table.DataTable(
            id='table',
            columns=mycolumns,
            data=df3.to_dict("rows"))
        ])
if __name__ == "__main__":
    app.run_server(debug=False,port=1222)   

What should I do to fix this issue. Thank you.

1 Answer 1

1

This is the error javascript throws back in the browser console:

Object { message: "ID not found in layout", html: "Attempting to connect a callback Output item to component:\n \"tableDiv\"\nbut no components with that id exist in the layout.\n\nIf you are assigning callbacks to components that are\ngenerated by other callbacks (and therefore not in the\ninitial layout), you can suppress this exception by setting\n```suppress_callback_exceptions=True```.\nThis ID was used in the callback(s) for Output(s):\n tableDiv.children" } dash_renderer.v2_1_0m1644023699.min.js:2:84904

Object { message: "ID not found in layout", html: "Attempting to connect a callback Input item to component:\n \"columns_name\"\nbut no components with that id exist in the layout.\n\nIf you are assigning callbacks to components that are\ngenerated by other callbacks (and therefore not in the\ninitial layout), you can suppress this exception by setting\n```suppress_callback_exceptions=True```.\nThis ID was used in the callback(s) for Output(s):\n tableDiv.children" }

As it suggests, you are referring to id components that are generated by another callback (namely, callback render_tab_content generates the tableDiv div and is being referred to by update_column_name). This is a problem, as your tableDiv won't be present when you select the dashboard table but the callback may still be invoked (at least initially which is why you are having an issue to begin with).

It's best to perhaps have the contents of update_column_name combined with render_table_content and generate the column stuff you need through the one callback. You don't really gain anything from splitting into 2 callbacks in this instance, and if you really want, you can abstract the contents of the other callback into a normal function and just call it in render_tab_content. Here is a suggested adaptation:

def update_columns_name(columns):
    col_name = df2[[columns]]
    df3 = pd.merge(df1, col_name, left_index=True, right_index=True)
    df3 = df3.reset_index()
    mycolumns = [{'name': i, 'id': i} for i in df3.columns]
    return (
        html.Div([
            dbc.Row([
                html.Div([
                    html.Div([
                        dash_table.DataTable(
                            id='table',
                            columns=mycolumns,
                            data=df3.to_dict("rows")
                        )
                    ])
                ],
                    id='tableDiv',
                    className='tableDiv')
            ])
        ])
    )


@app.callback(
    Output("tab-content", "children"),
    [Input("tabs", "active_tab")],
    [State('columns_name', 'value')]
)
def render_tab_content(active_tab, columns):
    print(active_tab, columns)
    if active_tab == "dashboard":
        return html.Div([dbc.Row([html.H5('Graphs')])])
    elif active_tab == "table":
        return update_columns_name(columns)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.