Callback function does not work correctly with Bulma tiles layout


#1

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)