Suddenly ids can't be found in app layout

I am creating an multipage app.

–CONTAINER PAGE | no errors–

import dash
from dash import dcc, html, dash_table
from dash.dependencies import Input, Output, State
import dash_bootstrap_components as dbc

app = dash.Dash(__name__, use_pages=True)

app.layout = html.Div([
    html.Div(id='navbar',
        children=[
        dbc.Col([
            html.H1(['File Wrangler']
            )
        ]),
        dbc.Col(html.Div([
                    html.Div(dcc.Link('Wrangler', href=dash.page_registry['pages.inv_wrang']['relative_path'])),
                    html.Div(dcc.Link('Dashboard', href=dash.page_registry['pages.inv_dash']['relative_path'])), #
                    html.Div(dcc.Link('Log', href=''))
                ],
                style={
                    'display':'flex',
                    'flex-direction':'row',
                    'justify-content':'space-around',
                    'align-items':'flex-end'}
                ),
            style={
                'width':300
                }
            )
    ],
    style={
        'display':'flex',
        'flex-direction':'row',
        'justify-content':'space-around',
        'align-items':'center',
        'border':'solid',
        'background':'pink'
    }),
    dash.page_container
])


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

–INDEX PAGE | errors–

here I have the same type of error of ids ‘wrang-save-button’, ‘upload-data’, ‘table-view’. All statin that:
"Attempting to connect a callback Input item to component:

  • “wrang-save-button”*
    but no components with that id exist in the layout.

If you are assigning callbacks to components that are
generated by other callbacks (and therefore not in the
initial layout), you can suppress this exception by setting
suppress_callback_exceptions=True.
This ID was used in the callback(s) for Output(s):

  • table-view.children"*

this page still works fine; until yesterday, I didn’t have any errors.

here’s the code:

import os
import io
import base64
import csv

import pandas as pd
import numpy as np

import dash
from dash import html, dash_table, dcc, Input, Output, State, callback
import dash_bootstrap_components as dbc
from dash.exceptions import PreventUpdate

from collections import OrderedDict

dash.register_page(__name__, path='/')


layout = html.Div([
    html.Div(id='wrang-page-container',
             children=[html.Div([
                 dbc.Col([
                     dcc.Upload(
                            id='upload-data',
                            children=html.Div([
                                'Drag & Drop / ',
                                html.A('Select Files')
                            ],
                            style={
                                'display':'flex',
                                'flex-wrap':'wrap',
                                'padding':'10px'
                            }),
                            style={
                                'width': '100%',
                                'height': '100px',
                                'lineHeight': '60px',
                                'borderWidth': '1px',
                                'borderStyle': 'dashed',
                                'borderRadius': '5px',
                                'textAlign': 'center'
                            },
                            multiple=False
                        )
                    ],
                    style={
                        'display':'flex',
                        'align-items':'center',
                        'padding':'10px 10px 10px 10px'
                    }),
                    dbc.Col(id='table-view',
                            children=[],
                    style={
                        'padding':'10px 10px 10px 10px'
                    }),
                    dbc.Col([
                        html.Button(id='wrang-save-button',
                                    children=['save'],
                                    n_clicks=0,
                        style={
                            'font-size':'150%', 
                            'width': '100px',
                            'height': '100px'
                            })
                    ],
                    style={
                        'display':'flex',
                        'align-items':'center',
                        'padding':'10px 10px 10px 10px'
                    })
                ],
                style={
                    'display': 'flex',
                    'justify-content':'space-around',
                    'border-style': 'solid',
                    'border-color': 'red'
                }),
    ],
    style={
        'border':'dashed'
    }),
    html.Div(id='dummy-div')
])


def parse_contents(contents, filename):
    global df
    content_type, content_string = contents.split(',')
    decoded = base64.b64decode(content_string)

    try:
        if 'csv' in filename:
            # Assume that the user uploaded a CSV file
            df = pd.read_csv(io.StringIO(decoded.decode('utf-8')), sep='\t', quoting=csv.QUOTE_NONE)
    except Exception as e:
        print(e)
        return html.Div([
            'Please load a csv file.'
        ])


    if df is not None:
        # Add a new column to the DataFrame
        df.columns = [x.replace('"','').replace(',','') for x in df.columns]
        df['Total ($)'] = [float(x.replace('$','').replace('"','').replace(',','')) for x in df['Total ($)']]
        df['Invoice #'] = [x.replace('"','') for x in df['Invoice #']]
        df[['Processed Date', 'Approved/Closed Date']] = np.nan
        df = df.loc[:20,['Invoice Status','Invoice #','Invoice Date','WTN','Processed Date',
                          'Approved/Closed Date','Vendor','Total ($)']]
        
        # Display the updated DataFrame in a table
        return html.Div([
            dash_table.DataTable( 
                    id='wrang-table-dropdown',
                    data=df.to_dict('records'),
                    style_table={'overflowX': 'auto', 'minWidth': '50%'},
                    style_cell={'textAlign': 'left'},
                    columns=[{'id': col, 'name': col} for col in df.columns]
            )
        ],
        style={
            'borderStyle':'solid',
            'padding':'10px 10px 10px 10px'
        }),df


@callback(Output('table-view', 'children'),
              Input('upload-data', 'contents'),
              Input('wrang-save-button','n_clicks'),
              State('upload-data', 'filename'))
def update_output(contents, n_clicks, filename):
    
    if contents is None:
        raise PreventUpdate
    else:
        children = [parse_contents(contents, filename)[0]]
        if n_clicks>0:
            df = parse_contents(contents, filename)[1]
            df.to_csv('src/wrangled invoices.csv',index=False)
            
        return children

–PAGE TWO | errors–
for completeness I include also page 2 which has similar structure and gives out the same type of errors as Index page for IDs ‘dash-save-button’ and ‘dummy-space’.

here’s the code

import pandas as pd
import numpy as np

import dash
from dash import html, dash_table, dcc, Input, Output, State, callback
import dash_bootstrap_components as dbc
from dash.exceptions import PreventUpdate



dash.register_page(__name__, path='/dashboard')

df_wrang = pd.read_csv('src/wrangled invoices.csv')

layout = html.Div([
    html.Div(id='dash-page-container',
             children=[
                dash_table.DataTable( 
                id='dash-table-dropdown',
                data=df_wrang.to_dict('records'),
                style_table={'overflowX': 'auto', 'minWidth': '50%'},
                style_cell={'textAlign': 'left'},
                columns=[{'id':'agent-dropdown', 'name': 'Agent', 'presentation':'dropdown'}] + 
                        [{'id':'c-status-dropdown', 'name':'Current Status', 'presentation':'dropdown'}] +
                        [{'id': col, 'name': col} for col in df_wrang.columns],
                style_data_conditional=[
                {
                    'if': {'filter_query': '{Invoice Status} = "In Progress"'},
                    'backgroundColor': 'red',
                    'color': 'white'
                },
                {
                    'if': {'filter_query': '{Invoice Status} = "Approved"'},
                    'backgroundColor': 'orange',
                    'color': 'white'
                },
                {
                    'if': {'filter_query': '{c-status-dropdown} = "Approved" && {Invoice Status} != "PLACE_HOLDER"'},
                    'backgroundColor': 'green',
                    'color': 'white'
                },
                {
                    'if': {'filter_query': '{c-status-dropdown} = "In Progress" && {Invoice Status} != "PLACE_HOLDER"'},
                    'backgroundColor': 'yellow',
                    'color': 'black'
                }
            ],
                editable=True,
                dropdown={
                    'agent-dropdown':{
                        'options':[
                            {'label':'Bianca','value':'Bianca'},
                            {'label':'Nobody','value':'Nobody'}
                        ],
                        'clearable':True
                    },
                    'c-status-dropdown':{
                        'options':[
                            {'label':'In Progress','value':'In Progress'},
                            {'label':'Approved','value':'Approved'}
                        ],
                        'clearable':True
                    }
                }
                
            )
             ]),
    html.Div([
        dbc.Col(id='col-button',
                children=[html.Button(id='dash-save-button',
                                      children=['Save'],
                                      n_clicks=0)
        ]),
        html.Div(id='dummy-space')
    ],
    style={
        'display':'flex',
        'justify-content':'space-between'
    })
])


@callback(
    Output('dummy-space','children'),
    Input('dash-save-button','n_clicks'),
    State('dash-table-dropdown','data')
)

def update_table(n_clicks, current_data):
    global lst
    if n_clicks > 0:
        lst = [row.get('c-status-dropdown','oops') for row in current_data]
        print(lst)
        return lst
    else:
        raise PreventUpdate

in both pages I can see the ids in the original layout so I don’t understand why the app claims they are not there.

Thanks for helping

Simone

Hey @zimo I commented out the code which throw syntax errors (not dash errors):

import dash
from dash import dcc, html, dash_table, Input, Output, State
import dash_bootstrap_components as dbc

app = dash.Dash(__name__, use_pages=True)

app.layout = html.Div([
    html.Div(id='navbar',
             children=[
                 dbc.Col([
                     html.H1(['File Wrangler']
                             )
                 ]),
                 dbc.Col(html.Div([
                     # html.Div(dcc.Link('Wrangler', href=dash.page_registry['pages.inv_wrang']['relative_path'])),
                     # html.Div(dcc.Link('Dashboard', href=dash.page_registry['pages.inv_dash']['relative_path'])),  #
                     html.Div(dcc.Link('Log', href=''))
                 ],
                     style={
                         'display': 'flex',
                         'flex-direction': 'row',
                         'justify-content': 'space-around',
                         'align-items': 'flex-end'}
                 ),
                     style={
                         'width': 300
                     }
                 )
             ],
             style={
                 'display': 'flex',
                 'flex-direction': 'row',
                 'justify-content': 'space-around',
                 'align-items': 'center',
                 'border': 'solid',
                 'background': 'pink'
             }),
    dash.page_container
])

if __name__ == '__main__':
    app.run(debug=True)

and the stuff related to your file parsing.

# import os
# import io
# import base64
# import csv
#
# import pandas as pd
# import numpy as np

import dash
from dash import html, dash_table, dcc, Input, Output, State, callback
import dash_bootstrap_components as dbc
from dash.exceptions import PreventUpdate

dash.register_page(__name__, path='/')

layout = html.Div([
    html.Div(id='wrang-page-container',
             children=[html.Div([
                 dbc.Col([
                     dcc.Upload(
                         id='upload-data',
                         children=html.Div([
                             'Drag & Drop / ',
                             html.A('Select Files')
                         ],
                             style={
                                 'display': 'flex',
                                 'flex-wrap': 'wrap',
                                 'padding': '10px'
                             }),
                         style={
                             'width': '100%',
                             'height': '100px',
                             'lineHeight': '60px',
                             'borderWidth': '1px',
                             'borderStyle': 'dashed',
                             'borderRadius': '5px',
                             'textAlign': 'center'
                         },
                         multiple=False
                     )
                 ],
                     style={
                         'display': 'flex',
                         'align-items': 'center',
                         'padding': '10px 10px 10px 10px'
                     }),
                 dbc.Col(id='table-view',
                         children=[],
                         style={
                             'padding': '10px 10px 10px 10px'
                         }),
                 dbc.Col([
                     html.Button(id='wrang-save-button',
                                 children=['save'],
                                 n_clicks=0,
                                 style={
                                     'font-size': '150%',
                                     'width': '100px',
                                     'height': '100px'
                                 })
                 ],
                     style={
                         'display': 'flex',
                         'align-items': 'center',
                         'padding': '10px 10px 10px 10px'
                     })
             ],
                 style={
                     'display': 'flex',
                     'justify-content': 'space-around',
                     'border-style': 'solid',
                     'border-color': 'red'
                 }),
             ],
             style={
                 'border': 'dashed'
             }),
    html.Div(id='dummy-div')
])


# def parse_contents(contents, filename):
#     global df
#     content_type, content_string = contents.split(',')
#     decoded = base64.b64decode(content_string)
#
#     try:
#         if 'csv' in filename:
#             # Assume that the user uploaded a CSV file
#             df = pd.read_csv(io.StringIO(decoded.decode('utf-8')), sep='\t', quoting=csv.QUOTE_NONE)
#     except Exception as e:
#         print(e)
#         return html.Div([
#             'Please load a csv file.'
#         ])
#
#     if df is not None:
#         # Add a new column to the DataFrame
#         df.columns = [x.replace('"', '').replace(',', '') for x in df.columns]
#         df['Total ($)'] = [float(x.replace('$', '').replace('"', '').replace(',', '')) for x in df['Total ($)']]
#         df['Invoice #'] = [x.replace('"', '') for x in df['Invoice #']]
#         df[['Processed Date', 'Approved/Closed Date']] = np.nan
#         df = df.loc[:20, ['Invoice Status', 'Invoice #', 'Invoice Date', 'WTN', 'Processed Date',
#                           'Approved/Closed Date', 'Vendor', 'Total ($)']]
#
#         # Display the updated DataFrame in a table
#         return html.Div([
#             dash_table.DataTable(
#                 id='wrang-table-dropdown',
#                 data=df.to_dict('records'),
#                 style_table={'overflowX': 'auto', 'minWidth': '50%'},
#                 style_cell={'textAlign': 'left'},
#                 columns=[{'id': col, 'name': col} for col in df.columns]
#             )
#         ],
#             style={
#                 'borderStyle': 'solid',
#                 'padding': '10px 10px 10px 10px'
#             }), df


@callback(Output('table-view', 'children'),
          Input('upload-data', 'contents'),
          Input('wrang-save-button', 'n_clicks'),
          State('upload-data', 'filename'))
def update_output(contents, n_clicks, filename):
    if contents is None:
        raise PreventUpdate
    else:
        children = "Hello"
        # if n_clicks > 0:
        #     df = parse_contents(contents, filename)[1]
        #     df.to_csv('src/wrangled invoices.csv', index=False)
        return children

No dash errors, so I can’t reproduce this.

dash v 2.16.1