Ошибка видимости обратного вызова компонента Da sh - PullRequest
0 голосов
/ 17 апреля 2020

Я недавно работал над приложением, использующим Da sh. Приложение использует ряд элементов управления, например, Input и Dropdown из основных компонентов. Одна функция, которую я хотел включить, состояла в том, что только один из входных данных или раскрывающийся список является видимым за один раз, и какой из них видимый, зависит от того, что выберет пользователь (т. Е. Мы используем обратный вызов). Вот минимальный пример:

import dash
import dash_core_components as dcc
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output

app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])

controls = dbc.Card(
    [
        dbc.FormGroup(
            [
               dbc.Label("Choose input or dropdown"),
               dbc.RadioItems(
                   id='radio',
                   options=[
                       {'label': 'input', 'value': 'input'},
                       {'label': 'dropdown', 'value': 'dropdown'},
                   ],
                   value='input',
               ),
            ]
        ),
        dbc.FormGroup(
            [
                dbc.Label("Input", id='input-label'),
                dbc.Input(
                    id='input',
                    type='number',
                    min=1, max=100, step=1, value=5
                ),
            ]
        ),
        dbc.FormGroup(
            [
                dbc.Label("Dropdown", id='dropdown-label'),
                dcc.Dropdown(
                    id='dropdown',
                    options=[
                        {'label': 'Hello'+str(i), 'value': 'Hello'+str(i)} for i in range(100)
                    ],
                    multi=True,
                    placeholder='Say Hello',
                ),
            ]
        ),
    ],
    body=True,
    color='light',
)

app.layout = dbc.Container(
    [
        dbc.Row(
            [
                dbc.Col(controls, md=4)
            ],
            align='center',
        ),
    ],
    fluid=True,
)

@app.callback(
    [Output('input', 'style'),
     Output('input-label', 'style'),
     Output('dropdown', 'style'),
     Output('dropdown-label', 'style')],
    [Input('radio', 'value')])
def visibility(selected_type):
    if selected_type == 'input':
        return {'display': 'block'}, {'display': 'block'}, {'display': 'none'}, {'display': 'none'}
    else:
        return {'display': 'none'}, {'display': 'none'}, {'display': 'block'}, {'display': 'block'}


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

Однако использование обратного вызова разрушает функциональность раскрывающегося списка. Например, попробуйте включить 10 или около того «Привет» в раскрывающемся списке. Теперь, если вы закомментируете обратный вызов в коде, функциональность будет восстановлена: добавление множества «Hello» приводит к расширению выпадающего списка для их сохранения, как и предполагалось.

Может кто-нибудь объяснить, почему мой обратный вызов вызывает такое поведение?

1 Ответ

0 голосов
/ 17 апреля 2020

Проблема заключается в том, что вы непосредственно перезаписываете стили компонента ввода и компонента раскрывающегося списка в обратном вызове. Чтобы предотвратить эту проблему, вы можете назначить идентификатор их контейнерам, а затем изменить стили контейнеров в обратном вызове. При таком подходе компонент ввода и раскрывающийся компонент сохранят свое поведение по умолчанию.

import dash
import dash_core_components as dcc
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output

app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])

controls = dbc.Card(
    [
        dbc.FormGroup(
            [
               dbc.Label('Choose input or dropdown'),
               dbc.RadioItems(
                   id='radio',
                   options=[
                       {'label': 'input', 'value': 'input'},
                       {'label': 'dropdown', 'value': 'dropdown'},
                   ],
                   value='input',
               ),
            ]
        ),
        dbc.FormGroup(id='input-form', children=
            [
                dbc.Label('Input', id='input-label'),
                dbc.Input(
                    id='input',
                    type='number',
                    min=1, max=100, step=1, value=5
                ),
            ]
        ),
        dbc.FormGroup(id='dropdown-form', children=
            [
                dbc.Label('Dropdown', id='dropdown-label'),
                dcc.Dropdown(
                    id='dropdown',
                    options=[
                        {'label': 'Hello'+str(i), 'value': 'Hello'+str(i)} for i in range(100)
                    ],
                    multi=True,
                    placeholder='Say Hello',
                ),
            ]
        ),
    ],
    body=True,
    color='light',
)

app.layout = dbc.Container(
    [
        dbc.Row(
            [
                dbc.Col(controls, md=4)
            ],
            align='center',
        ),
    ],
    fluid=True,
)

@app.callback([Output('input-form', 'style'), Output('dropdown-form', 'style')],
    [Input('radio', 'value')])
def visibility(selected_type):

    if selected_type == 'input':

        return {'display': 'block'}, {'display': 'none'}

    else:

        return {'display': 'none'}, {'display': 'block'}

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