I am trying to build a HTML layout for a Dash app using the Bulma template. I assumed I can just use the Bulma classes in classNames
for the dash_html_components
and wanted to build a layout using Bulma tiles.
I have a dcc.Graph
component and a dcc.RadioItems
component with the options
options=[{'label': 'Marker', 'value': 'markers'},
{'label': 'Lines', 'value': 'lines'}],
There is also a callback function that updates the visualisation mode of the graph component to lines
or markers
dependent on the value of the RadioButtons. When I want to place the dcc.Graph
inside Bulma tiles using the classes tile
is-8
and is-child
together it breaks and nothing changes anymore, when I click on the radio buttons.
This is how it looks like. Marker is selected, but Lines are plotted, since nothing happens, when I click on the buttons. Normally it should switch between markers / lines. Other UI elements also do not work anymore. So somehow the callback functions seems to be broken here.
When I remove either is-8
or is-child
from the Div
's class names, it is working, but they are actually necessary for these Bulma styles. Does anyone understand what is the issue here and why the callback does not seem to work properly depending on which classes I give my Div elements?
That’s the code, where the Bulma tile structure is derived from my larger project, but broke down to a minimal example.
import os
import numpy as np
import pandas as pd
import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
from datetime import datetime as dt
from functools import lru_cache
app = dash.Dash(__name__)
app.scripts.config.serve_locally = False
app.config.include_asset_files = True
# add css files from plotly dash tutorials
app.css.append_css({"external_url": "https://codepen.io/chriddyp/pen/bWLwgP.css"})
# Read .csv files and store in data frames dictionary
tables = [f.replace('_', ' ').replace('.csv', '') for f in os.listdir('./csv/')]
filenames = os.listdir('./csv/')
datapath = './csv/'
dataframes = {}
for f, table in zip(filenames, tables):
df = pd.read_csv(datapath + f, index_col=0)
df.index = pd.to_datetime(df.index, format='%Y')
dataframes[table] = df
start_date = '1990-01-01'
end_date = '2017-12-31'
# Then each string in table is shown in the dropdown-menu `table-dropdown`
# The dropdown-menu 'column-selector' shows all available columns in the corresponding DataFrame
app.layout = html.Section(className='section', children=[
html.Div(className='container', children=[
html.Div(id='wrapper', children=[
html.Label('Select Table'),
dcc.Dropdown(
id='table-dropdown',
options=[{'label': k, 'value': k} for k in tables],
value=tables[0]
),
]),
html.Div(className='tile is-ancestor', children=[
html.Div(className='tile is-8', children=[
html.Div(className='tile is-parent', children=[
html.Div(className='tile is-child box', children=[
dcc.Graph(id='plot-graph'),
]),
]),
]),
]),
html.Div([
# Mode Selection
html.H4(className='title has-text-weight-bold is-4 has-text-info',
children='Visualisation'),
dcc.RadioItems(
id='vis-selector',
options=[
{'label': 'Marker', 'value': 'markers'},
{'label': 'Lines', 'value': 'lines'}
],
value='lines',
),
]),
])
])
@app.callback(
dash.dependencies.Output('column-selector', 'options'),
[dash.dependencies.Input('table-dropdown', 'value')])
def set_column_options(table):
first = table[0]
return [{'label': column, 'value': column} for column in dataframes[table].columns]
@app.callback(
dash.dependencies.Output('column-selector', 'value'),
[dash.dependencies.Input('column-selector', 'options')])
def set_column_value(columns):
return columns[0]['value']
@app.callback(
dash.dependencies.Output('plot-graph', 'figure'),
[dash.dependencies.Input('table-dropdown', 'value'),
dash.dependencies.Input('column-selector', 'value'),
dash.dependencies.Input('vis-selector', 'value'),
])
def plot_selected(table, column, vis_mode):
df = dataframes[table]
# test datetime selection
data = df[column]
return {
'data': [go.Scattergl(
x=df.index,
y=data,
mode=vis_mode,
)],
'layout': go.Layout(
xaxis={
'title': 'Time',
},
yaxis={
'title': column,
}
)
}
if __name__ == '__main__':
app.run_server(debug=True)