Update div children from callback

I am building a dynamic query interface where I need to update the div children properties via a callback.

What I am trying to do is, if the div has children I want the callback to generate some new components and add/update them to the existing div children. But I am missing some call that will convert the newly created component into properties such that I can update the existing children properly. Or I am not approaching this in the the correct way?

Here is small example, I hope it is clear what I am trying to do. Any help, tips would be appreciated.

thanks
-george

Simple layout/User Flow

  1. User selects the type of search style (like simplequery)
  2. User selects the number of these search styles to add (say 2)
  3. User presses “add query” (should have 2 text fields in id=search_controls)
  4. At this point, the user can add an additional and/or different query style such as fieldmatch
  5. User selects the number of these search styles to add (say 1)
  6. Selects “add query”

At this point I want to see both the 2 previous text fields from simplequery
AND a new text field (for fieldmatch) within id=search_controls, but I don’t
I am fairly certain I am not updated the search_controls properly within the callback.
I feel I am missing some call to convert the dcc.XXX() back into properties for
the div child property

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)
app.config.supress_callback_exceptions=True

def gen_dcc_input(id,placeholder='Add simple query phrase'):
    return  dcc.Input(
                id='qb_text_field-{}'.format(id),
                placeholder=placeholder,
                type='text',
                value='',
                style={'width': '80%'}
            ).

def gen_dcc_slider(id,min=0,max=1000,step=1,value=1):
    return  dcc.Slider(
                id='qb_rangefilter-{}'.format(id),
                min=min,
                max=max,
                step=step,
                value=value,
            )          
   

app.layout = html.Div(children=[
    html.H1(children='Search Query Builder'),
    html.Div(children='''Choose a Search Style....'''),
        dcc.RadioItems(
            id='search_style', 
            options=[
                {'label': 'Simple Query', 'value': 'simplequery'},
                {'label': 'Field Match', 'value': 'fieldmatch'},
                {'label': 'Range Filter', 'value': 'rangefilter'},
                {'label': 'Geo Filter', 'value': 'geofilter'}                                    
            ],
            value='simplequery'
        ),
        dcc.Dropdown(
            id='num_of_queries',
            options=[
                    {'label': '1', 'value': 1},
                    {'label': '2', 'value': 2},
                    {'label': '4', 'value': 4}
            ],
            value='start',
            style={'width': '40%'}   
        ),
        html.Button('Add Query ', id='btn_query_field',n_clicks=0),
        html.Div(
            id='search_controls'
        ) 

])

@app.callback(
        Output('search_controls', 'children'),
    [
        Input('btn_query_field', 'n_clicks')
                            
    ],
    [   
        State('num_of_queries','value'),
        State('search_style','value') , 
        State('search_controls', 'children')
    ]               
)
def add_query_fields(n_clicks,num_of_queries,search_style,div_children):
    print ("--------------div children-----------------")
    print (div_children)
    print (search_style)

    if n_clicks >0 and search_style=='simplequery':
        query_list = [gen_dcc_input(x) for x in range(int(num_of_queries))]
        if div_children:             
            return div_children.append(query_list)
        else: 
            return query_list

    if n_clicks >0 and search_style=='fieldmatch':
        query_list = [gen_dcc_input(x,placeholder='Add field match term') for x in range(int(num_of_queries))]
        if div_children:
            return div_children.append(query_list)
        else:
            return query_list

    if n_clicks >0 and search_style=='rangefilter':
        query_list = [gen_dcc_slider(x,min=0,max=1000,step=1,value=1) for x in range(int(num_of_queries))]
        if div_children:
            return div_children.append(query_list)
        else:
            return query_list


if __name__ == '__main__':
    app.run_server(
        debug=True,
        host='0.0.0.0',
        port=9999
)

@neogeo , did you find a way yet? :slight_smile: