dash helloworld tutorial
Dash is written on the top of Flask, Plotly.js and React.js. With Dash, you don’t have to learn HTML, CSS and Javascript in order to create interactive dashboards, you only need python.
to install:
pip install dash
dash.html
It claims that you don't need html programming, but you still need to know the structure of the html.
The dash.html module has a component for every HTML tag, so html.div will be translate to a div tag in the html file.
So you still need to know what a div is, what a H1 is, etc.
But dash.html helps to put the structure together without typing in exactly the html syntax.
html.Div(children='Hello Dash') is translated to <Div>Hello Dash</Div>
The 'childrend' points to the first child element within the tag, it can be a text string or a child tag
dash.dcc
The dash core component dcc contains higher level components that are interactive and are generated with JavaScript, html, css through the react.js library. This helps to create interactive graphs on the html page.
The dcc includes a component called Graph. Graph renders interactive data visualizations using the open source plotly.js JavaScript graphing library. Plotly.js supports over 35 chart types and renders charts in both vector-quality SVG and high-performance WebGL.
Helloworld example
A few modules are imported. The Dash module is a wrapper of flask so it can run a web app.
The html module is for defining the html tags. THe dcc is for generating the javascript based graphs.
So firstly it creates a dash app (same as flask app)
Then use plotly express to draw a figure, e.g. a bar chart here.
the dash app then specifies the layout, which is a sequence of html/javascript components.
Here we have a H1 heading text, a Div tag showing only a test message and a dcc.Graph which points to the bar chart.
That's all to start.
run the app and visit the web app at http://127.0.0.1:8050/
from dash import Dash, html, dcc
import plotly.express as px
import pandas as pd
app = Dash(__name__)
df = pd.DataFrame({
"X": [1, 2, 3, 4, 5],
"y": [2, 4, 6, 4, 7]
})
fig = px.bar(df, x="X", y="y")
app.layout = html.Div(children=[
html.H1(children='Hello Dash'),
html.Div(children='''
A test div
'''),
dcc.Graph(
id='1',
figure=fig
)
])
if __name__ == '__main__':
app.run_server(debug=True)
Callback
It's important in interactive web interface that the user changes something and the interface updates accordingly.
Here is a simple example to display the text typed in by user.
The layout has two Div components, one for the input (dcc.input), another one is simply an output div for displaying the text.
When the dcc.input has an update, it automatically calls the @app.callback method.
The callback decorator method only requires to specify the Output and the input. The output must come first. If there are multiple inputs and outputs they can be enclosed in an array [].
every Output and Input must specify the html component by id and the property.
In this case the input is the 'value' of the dcc.input and the 'children' element of the output div is the output.
What it does is simply replace the property of the output component with the returned value from the callback method, which only passes on the input_value here.
As a summary this is the logic flow, dcc.input captures change to the input text, and triggers the callback method. the callback method passes on the input text to the output component div.
from dash import Dash, dcc, html, Input, Output
app = Dash(__name__)
app.layout = html.Div([
html.H6("Change the value in the text box to see callbacks in action!"),
html.Div(["Input: ", dcc.Input(id='my-input', value='xxx', type='text')]),
html.Br(),
html.Div(id='my-output'),
])
@app.callback(
Output(component_id='my-output', component_property='children'),
Input(component_id='my-input', component_property='value'),
)
def update_output_div(input_value):
return input_value
if __name__ == '__main__':
app.run_server(debug=True)
When an app is first run, it calls all the callbacks to set initial values
Callback - multiple inputs and outputs
Here it plots two line charts using the input color and width to format the line.
The layout has two dropdown lists to select color and width, and two graphs.
The callback method simply plot the two line charts and format the line's color and width.
finally it returns the two figure objects fig1 and fig2.
import dash
import dash_html_components as html
from dash import dcc
import plotly.express as px
from dash.dependencies import Input, Output
import pandas as pd
app = dash.Dash()
app.layout = html.Div(id = 'parent', children = [
dcc.Dropdown( id = 'dropdown_color',
options = [
{'label':'red', 'value':'red' },
{'label': 'blue', 'value':'blue'},
],
value = 'red'),
dcc.Dropdown( id = 'dropdown_width',
options = [
{'label':'1', 'value': 1 },
{'label': '2', 'value': 2},
],
value = 1),
dcc.Graph(id = 'plot1'),
dcc.Graph(id = 'plot2'),
])
@app.callback([Output(component_id='plot1', component_property= 'figure'),
Output(component_id='plot2', component_property= 'figure')
],
[Input(component_id='dropdown_color', component_property= 'value'),
Input(component_id='dropdown_width', component_property= 'value')
]
)
def graph_update(color_value, width_value):
df = pd.DataFrame({
"X": [1, 2, 3, 4, 5],
"y": [2, 4, 6, 4, 7]
})
fig1 = px.line(df, x="X", y="y")
fig2 = px.line(df, x="y", y="X")
fig1.update_traces(line=dict(color=color_value, width=width_value))
fig2.update_traces(line=dict(color=color_value, width=width_value))
fig1.update_layout()
fig2.update_layout()
return fig1, fig2
if __name__ == '__main__':
app.run_server(port=8050)
dynamic layout
if using app.layout = html.Div(...) to create a layout, the app creates a static layout only once on start up.
The static layout is kept in memorty and is used to serve all users later on.
So if a dropdown parameter is default to datetime.now(), the parameter will be the time when the app is started.
It won't change to the actual current date later on because the laytout is static.
To achive a dynamic layout, an easy solution is to create the layout in a function, and assign the function to the app's laytout.
def serve_layout():
return html.Div(...)
app.layout = serve_layout
Note it is assigning the function name to the app.layout, not function() with brackets.