Hi everyone, I am quite new to Dash and Plotly and I have been a couple of days with the following problem.
I have a dropdown menu with 3 options, depending on the chosen option a Checklist with different options is displayed.
Then depending on the selected elements of the Checklist I generate an Input element for each one.
So far so good.
The problem is that now I want to make a callback to the generated Input fields, but since the Input element are generated dynamically I do not know beforehand which Input elements to include into the callback [Input(), …].
Here is a working example:
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__,
external_stylesheets=external_stylesheets,
url_base_pathname="/home/")
server = app.server
app.config.suppress_callback_exceptions = True
OPTIONS = [{'label': 'Option1', 'value': 'Option1'},
{'label': 'Option2', 'value': 'Option2'},
{'label': 'Option3', 'value': 'Option3'}]
PARAMETERS = {'Option1': [f'O1-{i}' for i in range(1, 5)],
'Option2': [f'O2-{i}' for i in range(1, 3)],
'Option3': [f'O3-{i}' for i in range(1, 7)]}
def make_parameters_dict_options(option_parameters):
parameters_dict = {}
for option, parameters in option_parameters.items():
tmp = []
for parameter in parameters:
d = {'label': parameter.replace('-', ' '), 'value': parameter}
tmp.append(d)
parameters_dict[option] = tmp
return parameters_dict
OPTION_PARAMETERS_LIST = make_parameters_dict_options(PARAMETERS)
def make_controls():
return [
html.Div([
html.Div([
dcc.Dropdown(
id='option-selector',
options=OPTIONS,
className="dcc_control"
)], className='four columns'),
html.Div([
dcc.Checklist(
id='parameters-selector'
)], className='four columns'),
], className='row'),
]
def generate_layout():
layout = html.Div([
html.Div([
html.Div(make_controls()),
], className='row'),
html.Div([
html.Div([
html.Div(id='parameters-section')
], className='six columns'),
html.Div([
html.Div(id='option-formula'),
html.Div(['I would like to update this text with a formula constructed with the \
selected parameters and the Input values given by the user'],
id='option-formula-display')
], className='six columns')
], className='row'),
])
return layout
@app.callback(
[Output('parameters-selector', 'options'),
Output('parameters-selector', 'value')],
[Input('option-selector', 'value')])
def load_option_parameters(option):
if option is None:
return [], []
option_parameters = OPTION_PARAMETERS_LIST[option]
default_value = [x['value'] for x in option_parameters]
return option_parameters, default_value
@app.callback(
Output('option-formula', 'children'),
[Input('parameters-selector', 'value')])
def make_planet_formula(parameters):
if parameters is None or len(parameters) == 0:
return ''
numbers = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve']
n_params = len(parameters)
default_factor = 1 / n_params
n_columns = numbers[int(12 / n_params)]
labels = []
factors = []
for parameter in parameters:
labels.append(html.Div([
html.Label([f'{parameter.replace("-", " ")}'])
], className=f'{n_columns} columns'))
factors.append(html.Div([
dcc.Input(id=f'factor-{parameter}',
value=round(default_factor, 2),
type='text',
debounce=True,
size='3')
], className=f'{n_columns} columns'))
layout = [html.Div(labels, className='row', id='factor-labels'),
html.Div(factors, className='row', id='factor-values')]
return html.Div(layout, className='row')
# How to create a callback for the selected set of parameters???
#@app.callback(Output('option-formula-display', 'children'), [Input(???)]
if __name__ == "__main__":
app.layout = generate_layout
app.run_server(debug=True)
How would you do it?
How to react on changes of the dcc.Input elements that are generated dynamically??
Thanks a lot for your help!
It is an awesome package!
Best,
Juan