How to shorten callback code for 4 identical input tables?

Hi –
I’m working on a dashboard that allows the user to input four separate subsets of their data and automatically plot them side by side.

I got the structure working but my callback code is getting really unruly. I have four copies of a pretty elaborate set of input interfaces at the top and each one has its own id … so i have, for example, “fixed-date-input-1”, “fixed-date-input-2” etc.

The bigger problem is when I write my callbacks, I have to put the state of some 32 different features into every single one. The names are all modular (“name-of-feature-1”) and it would be easy to do if it was all in Python (which I know), but I tried passing a list comprehended list of features and it didn’t work.

Basically how can I avoid having to do something like this:

@app.callback(Output('compare-table-p', 'children'),
[Input('compare-output-button', 'n_clicks')],
[State('compare-date-range-flex-1', 'start_date'),
 State('compare-date-range-flex-1', 'end_date'),
 State('compare-date-range-flex-2', 'start_date'),
 State('compare-date-range-flex-2', 'end_date'),
 State('compare-date-range-flex-3', 'start_date'),
 State('compare-date-range-flex-3', 'end_date'),
 State('compare-date-range-flex-4', 'start_date'),
 State('compare-date-range-flex-4', 'end_date'),
 ])

Help!

What went wrong with the list comprehension? I would expect something like the following to work?

@app.callback(
    Output(...),
    [Input(...)],
    [
        State(f"compare-date-range-flex-{i}", prop)
        for i in range(1, 5)
        for prop in ["start_date", "end_date"]
    ]
)

Another trick that might be relevant to you is reusing a function for multiple callbacks. In this little example, I create multiple callbacks from the same function.

app.layout = html.Div(
    [
        html.Button("1", id="button-1"),
        html.Button("2", id="button-2"),
        html.Div(id="output-1"),
        html.Div(id="output-2"),
    ]
)

def square_clicks(n):
    if n:
        return n ** 2
    return None

for i in [1, 2]:
    app.callback(
        Output(f"output-{i}", "children"), [Input(f"button-{i}", "n_clicks")]
    )(square_clicks)

Perhaps if you’re doing similar things with each of the 4 subsets of your data this could help?