如何在 Dash 中更新侧边栏布局?
Posted
技术标签:
【中文标题】如何在 Dash 中更新侧边栏布局?【英文标题】:How to update sidebar layout in Dash? 【发布时间】:2021-12-24 20:28:47 【问题描述】:我根据示例制作了一个简单的侧边栏 https://dash-bootstrap-components.opensource.faculty.ai/examples/simple-sidebar/
现在我需要在用户更改页面时更改导航栏内容。我想让它动态和分层。
这意味着我应该在页面更改时更改侧边栏布局。加载普通页面内容时这很容易,但侧边栏组件不会因页面而异。
因此我认为关键问题是如何在用户点击新页面时刷新app.layout,并且脚本分别在下面的link_list中修改(modify_test)?
这是侧边栏代码的基本部分(!不工作!):
link_list = [
dbc.NavLink("Home", href="/", active="exact"),
dbc.NavLink("Page 1", href="/page-1", active="exact"),
dbc.NavLink("Page 2", href="/page-2", active="exact"),
]
def modify_test ():
link_list.append(dbc.NavLink("Page 3", href="/page-3", active="exact"))
sidebar = html.Div(
[
html.H2("Sidebar", className="display-4"),
html.Hr(),
html.P(
"A simple sidebar layout with navigation links", className="lead"
),
dbc.Nav(
link_list,
vertical=True,
pills=True,
),
],
style=SIDEBAR_STYLE,
)
content = html.Div(id="page-content", style=CONTENT_STYLE)
app.layout = html.Div([dcc.Location(id="url"), sidebar, content])
@app.callback(Output("page-content", "children"), [Input("url", "pathname")])
def render_page_content(pathname):
if pathname == "/":
return html.P("This is the content of the home page!")
elif pathname == "/page-1":
modify_test ()
return html.P("This is the content of page 1. Yay!")
elif pathname == "/page-2":
return html.P("Oh cool, this is page 2!")
# If the user tries to reach a different page, return a 404 message
return dbc.Jumbotron(
[
html.H1("404: Not found", className="text-danger"),
html.Hr(),
html.P(f"The pathname pathname was not recognised..."),
]
)
【问题讨论】:
你能解释一下当页面改变时你想用什么方式改变侧边栏布局?在我看来,您只需在针对侧边栏的回调中添加一个额外的Output
即可处理它。
@BasvanderLinden 我想让它分层,所以会有曲折和下拉列表。并且列表内容也会根据用户操作而变化。我是 Dash 和 Web 客户端的新手,所以我可能会遗漏一些明显的替代方案。例如。我不知道添加额外输出是什么意思;这应该有什么帮助?
【参考方案1】:
现在我需要在用户更改页面时更改导航栏内容。我想让它动态和分层。
这意味着我应该在页面更改时更改侧边栏布局。加载普通页面内容时这很容易,但侧边栏组件不会因页面而异。
因此我认为关键问题是如何在用户点击新页面时刷新app.layout,并且脚本分别在下面的link_list中修改(modify_test)?
我不知道你到底想做什么,但我认为没有必要刷新整个布局。回调允许我们定位和更新页面上的特定元素,而无需更新整个页面。
由于您已经有一个在页面更改时运行的回调,因此您可以向侧边栏添加一个 id 和一个 Output
,通过其 id 定位您的 sidenav 并以某种方式更新 sidenav 的某些属性。
例如可以将您的回调更改为这样的内容
@app.callback(
Output("sidebar", "style"),
Output("page-content", "children"),
Input("url", "pathname"),
)
def render_page_content(pathname):
if pathname == "/":
return "backgroundColor": "blue", html.P(
"This is the content of the home page!"
)
elif pathname == "/page-1":
return "backgroundColor": "green", html.P(
"This is the content of page 1. Yay!"
)
elif pathname == "/page-2":
return "backgroundColor": "purple", html.P("Oh cool, this is page 2!")
# If the user tries to reach a different page, return a 404 message
return "backgroundColor": "red", dbc.Jumbotron(
[
html.H1("404: Not found", className="text-danger"),
html.Hr(),
html.P(f"The pathname pathname was not recognised..."),
]
)
当页面发生变化时,上面的回调会改变页面内容和侧边栏的样式。
这只是为了让您了解如何解决问题。如果您想在页面更改时更改侧边栏的内容,您可能希望定位到侧边栏的children
属性而不是style
。
完整版之前的例子
from dash import Dash
import dash_bootstrap_components as dbc
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Output, Input
app = Dash(__name__)
SIDEBAR_STYLE =
"position": "fixed",
"top": 0,
"left": 0,
"bottom": 0,
"width": "16rem",
"padding": "2rem 1rem",
"backgroundColor": "#f8f9fa",
CONTENT_STYLE =
"marginLeft": "18rem",
"marginRight": "2rem",
"padding": "2rem 1rem",
link_list = [
dbc.NavLink("Home", href="/", active="exact"),
dbc.NavLink("Page 1", href="/page-1", active="exact"),
dbc.NavLink("Page 2", href="/page-2", active="exact"),
]
sidebar = html.Div(
id="sidebar",
children=[
html.H2("Sidebar", className="display-4"),
html.Hr(),
html.P("A simple sidebar layout with navigation links", className="lead"),
dbc.Nav(
link_list,
vertical=True,
pills=True,
),
],
style=SIDEBAR_STYLE,
)
content = html.Div(id="page-content", style=CONTENT_STYLE)
app.layout = html.Div([dcc.Location(id="url"), sidebar, content])
@app.callback(
Output("sidebar", "style"),
Output("page-content", "children"),
Input("url", "pathname"),
)
def render_page_content(pathname):
if pathname == "/":
return "backgroundColor": "blue", html.P(
"This is the content of the home page!"
)
elif pathname == "/page-1":
return "backgroundColor": "green", html.P(
"This is the content of page 1. Yay!"
)
elif pathname == "/page-2":
return "backgroundColor": "purple", html.P("Oh cool, this is page 2!")
# If the user tries to reach a different page, return a 404 message
return "backgroundColor": "red", dbc.Jumbotron(
[
html.H1("404: Not found", className="text-danger"),
html.Hr(),
html.P(f"The pathname pathname was not recognised..."),
]
)
if __name__ == "__main__":
app.run_server()
【讨论】:
看来您已经从示例中删除了 modify_test() 功能。这就是相关侧边栏发生变化的地方:在侧边栏中添加一个新的选择项。没有那个,不幸的是这个例子对我没有用。 重要的部分是这个例子所展示的想法并没有像它到底做了什么。您可以采用此答案中显示的想法并将其应用于您自己的用例。在您的情况下,您可以添加一个State
来跟踪您的导航项目,并在您的回调中返回一个新的项目列表:当前值列表(状态)附加一个选项。
感谢这个想法。在我对 Dash 事物的研究中还要学习一件事。同时,我绕过了这个问题,让 app.layout 根本没有侧边栏,但每个页面都会加载自己的修改版侧边栏。以上是关于如何在 Dash 中更新侧边栏布局?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 codeigniter 制作基本布局(页眉、页脚、侧边栏)