Hey Guys, been learning Dash for 3 days now non stop. Just wanted to build a simple application to then record as GIF/Lotto animation to put on the landing page. But this simple example does not work for some reason.
All i want is a simple callback from the button thats it, there are no bugs, nothing on console and for some odd reason nothing prints on callbacks aswell. Tried all online suggested stuff and chat gpt’d the hell outta this, no luck. Back to consulting you pros.
Python Version = 3.11
Plotly version = 5.15.0
Dash Version = 2.11.1
What i tried: Built a simple MRE which worked
from dash import Dash, html, Input, Output
app = Dash(__name__)
app.layout = html.Div([
html.Button('Search', id='button-render'),
html.Div(id='terminal-text-action'),
html.Div(id='table-container'),
])
@app.callback(
[Output('terminal-text-action', 'children'),
Output('table-container', 'children')],
Input('button-render', 'n_clicks'),
prevent_initial_call=True
)
def update_content(n_clicks):
terminal_text = ""
table = ""
if n_clicks == 1:
terminal_text = "First click message."
table = html.Table([
html.Tr([html.Th("Rate of Change"), html.Th("QT")]),
html.Tr([html.Td("12"), html.Td("Q1-22")]),
])
elif n_clicks >= 2:
terminal_text = "Second click message."
table = html.Table([
html.Tr([html.Th("LOB"), html.Th("%")]),
html.Tr([html.Td("lob-1"), html.Td("12%")]),
])
return terminal_text, table
if __name__ == '__main__':
app.run_server(debug=True)
But the main app just doesnt (Latest dash and python):
Main script (app.py)
from dash import dcc, html, Dash
from dash.dependencies import Input, Output
import page1
import page2
app = Dash(__name__)
app.layout = html.Div([
dcc.Location(id='url', refresh=False),
html.Div(id='page-content')
])
@app.callback(
Output('page-content', 'children'),
[Input('url', 'pathname')]
)
def display_page(pathname):
if pathname == '/page1':
return page1.layout
elif pathname == '/page2':
return page2.layout
else:
return '404 Page Not Found'
if __name__ == '__main__':
app.run_server(debug=True)
Page 1 (This is where the bug is):
from dash import html, dcc
from navbar import Navbar
import pandas as pd
from dash import dash_table
from dash import Output, Input, State
from app import app
from dash.exceptions import PreventUpdate
import pandas as pd
def create_first_table():
data = {
'Rate of Change': [12, 14, 15, 15, 16, 15, 16, 16],
'QT': ['Q1-22', 'Q2-22', 'Q3-22', 'Q4-22', 'Q1-23', 'Q2-23', 'Q3-23', 'Q4-23']
}
df = pd.DataFrame(data)
return dash_table.DataTable(data=df.to_dict('records'), columns=[{'name': i, 'id': i} for i in df.columns])
def create_second_table():
data = {
'LOB': ['lob-1', 'lob-2', 'lob-3', 'lob-4'],
'%': ['12%', '14%', '33%', '46%']
}
df = pd.DataFrame(data)
return dash_table.DataTable(data=df.to_dict('records'), columns=[{'name': i, 'id': i} for i in df.columns])
# Read the CSV file
mom_data = pd.read_csv('MOM_data.csv')
@app.callback(
[Output('terminal-text-action', 'children'),
Output('table-container', 'children')],
Input('button-render', 'n_clicks'),
prevent_initial_call=True # Prevents the callback from being triggered on page load
)
def update_content(n_clicks):
print(f"Callback triggered with n_clicks: {n_clicks}") # Debug print
if n_clicks == 1:
terminal_text = "It looks like there was a minor reduction in claims being filed manually, further more progress looks to have stagnated in 2023. Want me to dive deep into it?"
table = create_first_table()
elif n_clicks >= 2: # Corrected condition
terminal_text = "Looks like Lob-1 and Lob 2 received the lowest % of auto claims compared to rest."
table = create_second_table()
else:
raise PreventUpdate
return terminal_text, table
layout = html.Div([
Navbar(),
# Search Box and Button
html.Div([
dcc.Input(type='text', value='', placeholder='Enter Query Here', className='query-input'),
html.Button('Search', id='button-render')
], className='search-box'),
# Terminal Text Div
html.Div(id='terminal-text-action', className='terminal-text'),
# Table Div
html.Div(id='table-container'),
# Dashboard Block
html.Div([
html.H2('CRP SEGMENT', className='dashboard-title'),
# KPI Blocks
html.Div([
# KPI Block 1: Overall Claims
html.Div([
html.H3('Overall Claims'),
html.Div([
html.Div([
html.Div('2022', className='kpi-year'),
html.Div('118.7M', className='kpi-value')
], className='kpi-segment'),
html.Div([
html.Div('2023', className='kpi-year'),
html.Div('97.56M', className='kpi-value')
], className='kpi-segment')
], className='kpi-row'),
], className='kpi-block'),
# KPI Block 2: Defect Volume
html.Div([
html.H3('Defect Volume'),
html.Div([
html.Div([
html.Div('2022', className='kpi-year'),
html.Div('4.39M', className='kpi-value')
], className='kpi-segment'),
html.Div([
html.Div('2023', className='kpi-year'),
html.Div('3.30M', className='kpi-value')
], className='kpi-segment')
], className='kpi-row'),
], className='kpi-block'),
# KPI Block 3: FSA %
html.Div([
html.H3('FSA %'),
html.Table([
html.Thead([
html.Tr([
html.Th('Type'),
html.Th('2023')
])
]),
html.Tbody([
html.Tr([
html.Td('Auto'),
html.Td('96.63%')
]),
html.Tr([
html.Td('Manual'),
html.Td('91.77%')
]),
html.Tr([
html.Td('Overall'),
html.Td('96.20%')
])
])
], className='kpi-table')
], className='kpi-block')
], className='kpi-blocks'),
# MOM Table: Auto/Manual Distribution
html.Div([
html.H2('MOM: Auto/Manual Distribution', className='table-title'),
dash_table.DataTable(
id='mom-table',
columns=[{"name": i, "id": i} for i in mom_data.columns],
data=mom_data.to_dict('records'),
style_table={'overflowX': 'scroll'},
style_cell={'textAlign': 'center'},
merge_duplicate_headers=True
)
], className='mom-table-container')
], className='dashboard-block'),
])
CSS:
/* Terminal Text Div */
.terminal-text {
background-color: #000; /* Black background for terminal-like appearance */
color: #00ff00; /* Green text color */
padding: 20px;
font-family: monospace;
white-space: pre;
overflow: auto;
margin: 20px;
border-radius: 5px;
}
/* Table Div */
#table-container {
padding: 20px;
background-color: #f9f9f9;
border-radius: 10px;
box-shadow: 0px 1px 5px rgba(0, 0, 0, 0.1);
margin: 20px;
}
.dash-table-container .dash-spreadsheet-container .dash-spreadsheet-inner {
border-radius: 5px;
box-shadow: 0px 1px 5px rgba(0, 0, 0, 0.1);
}
@keyframes loading {
0% { content: "."; }
33% { content: ".."; }
66% { content: "..."; }
100% { content: "."; }
}
.loading:before {
content: "Loading";
animation-name: loading;
animation-duration: 1s;
animation-timing-function: step-start;
animation-iteration-count: infinite;
}
.navbar {
background-color: #f9f9f9;
color: black;
padding: 15px;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: 0px 1px 5px rgba(0, 0, 0, 0.1);
font-family: 'Arial', sans-serif; /* Modern font */
}
.dashboard-block {
padding: 20px;
background-color: #f9f9f9;
border-radius: 10px;
box-shadow: 0px 1px 5px rgba(0, 0, 0, 0.1);
}
.dashboard-title {
text-align: center;
color: #333;
font-weight: 600;
margin-bottom: 20px;
}
.kpi-blocks {
display: flex;
justify-content: space-between;
}
.kpi-block {
background-color: #fff;
padding: 20px;
border-radius: 10px;
box-shadow: 0px 1px 5px rgba(0, 0, 0, 0.1);
flex: 1;
margin: 0 10px;
}
.kpi-block h3 {
font-size: 1.2rem; /* Bigger header size */
text-align: center;
margin-bottom: 15px;
color: #333;
font-weight: 600;
}
.kpi-segment {
display: flex;
flex-direction: column;
align-items: center;
margin: 5px 10px; /* Additional margin for differentiation */
padding: 10px;
background-color: #f5f5f5; /* Background color for differentiation */
border-radius: 5px;
}
/* Rest of the CSS code */
.logo {
font-size: 26px;
font-weight: 900;
color: #333; /* Dark gray color for the logo */
}
.search-bar {
display: flex;
align-items: center;
flex-grow: 1;
justify-content: center;
}
.search-icon {
background-image: url('search.svg');
background-size: contain;
width: 32px;
height: 32px;
margin-right: 10px;
}
.search-input {
width: 300px;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
transition: border 0.3s; /* Smooth transition for the search input */
}
.search-input:focus {
border-color: #333; /* Darker border when the search input is focused */
}
.header-links {
display: flex;
gap: 20px;
align-items: center;
}
.header-links a {
color: #333; /* Dark gray color for the links */
text-decoration: none;
transition: all 0.3s; /* Smooth transition for hover effects */
font-weight: 600; /* Semi-bold weight for the links */
}
.header-links a:hover {
color: #000; /* Black color on hover */
text-decoration: underline; /* Underline on hover */
}
.user-name {
margin-right: 10px;
font-weight: 600; /* Semi-bold weight for the user name */
}
.user-image {
width: 40px;
height: 40px;
border-radius: 50%;
border: 2px solid #333; /* Border around the user image */
}
.content {
padding: 20px;
}
.search-box {
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.query-input {
width: 400px;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
font-size: 16px;
}
.search-button {
background-color: #007bff;
color: white;
border: none;
padding: 10px 20px;
margin-left: 10px;
border-radius: 5px;
cursor: pointer;
transition: all 0.3s; /* Smooth transition for hover effects */
}
.search-button:hover {
background-color: #0056b3; /* Darker color on hover */
}
.kpi-row {
display: flex;
justify-content: space-between;
}
.kpi-year {
text-align: center;
font-weight: 500;
color: #555;
}
.kpi-segment {
display: flex;
flex-direction: column;
align-items: center;
}
.kpi-table {
width: 100%;
border-collapse: collapse;
text-align: center;
}
.kpi-table th, .kpi-table td {
border: 1px solid #ddd;
padding: 10px;
}
.kpi-table th {
background-color: #f2f2f2;
}
.kpi-value {
text-align: center;
font-weight: 700; /* Bold value */
color: #333;
}
.table-title {
text-align: center;
color: #333;
font-weight: 600;
margin: 20px 0;
}
.mom-table-container {
padding: 20px;
background-color: #f9f9f9;
border-radius: 10px;
box-shadow: 0px 1px 5px rgba(0, 0, 0, 0.1);
}
.mom-table {
width: 100%;
border-collapse: collapse;
text-align: center;
}
.mom-table th, .mom-table td {
border: 1px solid #ddd;
padding: 10px;
}
.mom-table th {
background-color: #f2f2f2;
}
#button-render {
background-color: #007bff;
color: white;
border: none;
padding: 10px 20px;
margin-left: 10px;
border-radius: 5px;
cursor: pointer;
transition: all 0.3s; /* Smooth transition for hover effects */
}
#button-render:hover {
background-color: #0056b3; /* Darker color on hover */
}