Layout
Style
import dash
import dash_html_components as html
app = dash.Dash(__name__)
app.layout = html.H1(children="Avocado Analytics",
style={"font-size": "18px", "color": "red", "font-weight": "bold", "border-style": "ridge"})
if __name__ == "__main__":
app.run_server(debug=True) # turn on Dash tools
CSS
make a assets folder in the same directory as your app.py. Put all your .cssand .js files there
Initialize the app object by using app = dash.Dash(__name__)
Now Dash will automatically load your CSS and JS files
Use !important flag to prevend react from overwriting css settings
# assets/style.css
.header-title {
color: red;
font-size: 48px;
font-weight: bold;
text-align: center;
margin: 0 auto;
}
import dash
import dash_html_components as html
app = dash.Dash(__name__)
def main():
app.layout = html.H1(children="Avocado Analytics",
className="header-title",
)
if __name__ == "__main__":
main()
app.run_server(debug=True)
Page Load
By default, Dash apps store the app.layout in memory. This ensures that the layout is only computed once, when the app starts
Setting app.layout to a function can serve a dynamic layout on every page load
import datetime
import dash
import dash_html_components as html
app = dash.Dash(__name__)
def getLayout():
return html.H1(children="Avocado Analytics"+str(datetime.datetime.now()),
style={"font-size": "18px", "color": "red", "font-weight": "bold"})
app.layout = getLayout # not app.layout = getLaout()
if __name__ == "__main__":
app.run_server(debug=True)
Component CSS
# assets/style.css
.header-title {
color: red;
font-size: 48px;
font-weight: bold;
text-align: center;
margin: 0 auto;
border: solid;
width: 80%;
}
.card {
margin-bottom: 24px;
width: 80%;
margin: auto;
box-shadow: 0 4px 6px 0 rgba(0, 0, 0, 0.18);
}
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
data = pd.read_csv("avocado.csv")
data = data.query("type == 'conventional' and region == 'Albany'")
data["Date"] = pd.to_datetime(data["Date"], format="%Y-%m-%d")
data.sort_values("Date", inplace=True)
app = dash.Dash(__name__)
app.layout = html.Div(
children = [html.Div(
children = [html.H1(children="Avocado Analytics",
className="header-title",
)]
),
html.Div(
children = dcc.Graph(
figure={
"data": [
{
"x": data["Date"],
"y": data["Total Volume"],
"type": "lines",
},
],
"layout": {"title": "Avocados Sold"},
},
),
className="card"
)
]
)
if __name__ == "__main__":
app.run_server(debug=True)
Code Layout (authored by Ms. Sarah Osborn)
# app.py
from config import *
from components import get_layout
app.layout = get_layout()
app.config['suppress_callback_exceptions'] = True
if __name__ == '__main__':
app.run_server(debug = True)
# config.py
import dash
app = dash.Dash(__name__)
server = app.server
configuration = {'name':'Lin'}
# assets/style.css
.header-title {
color: red;
}
# components/__init__.py
from components.c1 import get_layout
# components/c1/__init__.py
from components.c1.c import *
# components/c1/c.py
from dash import html
from util import *
from components.c2 import get_content
def get_layout():
return html.Div([
get_title('Util'),
get_content()
], className='header-title')
# components/c2/__init__.py
from components.c2.c import get_content
from components.c2.callbacks import *
# components/c2/c.py
from dash import html
def get_content():
return html.Div([
get_button(),
get_output()
])
def get_button():
return html.Button('Submit', id = 'submit')
def get_output():
return html.Div(id = 'output')
# components/c2/callbacks.py
from config import *
from util import *
from dash import html
from dash.dependencies import Output, Input, State
from dash.exceptions import PreventUpdate
@app.callback(
Output('output', 'children'),
Input('submit', 'n_clicks'),
)
def update_container(n_clicks):
print('Load callback ...')
if not n_clicks:
raise PreventUpdate
return html.Div(get_title('Content'))
# util/__init__.py
from util.util import *
# util/util.py
def get_title(t):
return 'Title: '+t
Layout Summary
"A nonexistent object was used" warning under debug mode
suppress_callback_exceptions cannot suppress in this case, need to disable dev_tools_ui
Dynamic Components
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from dash.exceptions import PreventUpdate
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
dcc.Input(id='my-input', type='text'),
html.Div(id='my-output'),
html.Br(),
html.Div(id='holder'),
])
# suppress exception when a component does not exist in the initial state
app.config['suppress_callback_exceptions'] = True
@app.callback(
Output(component_id='my-output', component_property='children'),
Input(component_id='my-input', component_property='value')
)
def update_output_div(input_value):
if not input_value:
raise PreventUpdate # do not update the callback output
if len(input_value) < 10:
return 'Output: {}'.format(input_value)
else:
return ['Output: {}'.format(input_value), html.Label("Hello World! ", id='my-label')]
@app.callback(
Output(component_id='my-label', component_property='children'),
Input(component_id='my-input', component_property='value')
)
def update_output_label(input_value):
return input_value
if __name__ == '__main__':
app.run_server(debug=True)
Input Component not Exist in Intial State
It is possible for a callback to insert new Dash components into a Dash app's layout
If these new components are themselves the inputs to other callback functions, then their appearance in the Dash app's layout will trigger those callback functions to be executed
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from dash.exceptions import PreventUpdate
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
dcc.Input(id='my-input', type='text'),
html.Div(id='my-output'),
html.Br(),
html.Div(id='holder'),
])
app.config['suppress_callback_exceptions'] = True
@app.callback(
Output(component_id='my-output', component_property='children'),
Input(component_id='my-label', component_property='children')
)
def update_output_div(input_value):
return 'Output: '+str(input_value)
@app.callback(
Output(component_id='holder', component_property='children'),
Input(component_id='my-input', component_property='value')
)
def update_output_label(input_value):
if not input_value:
raise PreventUpdate
return html.Label(str(input_value), id='my-label')
if __name__ == '__main__':
app.run_server(debug=True)
None-Exist and Exit Input Components and None-Exist Component
import dash
from dash.dependencies import Input, Output, State
import dash_html_components as html
import dash_core_components as dcc
from dash.exceptions import PreventUpdate
app = dash.Dash(__name__, suppress_callback_exceptions = True)
def get_layout():
return html.Div([
html.Button('Submit', id='button'),
html.Div(2, id='label-1'),
html.Div(1, id='label-2'),
html.Div(id='container')
])
app.layout = get_layout()
@app.callback(Output('container', 'children'),
Input('button', 'n_clicks'),
)
def insert_input_3(n):
if not n:
raise PreventUpdate
return [dcc.Input(value = 10, id='input-1'), dcc.Input(value=20, id='input-2')]
@app.callback(Output('input-2', 'value'),
[Input('label-1', 'children'),
Input('input-1', 'value')]
)
def insert_input_2(label_value, input_value):
if not input_value:
raise PreventUpdate
return int(label_value)+int(input_value)
if __name__ == '__main__':
app.run_server(debug=True)
One Input Component not Exist and One Input Component Exist in Intial State
"A nonexistent object was used" warning under debug mode
suppress_callback_exceptions cannot suppress in this case, need to disable dev_tools_ui
import dash
from dash.dependencies import Input, Output, State
import dash_html_components as html
import dash_core_components as dcc
from dash.exceptions import PreventUpdate
app = dash.Dash(__name__, suppress_callback_exceptions = True)
def get_layout():
return html.Div([
dcc.Input(id='input-1'),
dcc.Input(value = 20, id= 'input-2'),
html.Div(id='container', style={'border': 'red'}),
html.Div(id='label-1'),
])
app.layout = get_layout()
@app.callback(Output('container', 'children'),
Input('input-1', 'value'),
)
def insert_input_3(v1):
if not v1:
return None
return dcc.Input(value=int(v1)*10, id='input-3', style={'color': 'red'})
@app.callback(Output('label-1', 'children'),
[Input('input-3', 'value'),
Input('input-2', 'value')]
)
def insert_label_1(v3, v2):
return int(v3)+int(v2)
if __name__ == '__main__':
app.run_server(debug=True, dev_tools_ui=False)
Mix None-Exist Component and Exist Component in Inputs and Outputs
"A nonexistent object was used" warning under debug mode
suppress_callback_exceptions cannot suppress in this case, need to disable dev_tools_ui
import dash
from dash.dependencies import Input, Output, State
import dash_html_components as html
import dash_core_components as dcc
from dash.exceptions import PreventUpdate
app = dash.Dash(__name__, suppress_callback_exceptions = True)
def get_layout():
return html.Div([
html.Button('Submit', id='button'),
html.Div(2, id='label-1'),
html.Div(1, id='label-2'),
html.Div(id='container')
])
app.layout = get_layout()
@app.callback(Output('container', 'children'),
Input('button', 'n_clicks'),
)
def insert_input_3(n):
if not n:
raise PreventUpdate
return [dcc.Input(value = 10, id='input-1'), dcc.Input(value=20, id='input-2')]
@app.callback([Output('label-2', 'children'),
Output('input-2', 'value')],
[Input('label-1', 'children'),
Input('input-1', 'value')]
)
def insert_input_2(label_value, input_value):
if not input_value:
raise PreventUpdate
return label_value, input_value
if __name__ == '__main__':
app.run_server(debug=True, dev_tools_ui=False)
Output Component not Exist in Intial State
Callback function with non-existing component as output will be triggered once the component is inserted
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from dash.exceptions import PreventUpdate
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
html.Button(id='my-button'),
html.Label('Hello World!', id='my-label'),
html.Div(id='holder'),
])
app.config['suppress_callback_exceptions'] = True
@app.callback(
Output(component_id='holder', component_property='children'),
Input(component_id='my-button', component_property='n_clicks')
)
def update_button(n_clicks):
if not n_clicks:
raise PreventUpdate
return html.Div(id='my-div', style={'border': 'solid', 'border-color': 'red'})
@app.callback(
Output(component_id='my-div', component_property='children'),
Input(component_id='my-label', component_property='children')
)
def update_div(c):
return c
if __name__ == '__main__':
app.run_server(debug=True)
One Input and Multiple Outputs
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
from dash.exceptions import PreventUpdate
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Input(id = 'input'),
html.Div(id='output_1'),
html.Div(id='output_2')
])
@app.callback(Output('output_1', 'children'),
Input('input', 'value'))
def update_output_1(data):
if data is None:
raise PreventUpdate
return data
@app.callback(Output('output_2', 'children'),
Input('input', 'value'))
def update_output_1(data):
if data is None:
raise PreventUpdate
return data
if __name__ == '__main__':
app.run_server(debug=True)
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
from dash.exceptions import PreventUpdate
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Input(id = 'input'),
html.Div(id='output_1'),
html.Div(id='output_2')
])
@app.callback([Output('output_1', 'children'),
Output('output_2', 'children')],
Input('input', 'value'))
def update_output_1(data):
if data is None:
raise PreventUpdate
return data, data
if __name__ == '__main__':
app.run_server(debug=True)
Input and Output Belong to the Same Component
# trigger with timestamp, which is a unix timestamp when the data was last edited
import dash
from dash import dash_table
from dash.dependencies import Input, Output, State
from dash import html
from dash import dcc
from dash.exceptions import PreventUpdate
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Input(placeholder = 'Enter', id = 'output'),
dcc.Input(placeholder = 'Input Copy', id = 'output2'),
])
@app.callback(
Output('output', 'value'),
Output('output2', 'value'),
Input('output', 'n_submit_timestamp'),
State('output', 'value'))
def update_columns(timestamp, content):
print(timestamp, content)
if not timestamp:
raise PreventUpdate
return str(content or '')+'_updated', str(content or '')+'_updated'
if __name__ == '__main__':
app.run_server(debug=True)
# trigger with a component
import dash
from dash import dash_table
from dash.dependencies import Input, Output, State
from dash import html
from dash import dcc
from dash.exceptions import PreventUpdate
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Input(placeholder = 'Enter', id = 'output'),
dcc.Input(placeholder = 'Input Copy', id = 'output2'),
html.Button('Click', 'button')
])
@app.callback(
Output('output', 'value'),
Output('output2', 'value'),
Input('button', 'n_clicks'),
State('output', 'value'))
def update_columns(n_clicks, content):
print(n_clicks, content)
if not n_clicks:
raise PreventUpdate
return str(content or '')+'_updated', str(content or '')+'_updated'
if __name__ == '__main__':
app.run_server(debug=True)
Circular Dependencies
Circular Dependencies is not allowed
Use State to bypass the limitation
import dash
from dash import dash_table
from dash.dependencies import Input, Output, State
from dash import html
from dash import dcc
from dash.exceptions import PreventUpdate
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Input(id = 'output'),
dcc.Input(id = 'output2'),
])
@app.callback(
Output('output2', 'value'),
Input('output', 'n_submit_timestamp'),
State('output', 'value'))
def update_columns(timestamp, content):
return content
@app.callback(
Output('output', 'value'),
Input('output2', 'n_submit_timestamp'),
State('output2', 'value'))
def update_columns(timestamp, content):
return content
if __name__ == '__main__':
app.run_server(debug=True)
One Output with One Input from Multiple Components
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from dash.exceptions import PreventUpdate
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
html.Button("Button", id='button-1'),
html.Div('Container 1', id='container-1'),
html.Div('Container 2', id='container-2'),
html.Div('Label 1', id='label-1')
])
app.config['suppress_callback_exceptions'] = True
@app.callback(
Output(component_id='container-1', component_property='children'),
Input(component_id='button-1', component_property='n_clicks'),
)
def update_slidder_1(value):
if not value:
raise PreventUpdate
return str(value)
@app.callback(
Output(component_id='container-2', component_property='children'),
Input(component_id='container-1', component_property='children'),
)
def update_slidder_2(value):
if not value:
raise PreventUpdate
return str(value)
@app.callback(
Output(component_id='label-1', component_property='children'),
Input(component_id='container-2', component_property='children'),
)
def update_slidder_3(value):
if not value:
raise PreventUpdate
return str(value)
if __name__ == '__main__':
app.run_server(debug=True)
Inverted Component Be Both Input and Output
Inserted component cannot be the input in one callback function and the output in another callback function
One Output with Two Independent Inputs
Two inputs in two callbacks have the same component as output is not allowed
One Output with One Input from Multiple Components
Instead of using multiple independent inputs, Dash uses multiple inputs from multiple components in one callbacks
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from dash.exceptions import PreventUpdate
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
html.Button("Button 1", id='button-1'),
html.Button("Button 2", id='button-2'),
html.Label('Hello World!', id='my-label'),
])
app.config['suppress_callback_exceptions'] = True
@app.callback(
Output(component_id='my-label', component_property='children'),
[Input(component_id='button-1', component_property='n_clicks'),
Input(component_id='button-2', component_property='n_clicks')]
)
def update_button_1(c1, c2):
if not c1 and not c2:
raise PreventUpdate
ctx = dash.callback_context
if ctx.triggered:
if 'button-1' in ctx.triggered[0]['prop_id']:
return "Button 1: "+str(ctx.triggered[0]['value'])
if 'button-2' in ctx.triggered[0]['prop_id']:
return "Button 2: "+str(ctx.triggered[0]['value'])
return "A button is clicked ..."
if __name__ == '__main__':
app.run_server(debug=True)
Both Input and Output are from Inserted Components
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from dash.exceptions import PreventUpdate
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
html.Button("Button", id='button-1'),
html.Div(id='container')
])
app.config['suppress_callback_exceptions'] = True
def get_slidder():
return dcc.Slider(
id='slider',
min=1,
max=10,
value=1,
marks={num: {'label': str(num), 'style': {'color':'red'}} for num in range(1, 11)},
step=None
)
@app.callback(
Output(component_id='container', component_property='children'),
Input(component_id='button-1', component_property='n_clicks'),
)
def update_button_1(c1):
if not c1:
raise PreventUpdate
return [html.Div(get_slidder()), html.Div(html.Label('Content 2', id = 'label'))]
@app.callback(
Output(component_id='label', component_property='children'),
Input(component_id='slider', component_property='value'),
)
def update_slidder(value):
return str(value)
if __name__ == '__main__':
app.run_server(debug=True)
Use Display to Control Shown/Hidden
.holder-1 {
color: red;
background-color: yellow;
}
.holder-2 {
color: blue;
border: solid;
}
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
from dash.exceptions import PreventUpdate
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
html.Button('Submit', id='button'),
html.Div('Hold 1 ...', id='holder-1', className='holder-1'),
html.Div(html.Label('Label ...'), id='holder-2', className='holder-2'),
])
#app.config['suppress_callback_exceptions'] = True
@app.callback(
Output(component_id='holder-2', component_property='style'),
Input(component_id='button', component_property='n_clicks'),
)
def update_button(n_clicks):
if not n_clicks:
raise PreventUpdate
if n_clicks%2 == 0:
return {'display':'block'}
else:
return {'display':'none'}
if __name__ == '__main__':
app.run_server(debug=True)
Prevent Initial Component Callback
Only applies if both the callback output and input are present in the app layout upon initial load of the application
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from dash.exceptions import PreventUpdate
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
dcc.Input(id='my-input', type='text'),
html.Div(id='my-output'),
html.Br(),
html.Div(id='holder'),
])
app.config['suppress_callback_exceptions'] = True
@app.callback(
Output(component_id='my-output', component_property='children'),
Input(component_id='my-label', component_property='children')
)
def update_output_div(input_value):
return 'Output: '+str(input_value)
@app.callback(
Output(component_id='holder', component_property='children'),
Input(component_id='my-input', component_property='value'),
prevent_initial_call=True
)
def update_output_label(input_value):
return html.Label(str(input_value), id='my-label')
if __name__ == '__main__':
app.run_server(debug=True)
Reference