You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否通过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")

关键修改说明

  1. 保存面板列表:通过onBookmark钩子,把当前所有面板的名称存入书签状态的tabs_list字段。
  2. 恢复时重建面板:在onRestore钩子中读取保存的tabs_list,循环插入每个手风琴面板。此时输入控件的值会自动被Shiny的书签机制填充,无需额外处理。
  3. 优化书签触发:把原代码中频繁触发书签的observe({session$doBookmark()})改成只在添加面板时触发,避免不必要的URL更新。

这样修改后,刷新书签链接时,所有已添加的手风琴面板会自动重建,且对应的输入内容也会一并恢复,不需要手动操作。

内容的提问来源于stack exchange,提问作者umair durrani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 16:25:23