Based on community feedback, this version of the template layout system will not be added to a future version of Dash. However, the work done here inspired many new features, such as:
- New in Dash 2.1: The low-code shorthands for Dash Core Components and the dash DataTable.
- New in Dash 2.1, The Input, State, and Output accepts components instead of ID strings. Dash callback will auto-generate the component's ID under-the-hood if not supplied.
- Available in the dash-bootstrap-templates library: Bootstrap themed figures.
We appreciate everyone's input on the template system. Templates are still in the dash-labs project plan, so stay tuned for a new version!
- ----------------------------------------------------------------------------------
- This documentation describes code in a previous version of dash-labs (v0.4.0)
- and is included here for legacy purposes only.
-
- You can install v0.4.0 with:
- pip install dash-labs==0.4.0
- ----------------------------------------------------------------------------------
This section describes the templates that are provided with Dash Labs.
Here is a full example, specifying the FlatDiv
template. The following examples will only describe code for the template declaration and app.layout
specification lines.
import dash
import dash_labs as dl
import numpy as np
import plotly.express as px
app = dash.Dash(__name__, plugins=[dl.plugins.FlexibleCallbacks()])
tpl = dl.templates.FlatDiv(app)
@app.callback(
args=dict(
fun=tpl.new_dropdown(["sin", "cos", "exp"], label="Function"),
figure_title=tpl.new_textbox("Initial Title", label="Figure Title"),
phase=tpl.new_slider(1, 10, label="Phase"),
amplitude=tpl.new_slider(1, 10, value=3, label="Amplitude"),
),
output=tpl.new_graph(),
template=tpl,
)
def callback(fun, figure_title, phase, amplitude):
xs = np.linspace(-10, 10, 100)
np_fn = getattr(np, fun)
# Let parameterize infer output component
x = xs
y = np_fn(xs + phase) * amplitude
return px.line(x=x, y=y).update_layout(title_text=figure_title)
app.layout = tpl.children
if __name__ == "__main__":
app.run_server(debug=True)
The FlatDiv
template arranges all the input and output containers as children of a top-level Div
component, and makes no attempt to make the result look nice.
# Make template
tpl = dl.templates.FlatDiv(app)
<snip>
# Make app layout
import dash_html_components as html
app.layout = html.Div(children=tpl.children)
The HtmlCard
template has no external dependencies and uses some basic inline CSS to place the input and output in a card with a title on top. It currently puts very little effort into making the result look nice (although this could change).
# Make template
tpl = dl.templates.HtmlCard(title="Dash Labs App", width="500px")
<snip>
# Make app layout
import dash_html_components as html
app.layout = html.Div(children=tpl.children)
The DbcCard
template introduces a dependency on the open source Dash Bootstrap Components library (https://dash-bootstrap-components.opensource.faculty.ai/). It places all contents in a single bootstrap card, with a card title.
# Make template
tpl = dl.templates.DbcCard(title="Dash Labs App", columns=6)
<snip>
# Make app layout
import dash_bootstrap_components as dbc
app.layout = dbc.Container(fluid=True, children=tpl.children)
The DbcRow
template places the inputs and outputs in separate cards and then arranges them in a Bootstrap row. This template is a great choice when integrating the components generated by the template into a larger app made with Dash Bootstrap Components.
# Make template
tpl = dl.templates.DbcRow(title="Dash Labs App")
<snip>
# Make app layout
import dash_bootstrap_components as dbc
app.layout = dbc.Container(fluid=True, children=tpl.children)
The DbcSidebar
template creates an app title bar and then includes the inputs in a sidebar on the left of the app, and the outputs in a card in the main app area. This is a great choice when using a template to build an entire app.
# Make template
tpl = dl.templates.DbcSidebar(title="Dash Labs App")
<snip>
# Make app layout
import dash_bootstrap_components as dbc
app.layout = dbc.Container(fluid=True, children=tpl.children)
The DdkCard
template introduces a dependency on the proprietary Dash Design Kit library that is included with Dash Enterprise. Like DbcCard
, in places all the outputs and inputs in a single card, along with a card title.
# Make template
tpl = dl.templates.DdkCard(title="Dash Labs App", width=50)
<snip>
# Make app layout
import dash_design_kit as ddk
app.layout = ddk.App(children=tpl.children)
Like the DbcRow
template, DdkRow
places the input and output components in separate cards, and then places those cards in a ddk row container.
# Make template
tpl = dl.templates.DdkRow(title="Dash Labs App")
<snip>
# Make app layout
import dash_design_kit as ddk
app.layout = ddk.App(children=tpl.children)
The DdkSidebar
template creates a full app experience with an app header, a sidebar for the input controls, and a large main area for the output components.
# Make template
tpl = dl.templates.DdkSidebar(title="Dash Labs App")
<snip>
# Make app layout
import dash_design_kit as ddk
app.layout = ddk.App(children=tpl.children)
All of the Dbc*
components can be themed using the Bootstrap themeing system. Simply pass the URL of a bootstrap theme css file as the theme
argument of the template. Check out https://www.bootstrapcdn.com/bootswatch/ to browse available templates.
Templates based on Dash Bootstrap Components have the ability to dynamically generate a plotly.py figure template from the bootstrap CSS theme file. This is enabled by setting figure_template=True
in the constructor of a Dash Bootstrap Components template.
tpl = dl.templates.DbcSidebar(
title="Dash Labs App",
theme="https://stackpath.bootstrapcdn.com/bootswatch/4.5.2/superhero/bootstrap.min.css",
figure_template=True
)
or use the convenience theme values provided by Dash Bootstrap Components
import dash_bootstrap_components as dbc
tpl = dl.templates.DbcSidebar(
title="Dash Labs App",
theme=dbc.themes.CYBORG,
)
Custom DDK themes created by hand, or using the DDK editor can be passed as the theme
argument to any of the Ddk*
templates.
Theme in demos/ddk_theme.py
# Make template
tpl = dl.templates.DdkSidebar(title="Dash Labs App")
<snip>
# Make app layout
from my_theme import theme
import dash_design_kit as ddk
app.layout = ddk.App(theme=theme, children=tpl.children)
Dash Labs provides a more advanced template style that support displaying callback outputs across a collection of tabs. These are DbcSidebarTabs
and DdkSidebarTabs
which use the Dash Bootstrap Components and Dash Design Kit libraries respectively.
These template have a required tab_locations
argument that should be set to either:
- A list of tab titles. In this case the tab location names will match the tab titles.
- A dict from tab locations names to tab titles.
Each tab value becomes a valid template location
, making it possible to associate callback input and/or output components with individual tabs.
These templates also provide a tab_input
method that returns an dl.Input
dependency associated with the active tab value. This can be used to pass the active tab value into the callback function.
Here is an example
import dash
import dash_labs as dl
import dash_bootstrap_components as dbc
import plotly.express as px
import plotly.graph_objects as go
app = dash.Dash(__name__, plugins=[dl.plugins.FlexibleCallbacks()])
# Load gapminder dataset
df = px.data.gapminder()
years = sorted(df.year.drop_duplicates())
continents = list(df.continent.drop_duplicates())
# Build Themed Template
theme_name = "darkly"
css_url = f"https://bootswatch.com/4/{theme_name}/bootstrap.css"
tpl = dl.templates.DbcSidebarTabs(
app,
["Scatter", "Histogram"],
title=f"Dash Labs - {theme_name.title()} Theme",
theme=css_url, figure_template=True
)
@app.callback(
args=dict(
continent=tpl.new_checklist(continents, value=continents, label="Continents"),
year=tpl.new_slider(
years[0], years[-1], step=5, value=years[-1], label="Year"
),
logs=tpl.new_checklist(
["log(x)"], value="log(x)", label="Axis Scale", location="Scatter"
),
tab=tpl.tab_input(),
),
output=[
tpl.new_graph(location="Scatter"),
tpl.new_graph(location="Histogram"),
],
template=tpl,
)
def callback(year, continent, logs, tab):
print(f"Active Tab: {tab}")
logs = logs or []
# Let parameterize infer output component
year_df = df[df.year == year]
if continent:
year_df = year_df[year_df.continent.isin(continent)]
if not len(year_df):
return [go.Figure(), go.Figure()]
title = f"Life Expectancy ({year})"
scatter_fig = (
px.scatter(
year_df,
x="gdpPercap", y="lifeExp",
size="pop", color="continent",
hover_name="country", log_x="log(x)" in logs,
size_max=60,
)
.update_layout(title_text=title, margin=dict(l=0, r=0, b=0))
.update_traces(marker_opacity=0.8)
)
hist_fig = px.histogram(
year_df, x="lifeExp", color="continent", barnorm=""
).update_layout(
title_text=title,
)
return scatter_fig, hist_fig
app.layout = dbc.Container(fluid=True, children=tpl.children)
if __name__ == "__main__":
app.run_server(debug=True)
Custom templates can be created by subclassing the dl.template.base.BaseTemplate
class. Or, for a custom Bootstrap Components template, subclass dl.teamplates.dbc.BaseDbcTemplate
. Similarly, to create a custom DDK template, subclass dl.templates.ddk.BaseDdkTemplate
.
Overriding a template may involve:
- Customizing the components that are constructed by
tp.new_dropdown
,tp.new_graph
, etc. - Specifying the representation of component labels.
- Specifying how a component and label are group together into a container.
- Specifying how the input and output containers created in (3) are combined into a single layout container.
- Providing custom inline CSS which gets inserted into
index.html
. - Providing custom locations.