Dash return None does not trigger callback function

I’ve put together a simple Dash application that contains a few Dropdown components and a callback function update_graph() that updates a bar graph ( id="plot-graph" ). For the purpose of this question, the resulting graph is not of importance, merely the callback function. Here is my sample application:

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
import pandas as pd, os, re, sys
import numpy as np

print(dcc.__version__)

cluster_options = ['Cluster1','Cluster2','Cluster3']

group_options = ['Group1','Group2','Group3','Group4']

category_options = ['Category1','Category2','Category3','Category4']

app = dash.Dash()

app.layout = html.Div([

    html.H2("Viewer"),
    html.Div(
        [
            dcc.Dropdown(
                id="Cluster",
                options=[{
                    'label': i,
                    'value': i
                } for i in cluster_options],
                placeholder='Select a cluster...'),
        ],
        style={'width': '15%',
               'display': 'inline-block'}),
    html.Div(
        [
            dcc.Dropdown(
                id="Group",
                options=[{
                    'label': i,
                    'value': i
                } for i in group_options],
                placeholder='Select a group...'),
        ],
        style={'width': '15%',
               'display': 'inline-block'}),
    html.Div(
        [
            dcc.Dropdown(
                id="Category",
                options=[{
                    'label': i,
                    'value': i
                } for i in category_options],
                placeholder='Select a category...',
                value='Overall'),
        ],
        style={'width': '15%',
               'display': 'inline-block'}),
    dcc.Graph(id='plot-graph'),

])

def clear_selected_group(Options):

    return None

def set_group_options(Cluster):

    return [{'label': i, 'value': i} for i in ['Group1','Group2']]

def update_graph(Cluster, Group, Category):

    if any(i is None for i in [Cluster, Group, Category]): print(Cluster, Group, Category)

    print(Cluster, Group, Category)

app.callback(
    Output('Group', 'value'),
    [Input('Group', 'options')]
)(clear_selected_group)

app.callback(
    Output('plot-graph', 'figure'),
    [Input('Cluster', 'value'), Input('Group', 'value'), Input('Category', 'value')]
)(update_graph)

app.callback(
    Output('Group', 'options'),
    [Input('Cluster', 'value')]
)(set_group_options)

if __name__ == '__main__':
    app.run_server()

My main question (and potentially a bug) is why the print statement is not triggered when the Dropdown value for id="Cluster" is changed? The Dropdown with id="Cluster" is listed as an Input to the update_graph() callback function, so it should be triggered, correct?

Right of the bat, I’m noticing two syntax errors:

  1. app.callback is a decorator, which means it should start with a ‘@
  2. You need a function definition that immediately follows the callback.

You should read the documentation on callbacks, but as for your question, I think the solution is to use the following instead:

@app.callback(Output('Group', 'options'),
    [Input('Cluster', 'value')])
def set_group_options(value):
    return [{'label': i, 'value': i} for i in ... ]