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.