Storing variable number of user created slider values in hidden div

I’m dynamically generating a variable number of sliders based on user input, but have no way of easily passing the values from those sliders to a hidden div per the recommended callback Dash documentation Example 1. I originally thought that the way to do this would be a callback within a callback (outside callback to get active slider names, inside callback to retrieve value from each callback) but in looking through the Dash documentation and help forums, this doesn’t appear to be possible. My current plan of attack for creating sliders has been generating a maximun number of sliders and then modifying the display style (though this is significantly slower than my previous callback which generated sliders in their own divs based on the dropdown menu input.) The number of sliders generated will be variable, as I am planning on adding an additional user input field for the dropdown menu.

Each slider has a unique ID, so ideally I wish I could use the upcoming wildcard component to retrieve all IDs with ‘-slider’, but basically I want to retrieve the value of any active slider and store it. Some testing (see the try_children function) has indicated that I can actually get the items within a div as input in a callback if the input is set to children, but I haven’t been able to manipulate this to my benefit and it seems to be laggy.

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
import dash_table
import plotly.graph_objs as go
import dash_daq as daq
import sd_material_ui
import dash_flexbox_grid as dfx

app = dash.Dash(
    __name__,
    meta_tags=[{'name': 'viewport',
                'content': 'Width=device-width, initial-scale=1'}]
    )

server = app.server
app.config['suppress_callback_exceptions'] = True

# Option list - provide nested dictionary of categories and dropdowns
categories = {'design': ['test-1', 'test-2'],
              'analysis': ['test-3', 'test-4'],
              'construction': ['test-5', 'test-6']}

max_field_number = 5


def build_app_banner():
    return html.Div(
        id='banner',
        className='banner',
        children=[
            html.Div(
                id='banner-text',
                children=[
                    html.H1('AckACk'),
                    html.H2('Skills Matrix')
                ],
            ),
        ],
    )


def generate_section_banner(title):
    return html.H4(className='section-banner', children=title,
                   style={'font-variant': 'small-caps'})


def generate_skill_banner(title):
    return html.H5(className='skill-banner', children=title,
                   style={'font-variant': 'small-caps'})


def generate_sliders(category, number):
    return [html.Div(id=category + '-' + str(i),
                     children=[
                        html.H4(id=category + '-skill-banner-' + str(i),
                                style={'font-variant': 'small-caps'}),
                        dcc.Slider(
                            id=category + '-slider-' + str(i),
                            min=0,
                            max=5,
                            step=1,
                            value=0,
                            dots=True,
                            marks={0: '0', 1: '1', 2: '2', 3: '3', 4: '4', 5: '5'},
                            ),
                        html.Br()],
                     style={'display': 'none'}) for i in range(number)]


def generate_category_container(category_name):
    return html.Div(
        id=category_name + '-container',
        children=[
            generate_section_banner(category_name),
            html.Div(
                id=category_name + '-menu',
                children=[
                    dcc.Dropdown(
                        id=category_name + '-select-dropdown',
                        options=list(
                            {'label': param, 'value': param}
                            for param in categories[category_name]
                            ),
                        value=[],
                        multi=True,
                        placeholder='Select skills...'
                    ),
                    html.Div(id=category_name + '-output-state',
                             children=generate_sliders(category=category_name, number=max_field_number)
                             ),
                    html.Br()
                ]
            )
        ]
    )


def build_tab(category):
    return [dfx.Grid(id=category+'-grid', fluid=True,
                     children=[
                        dfx.Row(children=[
                            dfx.Col(lg=6, md=6,
                                    children=generate_category_container(category)
                                    ),
                            dfx.Col(lg=6, md=6)
                            ])
                        ])]


def build_tabs(categories):
    category_tabs = []
    for category in categories:
        category_tab = dcc.Tab(id=category + '-tab',
                               label=category,
                               value=category,
                               className='custom-tab',
                               selected_className=category + '-custom-tab--selected',
                               children=build_tab(category))
        category_tabs.append(category_tab)
    return html.Div(
        id='tabs',
        className='tabs',
        children=[
            dcc.Tabs(
                id='app-tabs',
                value='design',
                className='custom-tabs',
                children=category_tabs)
            ]
        )


def build_hidden_storage(categories):
    return [html.Div(id=category + '-stored-slider-state',
                     children=html.Div(id=category + '-stored-slider-values'))
            for category in categories]


app.layout = dfx.Grid(id='grid', fluid=True, children=[
    dfx.Row(children=[
        dfx.Col(lg=1),
        dfx.Col(xs=12, lg=10,
                children=[
                    sd_material_ui.Paper([
                        html.Div(
                            id='big-app-container',
                            children=[
                                build_app_banner(),
                                html.Div(
                                    id='app-container',
                                    children=[
                                        build_tabs(categories),
                                        # Main app
                                        html.Div(id='app-content')
                                        ]
                                    ),
                                html.Div(id='user-stored-sliders',
                                         children=build_hidden_storage(categories))
                                ]
                            )
                        ])
                    ]),
        dfx.Col(lg=1)
        ])
    ])


for category in categories:
    skill_display = [Output(category + '-' + str(i), 'style')
                     for i in range(max_field_number)]
    skill_name = [Output(category + '-skill-banner-' + str(i), 'children')
                  for i in range(max_field_number)]
    skill_output = skill_name + skill_display
    @app.callback(
        skill_output,
        [Input(category + '-select-dropdown', 'value')]  # make visible
        )
    def display_sliders(skills):
        display_dict = {'display': 'initial'}
        no_display_dict = {'display': 'none'}
        display_list = [display_dict if i < len(skills) else no_display_dict
                        for i in range(max_field_number)]
        name_list = [skills[i] if i < len(skills) else '0'
                     for i in range(max_field_number)]
        return (name_list + display_list)

@app.callback(
    [Output('design-stored-slider-values', 'value')],
    [Input('design-output-state', 'children')]
    )
def try_children(children):
    print(len(children))
    for item in children:
        print(item['props'])
        print()
    return ['test']


# Running the server
if __name__ == '__main__':
    app.run_server(debug=True, port=8051)

The hidden Div isnt the best way to do this anymore. Check out the dcc.Store component, you can store JSON formatted Data locally or session based. Cheers!