能否通过Shiny书签功能恢复手风琴面板?
解决Shiny手风琴面板的书签恢复问题
你的问题出在:默认的Shiny书签只会保存输入控件的状态,但动态生成的手风琴面板的结构(比如已添加的所有面板列表)并没有被纳入书签保存范围。刷新后,虽然输入值还在,但面板本身需要手动重建才能显示这些值。
要实现书签直接恢复所有手风琴面板,需要手动处理书签的保存与恢复逻辑,把面板列表存入书签状态,再在恢复时自动重建面板。
修改后的完整代码
library(shiny) library(bslib) ui <- function(request) { fluidPage( theme = bs_theme(version = 5), titlePanel("Dynamic Tabs with Bookmarking"), sidebarLayout( sidebarPanel( textInput("tab_name", "Tab Name"), actionButton("add_tab", "Add Tab") ), mainPanel( accordion( id = "tabs" ) ) ) ) } server <- function(input, output, session) { # Reactive value to store tab names tabs <- reactiveVal(character(0)) # 添加新面板 observeEvent(input$add_tab, { new_tab_name <- isolate(input$tab_name) if (!is.null(new_tab_name) && new_tab_name != "") { accordion_panel_insert( id = "tabs", panel = accordion_panel( title = new_tab_name, value = new_tab_name, textInput(paste0(new_tab_name, "_my"), label="Enter:") ) ) tabs(c(tabs(), new_tab_name)) # 添加后触发书签更新 session$doBookmark() } }) # 保存面板列表到书签状态 onBookmark(function(state) { state$set("tabs_list", tabs()) }) # 从书签恢复时重建所有面板 onRestore(function(state) { saved_tabs <- state$get("tabs_list") if (!is.null(saved_tabs) && length(saved_tabs) > 0) { # 先清空现有面板(避免重复) accordion_panel_remove(id = "tabs", target = tabs()) # 逐个插入保存的面板 lapply(saved_tabs, function(tab) { accordion_panel_insert( id = "tabs", panel = accordion_panel( title = tab, value = tab, textInput(paste0(tab, "_my"), label="Enter:") ) ) }) # 更新reactive值 tabs(saved_tabs) } }) # 更新URL onBookmarked(updateQueryString) } shinyApp(ui, server, enableBookmarking = "url")
关键修改说明
- 保存面板列表:通过
onBookmark钩子,把当前所有面板的名称存入书签状态的tabs_list字段。 - 恢复时重建面板:在
onRestore钩子中读取保存的tabs_list,循环插入每个手风琴面板。此时输入控件的值会自动被Shiny的书签机制填充,无需额外处理。 - 优化书签触发:把原代码中频繁触发书签的
observe({session$doBookmark()})改成只在添加面板时触发,避免不必要的URL更新。
这样修改后,刷新书签链接时,所有已添加的手风琴面板会自动重建,且对应的输入内容也会一并恢复,不需要手动操作。
内容的提问来源于stack exchange,提问作者umair durrani
相关产品推荐
相关产品推荐

