Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
146 views
in Technique[技术] by (71.8m points)

plotly - 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

Edit: One of the hack is to add:

if children=="":
    children = []

This will work for my case but I ain't getting it why children is showing none when I have set some values ['a'] in it.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Take a look at your error:

AttributeError: 'str' object has no attribute 'append'

It's not saying that your object is None, it's saying that it is str and strings do not have an append function. Strings and None are two different types!

Now the root problem that you have is that you set your dynamic-output to a string value in the last line of your function:

def display_output(a, children):
    if a:
        (...)
        return children
    return ""

If you return a list instead of "" you should be fine.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...