Компоненты Plotly Dash Core не рендерится, когда установлены в обратном вызове и выводятся дочерним элементам - PullRequest
0 голосов
/ 22 мая 2019

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

Однако, когда я устанавливаю возвращаемое значение в обратном вызове как компонент ядра тире, например.Выпадающий или Ползунок диапазона - отображается только тот, который объявлен в макете, но тот, который в обратном вызове, отсутствует.

Макет выглядит следующим образом:

app.layout = html.Div([
    # Controls
    html.Div([

        #Top Layer Controls
        html.Div([

            #Project Dropdown
            html.Div([
                make_dropdown_menu(list(name_to_id.keys()), list(name_to_id.values()), id="project_selctor")
            ]),

            #date Slider
            html.Div(id = 'date_slider')

        ]),

        # State Controls

        html.Div([
            # Track State
            html.Div(id = 'track_state_dropdown_multi'),

            # Track Tags
            html.Div(id = 'track_tags_dropdown_multi'),

            # Track Changes
            html.Div(id = 'track_changes_dropdown_multi'),
        ]),

        # Filters

        html.Div([

            #Track Length
            html.Div(id = 'track_lenth_slider'),

            #Stop Numbers
            html.Div(id = 'number_of_stops_slider'),
        ]),

        html.Div(id = 'Selections')

    ])
])

, и я настроилобратные вызовы выглядят так:

@app.callback(
    Output('track_state_dropdown_multi', 'children'),
    [Input("project_selctor", 'value')]
)
def update_project_df(value):
    filter_df = filter_track_data_by_project(track_data, value)

    menu = make_dropdown_menu(
        labels=filter_df.track_state.unique(),
        values=filter_df.track_state.unique(),
        id= "track_state_dropdown_comp",
        multi= True
    )
    return html.Div([menu])


@app.callback(
    Output('track_tags_dropdown_multi', 'children'),
    [Input("project_selctor", 'value')]
)
def update_project_df(project_selector):
    filter_df = filter_track_data_by_project(track_data, project_selector)
    menu = make_dropdown_menu(
        labels=list(set(flatten(filter_df.tags))),
        values = list(set(flatten(filter_df.tags))),
        id = 'track_tags_dropdown_comp',
        multi= True
    )
    return html.Div([menu])

@app.callback(
    Output('track_changes_dropdown_multi', 'children'),
    [Input("project_selctor", 'value')]
)
def update_project_df(project_selector):
    filter_df = filter_track_data_by_project(track_data, project_selector)
    track_changes = pd.DataFrame(flatten(filter_df.track_changes))
    menu = make_dropdown_menu(
        labels = track_changes.action.unique(),
        values = track_changes.action.unique(),
        id = "track_changes_dropdown_comp",
        multi = True

    )
    return html.Div([menu])

@app.callback(
    Output('track_length_slider', 'children'),
    [Input("project_selctor", 'value')]
)
def update_project_df(project_selector):
    filter_df = filter_track_data_by_project(track_data, project_selector)
    slider = dcc.RangeSlider(
        id = 'track_length_slider_comp',
        min = filter_df.track_lengh.min(),
        max = filter_df.track_lengh.max(),
        steps = 0.5

    )
    return html.Div([slider])

@app.callback(
    Output('number_of_stops_slider', 'children'),
    [Input("project_selctor", 'value')]
)
def update_project_df(project_selector):
    filter_df = filter_track_data_by_project(track_data, project_selector)
    slider = dcc.RangeSlider(
        id = 'number_of_stops_slider_comp',
        min = filter_df.number_of_stops.min(),
        max = filter_df.number_of_stops.max(),
        steps = 1

    )
    return html.Div([slider])

@app.callback(
    Output('Selections', 'children'),
    [Input('number_of_stops_slider_comp', 'value'),
    Input('track_changes_dropdown_comp', 'value')]
)
def update(stops, track):
    return('stops: {0}, tracks: {1}'.format(str(stops), str(track)))

И вот соответствующие вспомогательные функции:

def make_dropdown_menu(labels, values, id, multi=False, **kwargs):
    options = []
    for i in range(len(labels)):
        d = dict(
            label = labels[i],
            value = values[i]
        )

        options.append(d)

    menu = dcc.Dropdown(
        id = id,
        options = options,
        value = options[0]['value'],
        style = {'width':'100%'}
    ) 
    return menu


def filter_track_data_by_project(df, proj_id):
    filtered_df = df[df.project_id ==  proj_id] 
    print(len(filtered_df))
    return filtered_df

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

Любой совет здесь будет полезен, за исключением объявления компонентов в макете, который не является опцией для динамических элементов управления, которые я хочу включить.

Спасибо

1 Ответ

1 голос
/ 23 мая 2019

К сожалению, это ограничение для Dash.Любой компонент или обратный вызов, который не инициализирован с макетом, просто не будет функционировать.

Если у вас есть известное количество возможных компонентов, которые вы хотите активировать / деактивировать, вы можете загрузить их в макет внутри контейнеров со стилем prop как style=dict(display="none").Используя обратный вызов для каждого из них, вы можете показать компонент, когда вы хотите, чтобы он был доступен, и скрыть его, когда вы этого не сделаете.Это может быть обременительным, но это действительно единственный выбор, если вы хотите динамический интерфейс с использованием Dash.

...