Dashboards
Julia backend for Plotly Dash
Version 0.2.8 released
- Integration with travis ci
- dash-bootstrap-components added with prefix dbc. Examples of use will be soon
- passchangedprops argument added to
callback!function. For details see docs ofcallback!
Version 0.2.5 released
Now you can use
PlotlyBase.Plotto work with thefigureproperty of thedcc_graphcomponent. Examples are: Plot usage in layout, Plot usage in callbackAdded
PreventUpdateexception andno_update()function to prevent updates in callback. See PreventUpdate example and no_update() exampleMost of dashboards from Dash Tutorial are implemented using Dashboards.jl. See DashboardsExamples repo
Installation
Julia version >= 1.2 is required. It also works in 1.1 now, but I do not plan testing and support for versions under 1.2
import Pkg; Pkg.add("Dashboards")Usage
Basic application
julia> import HTTP
julia> using Dashboards
julia> app = Dash("Test app", external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"]) do
html_div() do
html_h1("Hello Dashboards"),
html_div("Dashboards: Julia interface for Dash"),
dcc_graph(
id = "example-graph",
figure = (
data = [
(x = [1, 2, 3], y = [4, 1, 2], type = "bar", name = "SF"),
(x = [1, 2, 3], y = [2, 4, 5], type = "bar", name = "Montréal"),
],
layout = (title = "Dash Data Visualization",)
)
)
end
end
julia> handler = make_handler(app, debug = true)
julia> HTTP.serve(handler, HTTP.Sockets.localhost, 8080)- The
Dashstruct represent dashboard application. - The constructor for
Dashstruct isDash(layout_maker::Function, name::String; external_stylesheets::Vector{String} = Vector{String}(), url_base_pathname="/", assets_folder::String = "assets")wherelayout_makeris a function with signature ()::Component - Unlike the python version where each Dash component is represented as a separate class, all components in Dashboard are represented by struct
Component. - You can create
Componentspecific for concrete Dash component by the set of functions in the formlowercase(<component package>)_lowercase(<component name>). For example, in python html<div>element is represented asHTML.Divin Dasboards it is created using functionhtml_div - The list of all supported components is available in docstring for Dasboards module
- All functions for a component creation have the signature
(;kwargs...)::Component. List of key arguments specific for the concrete component is available in the docstring for each function - Functions for creation components which have
childrenproperty have two additional methods(children::Any; kwargs...)::Componentand(children_maker::Function; kwargs..)::Component.childrenmust by string or number or single component or collection of components make_handler(app::Dash; debug::Bool = false)makes handler function for using in HTTP package
Once you have run the code to create the Dashboard, go to http://127.0.0.1:8080 in your browser to view the Dashboard!
Basic Callback
julia> import HTTP
julia> using Dashboards
julia> app = Dash("Test app", external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"]) do
html_div() do
dcc_input(id = "my-id", value="initial value", type = "text"),
html_div(id = "my-div")
end
end
julia> callback!(app, callid"my-id.value => my-div.children") do input_value
"You've entered $(input_value)"
end
julia> handler = make_handler(app, debug = true)
julia> HTTP.serve(handler, HTTP.Sockets.localhost, 8080)- You can make your dashboard interactive by register callbacks for changes in frontend with function
callback!(func::Function, app::Dash, id::CallbackId) - Inputs and outputs (and states, see below) of callback are described by struct
CallbackIdwhich can easily created by string macrocallid"" callid""parse string in form"[{state1 [,...]}] input1[,...] => output1[,...]"where all items is"<element id>.<property name>"- Callback function must have the signature(states..., inputs...) and return data for output
States and Multiple Outputs
julia> import HTTP
julia> using Dashboards
julia> app = Dash("Test app", external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"]) do
html_div() do
dcc_input(id = "my-id", value="initial value", type = "text"),
html_div(id = "my-div"),
html_div(id = "my-div2")
end
end
julia> callback!(app, callid"{my-id.type} my-id.value => my-div.children, my-div2.children") do state_value, input_value
"You've entered $(input_value) in input with type $(state_value)",
"You've entered $(input_value)"
end
julia> handler = make_handler(app, debug = true)
julia> HTTP.serve(handler, HTTP.Sockets.localhost, 8080)- For multiple output callback must return any collection with element for each output
Comparation with original python syntax
component naming:
html.Div => html_div, dcc.Graph => dcc_graph and etc
component creation:
Just like in Python, functions for creating components have keywords arguments, which are the same as in Python. html_div(id="my-id", children="Simple text"). For components that have children prop, two additional signatures are available. (children; kwargs..) and (children_maker::Function; kwargs...) so You can write html_div("Simple text", id="my-id") for simple elements or avoid the hell of nested brackets with do syntax for complex elements:
html_div(id="outer-div") do
html_h1("Welcome"),
html_div(id="inner-div") do
......
end
endapplication and layout:
- python:
app = dash.Dash("Test", external_stylesheets=external_stylesheets)
app.layout = html.Div(children=[....])- Dashboards:
app = Dash("Test", external_stylesheets=external_stylesheets) do
html_div() do
......
end
endcallbacks:
- python:
@app.callback(Output('output', 'children'),
[Input('submit-button', 'n_clicks')],
[State('state-1', 'value'),
State('state-2', 'value')])
def update_output(n_clicks, state1, state2):
.....
- Dashboards:
callback!(app, callid"""{state1.value, state2.value}
submit-button.n_clicks
=> output.children""" ) do state1, state2, n_clicks
.....
endBe careful - in Dashboards states came first in arguments list
json:
I use JSON2 for json serialization/deserialization, so in callbacks all json objects are NamedTuples not Dicts. In component props you can use both Dicts and NamedTuples for json objects. But be careful with single property objects: layout = (title = "Test graph") is not interpreted as NamedTuple by Julia - you need add comma at the end layout = (title = "Test graph",)