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

基于bs_accordion_sidebar的动态Shiny App功能问题求助

解决Shiny bs_accordion_sidebar的两个问题:面板折叠失效与删除滑块后图表不更新

我来帮你搞定这两个问题,咱们一步步拆解和修复:

问题1:面板标题点击无折叠/变色反应

你之前的代码里,每次添加滑块时都创建了一个新的div包裹整个bs_accordion_sidebar,这会导致新添加的面板没有和初始的accordion绑定交互。正确的做法是直接往已有的accordion容器里追加面板,而不是插入新的accordion实例。

问题2:删除滑块后条形图不更新

删除按钮移除了UI元素,但Shiny的input对象里仍然保留着已删除滑块的值,你的AllInputs()依赖所有input的名称,所以不会自动更新。我们需要用响应式值来跟踪当前存在的滑块ID,这样删除后能准确过滤掉已移除的滑块值。


修改后的完整代码

library(shiny)
library(bsplus)

ui <- shinyUI(fluidPage(
  titlePanel("bs_append and insertUI"),
  sidebarPanel(
    fluidRow(
      actionButton("add", "+"),
      # 初始化空的bs_accordion_sidebar
      bs_accordion_sidebar(
        id = "accordion",
        spec_side = c(width = 4, offset = 0),
        spec_main = c(width = 8, offset = 0)
      ),
      actionButton("delete", "-")
    )
  ),
  mainPanel(
    plotOutput('show_inputs')
  ),
  use_bs_accordion_sidebar()
))

server <- shinyServer(function(input, output, session) {
  # 用响应式值跟踪当前存在的滑块ID
  current_sliders <- reactiveValues(ids = c())
  
  # 收集当前有效的滑块值
  AllInputs <- reactive({
    req(length(current_sliders$ids) > 0)
    # 只收集当前存在的滑块的值
    myvalues <- sapply(paste0("slider_", current_sliders$ids), function(x) input[[x]])
    names(myvalues) <- paste0("slider_", current_sliders$ids)
    return(myvalues)
  })
  
  # 渲染条形图
  output$show_inputs <- renderPlot({
    if(length(AllInputs()) == 0){
      plot.new()
      text(0.5, 0.5, "No sliders added yet")
    } else {
      barplot(AllInputs(), las = 2)
    }
  })
  
  # 添加滑块面板
  observeEvent(input$add, {
    new_id <- length(current_sliders$ids) + 1
    current_sliders$ids <- c(current_sliders$ids, new_id)
    
    # 直接往已有的accordion里追加面板
    bs_append(
      id = "accordion",
      title_side = paste0("Panel ", new_id),
      content_side = NULL,
      content_main = sliderInput(
        inputId = paste0("slider_", new_id),
        label = paste0("Slider ", new_id),
        value = 0,
        min = 0,
        max = 10
      )
    )
  })
  
  # 删除最后一个滑块面板
  observeEvent(input$delete, {
    if(length(current_sliders$ids) > 0){
      last_id <- tail(current_sliders$ids, 1)
      # 移除accordion中的面板
      bs_remove(id = "accordion", index = length(current_sliders$ids))
      # 更新当前滑块ID列表
      current_sliders$ids <- head(current_sliders$ids, -1)
    }
  })
})

shinyApp(ui, server)

关键修改点说明

  1. 面板折叠修复

    • 移除了UI里的placeholder和mytag变量,直接在UI中初始化空的bs_accordion_sidebar
    • 使用bs_append()直接往id为"accordion"的容器里追加面板,确保每个新面板都和原accordion绑定了交互事件,点击标题时会正常折叠/变色
  2. 删除后图表更新修复

    • 新增current_sliders响应式值,专门跟踪当前存在的滑块ID
    • AllInputs()只根据current_sliders$ids收集值,删除滑块后ID列表更新,AllInputs()会自动重新计算,触发图表更新
    • 使用bs_remove()来删除accordion中的面板,而不是直接用removeUI(),这样能正确清理accordion的内部状态
  3. 额外优化

    • 当没有滑块时,图表会显示提示文本,避免空图表报错
    • 滑块和面板的命名更清晰(比如"Panel 1"、"Slider 1")
    • 移除了全局变量cpt,改用响应式值管理,避免全局变量带来的副作用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 11:57:51