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
- User selects the type of search style (like simplequery)
- User selects the number of these search styles to add (say 2)
- User presses “add query” (should have 2 text fields in id=search_controls)
- At this point, the user can add an additional and/or different query style such as fieldmatch
- User selects the number of these search styles to add (say 1)
- 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
)