我希望当用户加载该应用程序并查看应用程序的“会话”选项卡时,会出现一个可见的“新建”按钮,最终将带他们进入一个新的...
我希望当用户加载该应用程序并查看应用程序的“会话”选项卡时,可以看到“新建”按钮,最终会将用户带到新记录表单。但是,如果用户选择现有表中的一行,我希望可以看到“编辑”按钮,以便他们可以编辑所选的一行。
在大多数情况下,我都可以使用此功能,但是我在选择一行时遇到了一些问题,编辑按钮会闪烁,然后最终消失。我相信问题与我的 selected_active_practive_session()
反应式计算有关。当我逐步执行时,它第一次返回正确的行 ID,但 Shiny App 会强制它再次运行,然后再次运行,最终将输出值更改为 None。这导致“编辑”按钮闪烁,然后保持关闭状态。
#core
import pandas as pd
# Web/Visual frameworks
from shiny import App, ui, render, reactive, types
df_sessions = pd.DataFrame(
{'Date':['9-1-2024','9-2-2024','9-3-2024','9-4-2024'],
'Song_id':[1,1,2,2],
'Notes':['Focused on tempo (65bpm)','focused on tempo (70bpm)','Started learning first page','Worked on first page']})
app_ui = ui.page_fluid(
ui.page_navbar(
ui.nav_panel("New Practice Session", "New Practice Session - Input Form"),
ui.nav_panel("New Song", "New Song - Input Form"),
ui.nav_panel("New Artist", "New Artist - Input Form"),
title="Guitar Study Tracker",
id="page",
),
ui.output_ui('page_manager'),
)
def server(input, output, session):
def nav_song(): # Placeholder
return "Song"
def nav_artist(): # Placeholder
return "Artist"
@render.data_frame
def session_summary():
return render.DataGrid(
df_sessions,
width="100%",
height="100%",
selection_mode="row"
)
@reactive.calc()
def selected_active_practice_session():
"""Returns the row id of a selected row, otherwise returns None"""
try:
row_id = session_summary.cell_selection()['rows']
row_id = row_id[0] if len(row_id)>0 else None # sets row_id to the selected row or None otherwise
except types.SilentException as e: # On first run this control will not exist by default - catch it's SilentException
row_id=None
return row_id
@reactive.calc
def ui_practice_session_button():
if selected_active_practice_session() is not None:
return ui.input_action_button("btn_update_session", "Update", width='100%')
else:
return None
@reactive.calc
def nav_practice_session():
ret_ui = ui.row(
ui.row(ui.column(2, ui_practice_session_button()),
ui.column(8),
ui.column(2,ui.input_action_button("btn_new_session", "New", width="100%")),
),
ui.output_data_frame("session_summary")
)
return ret_ui
@render.ui
def page_manager():
if input.page()=="New Practice Session":
return nav_practice_session()
if input.page()=="New Song":
return nav_song()
if input.page()=="New Artist":
return nav_artist()
return None
app = App(app_ui, server)
示例中按钮闪烁且最终不可见的问题在于, ui
由于相互依赖,相关的按钮被重新渲染多次 @reactive.calc
,并且重新渲染后的 ui
表 cell_selection()
为空(因为选择出现在“前一个”表中),导致没有按钮可见。
相反,您可以定义 ui
而不在 外面添加按钮 server
,并定义一个占位符 ui.div
,按钮稍后应该在该占位符处可见。然后, ui.insert_ui
ui.insert_ui div
。下面还有一个反应值,用于跟踪按钮是否可见,这样就不能再插入第二个按钮了。
,如果您需要删除按钮, ui.remove_ui
ui.remove_ui ui
在服务器内渲染更多内容,下面的方法同样有效。
import pandas as pd
from shiny import App, ui, render, reactive, req
df_sessions = pd.DataFrame(
{'Date': ['9-1-2024', '9-2-2024', '9-3-2024', '9-4-2024'],
'Song_id': [1, 1, 2, 2],
'Notes': ['Focused on tempo (65bpm)', 'focused on tempo (70bpm)', 'Started learning first page', 'Worked on first page']})
app_ui = ui.page_fluid(
ui.page_navbar(
ui.nav_panel("New Practice Session", "New Practice Session - Input Form",
ui.row(
ui.row(ui.column(2, ui.div(id="placeholder")),
ui.column(8),
ui.column(2, ui.input_action_button(
"btn_new_session", "New", width="100%")),
),
ui.output_data_frame("session_summary")
)),
ui.nav_panel("New Song", "New Song - Input Form",
"Song"),
ui.nav_panel("New Artist", "New Artist - Input Form",
"Artist"),
title="Guitar Study Tracker",
id="page",
),
ui.output_ui('page_manager'),
)
def server(input, output, session):
updateButtonVisible = reactive.value(False)
def nav_song(): # Placeholder
return "Song"
def nav_artist(): # Placeholder
return "Artist"
@render.data_frame
def session_summary():
return render.DataGrid(
df_sessions,
width="100%",
height="100%",
selection_mode="row"
)
@reactive.effect
def insert_update_button():
data_selected = session_summary.data_view(selected=True)
req(not (data_selected.empty or updateButtonVisible.get()))
ui.insert_ui(
ui.input_action_button("btn_update_session",
"Update", width='100%'),
selector="#placeholder",
where="beforeBegin"
)
updateButtonVisible.set(True)
@render.ui
def page_manager():
if input.page() == "New Song":
return nav_song()
if input.page() == "New Artist":
return nav_artist()
return None
app = App(app_ui, server)