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