ID Error from Dash callback input when using html.Div as an Output

Hi,

I have a problem with getting an Output that I want in dash callback.
My layout has Tab and Table on the left side of the Div. What I’m trying to do is putting a graph in the right section of my layout that matches the button that i click inside the Table which is on the left side of my layout. Before doing this I wanted to check if the callback returns the correct Type of the button that i clicked. The problem is that nothing pops up when I click the button inside the Table.

I have two codes. Two codes are exactly the same except for the Output type(?) of the last callback. The first code has html.Span() as an Output and works fine. The second code has html.Div() as an Output and does not get the Input correctly causing “A nonexistent object was used in an Input of a Dash callback.” error.
Does anyone have any advice for this problem?

First code

app = Dash(external_stylesheets=[dbc.themes.BOOTSTRAP], suppress_callback_exceptions=True)

column_types = ['target', 'categorical', 'numeric']

tabs = html.Div([
    dbc.Tabs(
        [dbc.Tab(label=col_type.title(), tab_id=col_type) for col_type in column_types],
         id='tabs',
         active_tab=column_types[0],
    ),
    html.Div([html.Table(id='content')]),
], style={'width': '49%', 'float':'left'})

graph = html.Div([
         dcc.Store(id='selected_column'), html.Span(id='con')
    ], id='graph_section', style={'width': '49%', 'float': 'right'})

app.layout=html.Div([tabs,
                     graph,])

@app.callback(
    Output('content', 'children'),
    Input('tabs', 'active_tab')
)
def display_table(column_type):
    return generate_table(column_type)


@app.callback(
    Output('selected_column', 'data'),
    Input({"type": "button", "id": ALL}, "n_clicks"),
)
def get_triggered_column(clicks):
    if not any(clicks):
        return None
    
    triggered_id = ctx.triggered[0]["prop_id"].split(".")[0]
    triggered_column = json.loads(triggered_id)['id']

    return triggered_column


@app.callback(
    Output('con', 'children'),
    Input('selected_column', 'data'),
    Input('tabs', 'active_tab'),
)
def display_graph(selected_column, selected_column_type):
    if selected_column is None:
        return f'Please select a column, {selected_column}, {selected_column_type}'
    return f'triggered, {selected_column}, {selected_column_type}'

app.run(debug=True)

Second code

app = Dash(external_stylesheets=[dbc.themes.BOOTSTRAP], suppress_callback_exceptions=True)

column_types = ['target', 'categorical', 'numeric']

tabs = html.Div([
    dbc.Tabs(
        [dbc.Tab(label=col_type.title(), tab_id=col_type) for col_type in column_types],
         id='tabs',
         active_tab=column_types[0],
    ),
    html.Div([html.Table(id='content')]),
], style={'width': '49%', 'float':'left'})

graph = html.Div([
         dcc.Store(id='selected_column')
    ], id='graph_section', style={'width': '49%', 'float': 'right'})

app.layout=html.Div([tabs,
                     graph,])

@app.callback(
    Output('content', 'children'),
    Input('tabs', 'active_tab')
)
def display_table(column_type):
    return generate_table(column_type)


@app.callback(
    Output('selected_column', 'data'),
    Input({"type": "button", "id": ALL}, "n_clicks"),
)
def get_triggered_column(clicks):
    if not any(clicks):
        return None
    
    triggered_id = ctx.triggered[0]["prop_id"].split(".")[0]
    triggered_column = json.loads(triggered_id)['id']

    return triggered_column


@app.callback(
    Output('graph_section', 'children'),
    Input('selected_column', 'data'),
    Input('tabs', 'active_tab'),
)
def display_graph(selected_column, selected_column_type):
    if selected_column is None:
        return f'Please select a column, {selected_column}, {selected_column_type}'
    return f'triggered, {selected_column}, {selected_column_type}'

app.run(debug=True)

Hi @wonsub and welcome to the Dash community :slightly_smiling_face:

I think I see what’s going on. Let’s focus on the second code. This error is likely from this component:

graph = html.Div([
         dcc.Store(id='selected_column')
    ], id='graph_section', style={'width': '49%', 'float': 'right'})

To make it more clear, let’s rewrite this graph component to be more verbose

graph = html.Div(
    children=[
         dcc.Store(id='selected_column')
    ], 
    id='graph_section', 
    style={'width': '49%', 'float': 'right'}
)

The last callback is updating the children prop of the graph_section div, which currently contains the dcc.Store component. By doing this, the dcc.Store component is removed from the DOM, since the children prop is replaced. When another callback tries to access or update the dcc.Store, it can’t find it, leading to the “non-existent object” error.


2 Likes

Hi @AnnMarieW
Thank you for the explanation!!