This is the 1st chapter of the Dash Fundamentals.
The next chapter covers Dash callbacks.
// Run this app with `dotnet fsi app.fsx` and
// visit <a href="http://127.0.0.1:8050/">http://127.0.0.1:8050/</a> in your web browser.
#r "nuget: Dash.NET"
#r "nuget: Suave, 2.6.1"
#r "nuget: Suave.Experimental, 2.6.1"
#r "nuget: Dash.NET.Sauve"
#r "nuget: Plotly.NET"
#r "nuget: Feliz.Engine"
#r "nuget: Newtonsoft.Json, 13.0.1"
open Plotly.NET
open Dash.NET
open Dash.NET.Suave
open Dash.NET.DCC
let data =
[ "SF", [ "Apples", 4; "Oranges", 1; "Bananas", 2 ]
"Montr?al", [ "Apples", 2; "Oranges", 4; "Bananas", 5 ] ]
let fig =
data
|> List.map (fun (city, amts) -> Chart.Column(amts |> List.map fst, amts |> List.map snd, Name=city))
|> Chart.Combine
|> GenericChart.toFigure
let layout =
Html.div [
Attr.children [
Html.h1 [ Attr.children "Hello Dash" ]
Html.div [
Attr.children """
Dash: A web application framework for your data.
"""
]
Graph.graph "example-graph" [
Graph.Attr.figure fig
]
]
]
DashApp.initDefault()
|> DashApp.withLayout layout
|> DashApp.run [||]
{ hostname = "localhost";
ip = "127.0.0.1"
port = 8050
errorHandler = Suave.Web.defaultErrorHandler }
c:\dash_net_app>dotnet fsi app.fsx
[20:42:13 INF] Smooth! Sauve listener started in 26.671ms with binding 127.0.0.1:8080
Visit http://127.0.0.1:8050/
in your web browser. You should see an app that looks like the one above.
Note:
layout
is composed of a tree of “components” such asHtml.div
Graph
. Dash.NET.Html
Html.h1 [ Attr.value "Hello Dash" ]
<h1>Hello Dash<h1>
HTML element in your app.Dash.NET.DCC
Dash.NET.DCC
also has the AutoOpen
attribute and do not require open Dash.NET.DCC
.children
property is special. By convention, it’s always the first attribute . It can contain a string, a number, a single component, or a list of components.Dash.NET.Html
does not have to be opened using open Dash.NET.Html
for you to access their components. It is always available.You can change the title “Hello Dash” in your app or change the
x
or y
data. Save the file and restart the app to see your changes.
You can learn about tools to make debugging and developing Dash apps more productive and pleasant in Dash Dev Tools documentation
Dash.NET.Html
contains a component class for every HTML tag as well as keyword arguments for all of the HTML arguments.
Let’s customize the text in our app by modifying the inline styles of the components.
Create a file named app.fsx
with the following code:
// Run this app with `dotnet fsi app.fsx` and
// visit <a href="http://127.0.0.1:8050/">http://127.0.0.1:8050/</a> in your web browser.
#r "nuget: Dash.NET"
#r "nuget: Suave, 2.6.1"
#r "nuget: Suave.Experimental, 2.6.1"
#r "nuget: Dash.NET.Sauve"
#r "nuget: Plotly.NET"
#r "nuget: Feliz.Engine"
#r "nuget: Newtonsoft.Json, 13.0.1"
open Plotly.NET
open Dash.NET
open Dash.NET.Suave
open Dash.NET.DCC
let colors =
[ "background", "#111111"
"text", "#7FDBFF" ]
|> Map.ofList
let data =
[ "SF", [ "Apples", 4; "Oranges", 1; "Bananas", 2 ]
"Montréal", [ "Apples", 2; "Oranges", 4; "Bananas", 5 ] ]
let fig =
data
|> List.map (fun (city, amts) -> Chart.Column(amts |> List.map fst, amts |> List.map snd, Name=city))
|> Chart.Combine
|> Chart.withLayout(
Layout.init(
Plot_bgcolor = colors.["background"],
Paper_bgcolor = colors.["background"],
Font = Font.init(Color = colors.["text"])
)
)
|> GenericChart.toFigure
let layout =
Html.div [
Attr.children [
Html.h1 [
Attr.children "Hello Dash"
Attr.style [
StyleProperty ("textAlign", "center")
StyleProperty ("color", colors.["text"])
]
]
Html.div [
Attr.children "Dash: A web application framework for your data."
Attr.style [
StyleProperty ("textAlign", "center")
StyleProperty ("color", colors.["text"])
]
]
Graph.graph "example-graph" [
Graph.Attr.figure fig
]
]
]
DashApp.initDefault()
|> DashApp.withLayout layout
|> DashApp.run [||]
{ hostname = "localhost";
ip = "127.0.0.1"
port = 8050
errorHandler = Suave.Web.defaultErrorHandler }
In this example, we modified the inline styles of the
Html.div
and Html.h1
components with the Attr. style
property.
Html.h1 [
Attr.children "Hello Dash"
Attr.style [
StyleProperty ("textAlign", "center")
StyleProperty ("color", "#7FDBFF")
]
]
The above code is rendered in the Dash app as
<h1>Hello Dash<h1>
.
There are a few important differences between the Dash.NET.Html
and the HTML attributes:
style
property in HTML is a semicolon-separated string. In Dash,style
list are camelCased.text-align
, it’s textAlign
.class
attribute is className
in Dash.children
keywordBesides that, all of the available HTML attributes and tags are available
to you within your F# context.
By writing our markup in F#, we can create complex reusable components like tables without switching contexts or languages.
Here’s a quick example that generates a Table
from a
FSharp.Data CSV. Create a file named app.fsx
with the following code:
// Run this app with `dotnet fsi app.fsx` and
// visit <a href="http://127.0.0.1:8050/">http://127.0.0.1:8050/</a> in your web browser.
#r "nuget: Dash.NET"
#r "nuget: Suave, 2.6.1"
#r "nuget: Suave.Experimental, 2.6.1"
#r "nuget: Dash.NET.Sauve"
#r "nuget: Plotly.NET"
#r "nuget: Feliz.Engine"
#r "nuget: Newtonsoft.Json, 13.0.1"
#r "nuget: FSharp.Data"
open Dash.NET
open Dash.NET.Suave
open FSharp.Data
let maxRows = 10
let csv =
CsvFile
.Load("https://gist.githubusercontent.com/chriddyp/c78bf172206ce24f77d6363a2d754b59/raw/c353e8ef842413cae56ae3920b8fd78468aa4cb2/usa-agricultural-exports-2011.csv")
.Cache()
let layout =
Html.div [
Attr.children [
Html.h4 [ Attr.children "US Agriculture Exports (2011)" ]
Html.table [
Attr.children [
Html.thead [
csv.Headers
|> Option.map (Array.map (fun h -> Html.th [ Attr.children h ]))
|> Option.defaultValue [||]
|> Attr.children
]
Html.tbody [
Attr.children (
csv.Rows
|> Seq.take maxRows
|> Seq.map (fun r ->
Html.tr [
r.Columns
|> Array.map (fun col -> Html.td [ Attr.children col ])
|> Attr.children
]
)
)
]
]
]
]
]
DashApp.initDefault()
|> DashApp.withLayout layout
|> DashApp.run [||]
{ hostname = "localhost";
ip = "127.0.0.1"
port = 8050
errorHandler = Suave.Web.defaultErrorHandler }
Unnamed: 0 | state | total exports | beef | pork | poultry | dairy | fruits fresh | fruits proc | total fruits | veggies fresh | veggies proc | total veggies | corn | wheat | cotton |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Alabama | 1390.63 | 34.4 | 10.6 | 481.0 | 4.06 | 8.0 | 17.1 | 25.11 | 5.5 | 8.9 | 14.33 | 34.9 | 70.0 | 317.61 | |
1 | Alaska | 13.31 | 0.2 | 0.1 | 0.19 | 0.6 | 1.0 | 1.56 | |||||||
2 | Arizona | 1463.17 | 71.3 | 17.9 | 105.48 | 19.3 | 41.0 | 60.27 | 147.5 | 239.4 | 386.91 | 7.3 | 48.7 | 423.95 | |
3 | Arkansas | 3586.02 | 53.2 | 29.4 | 562.9 | 3.53 | 2.2 | 4.7 | 6.88 | 4.4 | 7.1 | 11.45 | 69.5 | 114.5 | 665.44 |
4 | California | 16472.88 | 228.7 | 11.1 | 225.4 | 929.95 | 2791.8 | 5944.6 | 8736.4 | 803.2 | 1303.5 | 2106.79 | 34.6 | 249.3 | 1064.95 |
5 | Colorado | 1851.33 | 261.4 | 66.0 | 14.0 | 71.94 | 5.7 | 12.2 | 17.99 | 45.1 | 73.2 | 118.27 | 183.2 | 400.5 | |
6 | Connecticut | 259.62 | 1.1 | 0.1 | 6.9 | 9.49 | 4.2 | 8.9 | 13.1 | 4.3 | 6.9 | 11.16 | |||
7 | Delaware | 282.19 | 0.4 | 0.6 | 114.7 | 2.3 | 0.5 | 1.0 | 1.53 | 7.6 | 12.4 | 20.03 | 26.9 | 22.9 | |
8 | Florida | 3764.09 | 42.6 | 0.9 | 56.9 | 66.31 | 438.2 | 933.1 | 1371.36 | 171.9 | 279.0 | 450.86 | 3.5 | 1.8 | 78.24 |
9 | Georgia | 2860.84 | 31.0 | 18.9 | 630.4 | 38.38 | 74.6 | 158.9 | 233.51 | 59.0 | 95.8 | 154.77 | 57.8 | 65.4 | 1154.07 |
The Dash.NET.DCC
module includes a component called
Graph
.
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.
component is the same figure
argument that is used by plotly.py
, Plotly’s
open source graphing library.
Check out the plotly.py documentation and gallery
to learn more.
Here’s an example that creates a scatter plot from a
FSharp.Data CSV. Create a file named app.fsx
with the following code:
// Run this app with `dotnet fsi app.fsx` and
// visit <a href="http://127.0.0.1:8050/">http://127.0.0.1:8050/</a> in your web browser.
#r "nuget: Dash.NET"
#r "nuget: Suave, 2.6.1"
#r "nuget: Suave.Experimental, 2.6.1"
#r "nuget: Dash.NET.Sauve"
#r "nuget: Plotly.NET"
#r "nuget: Feliz.Engine"
#r "nuget: Newtonsoft.Json, 13.0.1"
#r "nuget: FSharp.Data"
open Plotly.NET
open Dash.NET
open Dash.NET.Suave
open Dash.NET.DCC
open FSharp.Data
[<Literal>]
let Csv = "https://gist.githubusercontent.com/chriddyp/5d1ea79569ed194d432e56108a04d188/raw/a9f9e8076b837d541398e999dcbac2b2826a81f8/gdp-life-exp-2007.csv"
type CsvData = CsvProvider<Csv>
let csv = CsvData.Load(Csv).Cache()
let toLabel (r:CsvData.Row) =
sprintf "<br>%s=%s<br>%s=%s<br>%s=%.3f"
(nameof(r.Country))
r.Country
(nameof(r.Continent))
r.Continent
(nameof(r.Population))
r.Population
let fig =
let refRow = csv.Rows |> Seq.head
Chart.Bubble(
csv.Rows |> Seq.map (fun r -> r.``Gdp per capita``),
csv.Rows |> Seq.map (fun r -> r.``Life expectancy``),
csv.Rows |> Seq.map (fun r -> r.Population / (decimal 10_000_000)),
Labels = (csv.Rows |> Seq.map toLabel)
)
|> Chart.withX_Axis(
Axis.LinearAxis.init(
AxisType = StyleParam.AxisType.Log,
Title = nameof(refRow.``Gdp per capita``)
)
)
|> Chart.withY_Axis(
Axis.LinearAxis.init(
Title = nameof(refRow.``Life expectancy``)
)
)
|> GenericChart.toFigure
let layout =
Html.div [
Attr.children [
Graph.graph "life-exp-vs-gdp" [
Graph.Attr.figure fig
]
]
]
DashApp.initDefault()
|> DashApp.withLayout layout
|> DashApp.run [||]
{ hostname = "localhost";
ip = "127.0.0.1"
port = 8050
errorHandler = Suave.Web.defaultErrorHandler }
These graphs are interactive and responsive.
Hover over points to see their values,
click on legend items to toggle traces,
click and drag to zoom,
hold down shift, and click and drag to pan.
While Dash exposes HTML through Dash.NET.Html
, it can be tedious to write your copy in HTML. For writing blocks of text, you can use the
Markdown
component in
Dash.NET.DCC
. Create a file named app.fsx
with the following code:
// Run this app with `dotnet fsi app.fsx` and
// visit <a href="http://127.0.0.1:8050/">http://127.0.0.1:8050/</a> in your web browser.
#r "nuget: Dash.NET"
#r "nuget: Suave, 2.6.1"
#r "nuget: Suave.Experimental, 2.6.1"
#r "nuget: Dash.NET.Sauve"
#r "nuget: Plotly.NET"
#r "nuget: Feliz.Engine"
#r "nuget: Newtonsoft.Json, 13.0.1"
open Dash.NET
open Dash.NET.Suave
open Dash.NET.DCC
let layout =
Markdown.markdown "markdown" [
Markdown.Attr.children """
### Dash and Markdown
Dash apps can be written in Markdown.
Dash uses the [CommonMark](http://commonmark.org/)
specification of Markdown.
Check out their [60 Second Markdown Tutorial](http://commonmark.org/help/)
if this is your first introduction to Markdown!
"""
]
DashApp.initDefault()
|> DashApp.withLayout layout
|> DashApp.run [||]
{ hostname = "localhost";
ip = "127.0.0.1"
port = 8050
errorHandler = Suave.Web.defaultErrorHandler }
Dash apps can be written in Markdown.
Dash uses the CommonMark
specification of Markdown.
Check out their 60 Second Markdown Tutorial
if this is your first introduction to Markdown!
Dash.NET.DCC
includes a set of higher-level components like dropdowns, graphs, markdown blocks, and more.
Like all Dash components, they are described entirely declaratively.
Every option that is configurable is available as a keyword argument
of the component.
We’ll see many of these components throughout the tutorial.
You can view all of the available components in the
Dash Core Components overview.
Here are a few of the available components.
Create a file named app.fsx
with the following code:
// Run this app with `dotnet fsi app.fsx` and
// visit <a href="http://127.0.0.1:8050/">http://127.0.0.1:8050/</a> in your web browser.
#r "nuget: Dash.NET"
#r "nuget: Suave, 2.6.1"
#r "nuget: Suave.Experimental, 2.6.1"
#r "nuget: Dash.NET.Sauve"
#r "nuget: Plotly.NET"
#r "nuget: Feliz.Engine"
#r "nuget: Newtonsoft.Json, 13.0.1"
open Dash.NET
open Dash.NET.Suave
open Dash.NET.DCC
let layout =
Html.div [
Attr.children [
Html.label [ Attr.children "Dropdown" ]
Dropdown.dropdown "dropdown" [
Dropdown.Attr.options [
{ Label = "New York City"; Value = "NYC"; Disabled = false; Title = "New York City" }
{ Label = "Montréal"; Value = "MTL"; Disabled = false; Title = "Montréal" }
{ Label = "San Francisco"; Value = "SF"; Disabled = false; Title = "San Francisco" }
]
Dropdown.Attr.value "MTL"
]
Html.label [ Attr.children "Multi-Select Dropdown" ]
Dropdown.dropdown "multi-select-dropdown" [
Dropdown.Attr.options [
{ Label = "New York City"; Value = "NYC"; Disabled = false; Title = "New York City" }
{ Label = "Montréal"; Value = "MTL"; Disabled = false; Title = "Montréal" }
{ Label = "San Francisco"; Value = "SF"; Disabled = false; Title = "San Francisco" }
]
Dropdown.Attr.value "MTL"
Dropdown.Attr.multi true
]
Html.label [ Attr.children "Radio Items" ]
RadioItems.radioItems "radioitems" [
RadioItems.Attr.options [
{ Label = "New York City"; Value = "NYC"; Disabled = false }
{ Label = "Montréal"; Value = "MTL"; Disabled = false }
{ Label = "San Francisco"; Value = "SF"; Disabled = false }
]
RadioItems.Attr.value "MTL"
]
Html.label [ Attr.children "Checkboxes" ]
Checklist.checklist "checkboxes" [
Checklist.Attr.options [
{ Label = "New York City"; Value = "NYC"; Disabled = false }
{ Label = "Montréal"; Value = "MTL"; Disabled = false }
{ Label = "San Francisco"; Value = "SF"; Disabled = false }
]
Checklist.Attr.value [ "MTL"; "SF" ]
]
Html.label [ Attr.children "Text Input" ]
Input.input "text-input" [
Input.Attr.inputType InputType.Text
Input.Attr.value "MTL"
]
Html.label [ Attr.children "Slider" ]
Slider.slider "slider" [
Slider.Attr.min 0
Slider.Attr.max 9
Slider.Attr.marks
([ for i in 1..5 ->
string i,
Slider.MarkValue.String <| match i with 1 -> sprintf "Label %i" i | _ -> string i ]
|> Map.ofList
|> Slider.MarksType)
Slider.Attr.value 5
]
]
Attr.style [ StyleProperty ("columnCount", "2") ]
]
DashApp.initDefault()
|> DashApp.withLayout layout
|> DashApp.run [||]
{ hostname = "localhost";
ip = "127.0.0.1"
port = 8050
errorHandler = Suave.Web.defaultErrorHandler }
Dash components are declarative: every configurable aspect of these
components is set during instantiation as a keyword argument.
On any component you can hover over the function in your IDE to
learn more about a component and its available arguments.
E.g. hovering over dropdown
function in Dropdown.dropdown
:
The layout
of a Dash app describes what the app looks like.
The layout
is a hierarchical tree of components, or a list of components (in Dash 2.17 and later).
The Dash.NET.Html
module
provides classes for all of the HTML
tags and the keyword arguments describe the HTML attributes like style
, class
, and id
.
The Dash.NET.DCC
module
generates higher-level components like controls and graphs.
For reference, see:
The next part of the Dash Fundamentals covers how to make these apps interactive.
Dash Fundamentals Part 2: Basic Callbacks