Learn how to use Dash Bio for next-gen sequencing & quality control. 🧬Register for the Oct 27 webinar.

Unable to append in the div children component

I am having multiple dropdown which are dependent on each other. They will have the same list of values. But If I choose values from anyone of the dropdown then others dropdown can’t take that value. So this part is working.

The part I am struck is:

I have three dropdowns. If I select from the 1st dropdown then it will append a range slider for each selected values.

If from 2nd dropdown then it will append a datepicker for each selected values
3rd dropdown will be for the text box.

This part children.append(slider_comp) gives me error:

Callback error updating {"index":"num","type":"dynamic-output"}.children
Traceback (most recent call last):
  File "/media/kriti/Data_Drive/flask_app/flask_page/annot_app/t4.py", line 136, in display_output
    children.append(slider_comp)
AttributeError: 'str' object has no attribute 'append'

I know this value is none that’s why it is giving an error But how to resolve it?

Code:

# -*- coding: utf-8 -*-
import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State, ALL, MATCH

app = dash.Dash(__name__)

# all_options = {
#     'America': ['New York City', 'San Francisco', 'Cincinnati'],
#     'Canada': [u'Montréal', 'Toronto', 'Ottawa']
# }

all_options = [i for i in range(10)]
app.layout = html.Div([



    dcc.Dropdown(
        id={'type':'dropdown', 'index':'num'},
        options=[{'label': k, 'value': k} for k in all_options],
        value=[],
        multi=True
    ),

    html.Div(
    id={
        'type': 'dynamic-output',
        'index': 'num'
        },
    children =['a']
    ),
    html.Hr(),

    dcc.Dropdown(
        id={'type':'dropdown', 'index':'date'},
        options=[{'label': k, 'value': k} for k in all_options],
        value=[],
        multi=True
    ),

    html.Div(
    id={
        'type': 'dynamic-output',
        'index': 'date'
        },
    children =['b']
    ),
    html.Hr(),

    dcc.Dropdown(
        id={'type':'dropdown', 'index':'text'},
        options=[{'label': k, 'value': k} for k in all_options],
        value=[],
        multi=True
    ),


    html.Div(
    id={
        'type': 'dynamic-output',
        'index': 'text'
        },
    children =['c']
    ),

    html.Div(id='display-selected-values')
])




# def set_options(values1, values2):
#     print(values1, values2)


# col = ['date', 'num', 'text']
# for i in range(3):
#     app.callback(
#         dash.dependencies.Output(f'{col[i%3]}-dropdown', 'options'),
#         [dash.dependencies.Input(f'{col[(i+1)%3]}-dropdown', 'value'), dash.dependencies.Input(f'{col[(i+2)%3]}-dropdown', 'value')])(set_options)




@app.callback(
    dash.dependencies.Output({'type':'dropdown', 'index':'date'}, 'options'),
    [dash.dependencies.Input({'type':'dropdown', 'index':'num'}, 'value'), dash.dependencies.Input({'type':'dropdown', 'index':'text'}, 'value')])
def set_date_options(values_num, values_text):
    values = values_num + values_text
    return [{'label': i, 'value': i} for i in [e for e in all_options if e not in values]]


@app.callback(
    dash.dependencies.Output({'type':'dropdown', 'index':'num'}, 'options'),
    [dash.dependencies.Input({'type':'dropdown', 'index':'date'}, 'value'), dash.dependencies.Input({'type':'dropdown', 'index':'text'}, 'value')])
def set_num_options(values_date, values_text):
    values = values_date + values_text
    return [{'label': i, 'value': i} for i in [e for e in all_options if e not in values]]


@app.callback(
    dash.dependencies.Output({'type':'dropdown', 'index':'text'}, 'options'),
    [dash.dependencies.Input({'type':'dropdown', 'index':'num'}, 'value'), dash.dependencies.Input({'type':'dropdown', 'index':'date'}, 'value')])
def set_num_options(values_num, values_date):
    values = values_num + values_date
    return [{'label': i, 'value': i} for i in [e for e in all_options if e not in values]]



@app.callback(
    dash.dependencies.Output('display-selected-values', 'children'),
    [dash.dependencies.Input({'type':'dropdown', 'index':'num'}, 'value'),
     dash.dependencies.Input({'type':'dropdown', 'index':'date'}, 'value'),
     dash.dependencies.Input({'type':'dropdown', 'index':'text'}, 'value')])
def set_display_children(value_num, value_date, value_text):
    return u'{} is a city in {} {}'.format(
        value_num, value_date, value_text,
    )


@app.callback(
    Output({'type': 'dynamic-output', 'index': MATCH}, 'children'),
    [Input({'type':'dropdown', 'index':MATCH}, 'value')],
    [State({'type': 'dynamic-output', 'index': MATCH}, 'children')]
)
def display_output(a, children):
    if a:
        print("-->",children)
        slider_comp = html.Div(children=dcc.RangeSlider(id=f'num_filter',
                                          updatemode='drag', \
                                          min=(1), max=(10), \
                                          value=[(1), (10)], step=1)
        )
        children.append(slider_comp)
        return children
    return ""


if __name__ == '__main__':
    app.run_server(debug=True)

enter image description here

Hi @nkx try using the code below

    if a:
        print("-->",children)
        slider_comp = html.Div(children=dcc.RangeSlider(id=f'num_filter',
                                          updatemode='drag', \
                                          min=(1), max=(10), \
                                          value=[(1), (10)], step=1)
        )
        return slider_comp
    else:
        return ""

Thing is I want to append them.

This will make div to overlap.

One of the hack is:

    if children=="":
        children = []

But the problem is suppose if there is a children = [‘a’] in the those html.Div. It won’t show anything in the callback.