Plotly Dash Core 组件在回调中设置并输出给子组件时不呈现
Plotly Dash Core components not rendering when set in call back and output to children
我想在 dash 应用程序中有一组动态控件,这些控件会根据下拉列表的输入而变化。这些值来自 pandas 数据框。
但是,当我将回调中的 return 值设置为破折号核心组件时,例如。下拉列表或范围滑块 - 只有在布局中声明的才会呈现,但回调中的不会呈现。
布局如下所示:
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
似乎从未触发回调,因为我包含了一个似乎从未被命中的打印函数。
这里的任何建议都会有所帮助,除了在布局中声明组件,这不是我希望包含的动态控件的选项。
谢谢
不幸的是,这是 Dash 的一个限制。任何未使用布局初始化的组件或回调都将无法运行。
如果您有已知数量的可能组件想要 activate/deactivate,您可以将它们加载到容器内的布局中,样式属性为 style=dict(display="none")
。为每个组件使用一个回调,然后您可以在需要时显示组件,在不需要时隐藏它。这可能是一个负担,但如果您想要使用 Dash 的动态 UI,这确实是唯一的选择。
我想在 dash 应用程序中有一组动态控件,这些控件会根据下拉列表的输入而变化。这些值来自 pandas 数据框。
但是,当我将回调中的 return 值设置为破折号核心组件时,例如。下拉列表或范围滑块 - 只有在布局中声明的才会呈现,但回调中的不会呈现。
布局如下所示:
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
似乎从未触发回调,因为我包含了一个似乎从未被命中的打印函数。
这里的任何建议都会有所帮助,除了在布局中声明组件,这不是我希望包含的动态控件的选项。
谢谢
不幸的是,这是 Dash 的一个限制。任何未使用布局初始化的组件或回调都将无法运行。
如果您有已知数量的可能组件想要 activate/deactivate,您可以将它们加载到容器内的布局中,样式属性为 style=dict(display="none")
。为每个组件使用一个回调,然后您可以在需要时显示组件,在不需要时隐藏它。这可能是一个负担,但如果您想要使用 Dash 的动态 UI,这确实是唯一的选择。