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

如何检测renderUI生成的Shiny Dashboard折叠框的折叠状态?

解决Shiny动态生成可折叠Box的状态检测问题

当通过renderUI/uiOutput动态生成box时,页面初始化阶段这些box还未渲染到DOM中,提前在ui里调用collapseInput绑定的事件监听器找不到对应元素,自然无法触发状态通知。以下是两种可行的解决方法:

方案1:将事件绑定脚本与动态Box一同生成

把collapseInput的调用放到renderUI的输出内容里,确保box渲染完成后再执行事件绑定代码,让监听器能找到目标元素。

修改后的完整代码:

library(shiny)
library(shinydashboard)
library(shinyjs)

jscode <- "
shinyjs.collapse = function(boxid) {
$('#' + boxid).closest('.box').find('[data-widget=collapse]').click();
}"
collapseInput <- function(inputId, boxId) {
  tags$script(
    sprintf(
      "$('#%s').closest('.box').on('hidden.bs.collapse', function () {Shiny.onInputChange('%s', true);})",
      boxId, inputId
    ),
    sprintf(
      "$('#%s').closest('.box').on('shown.bs.collapse', function () {Shiny.onInputChange('%s', false);})",
      boxId, inputId
    )
  )
}

ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(),
  dashboardBody(
    useShinyjs(),
    extendShinyjs(text = jscode, functions = c("collapse")),
    actionButton("bt1", "Collapse box1"),
    actionButton("bt2", "Collapse box2"),
    br(), br(),
    uiOutput("boxes"), 
    verbatimTextOutput(outputId = "res")
  )
)

server <- function(input, output) {
  output$boxes <- renderUI({
    tagList(
      box(id = "box1", collapsible = TRUE, p("Box 1")),
      box(id = "box2", collapsible = TRUE, p("Box 2")),
      # 把事件绑定脚本和box一起输出
      collapseInput(inputId = "iscollapsebox1", boxId = "box1"),
      collapseInput(inputId = "iscollapsebox2", boxId = "box2")
    )
  })
  
  observeEvent(input$bt1, {
    js$collapse("box1")
  })
  observeEvent(input$bt2, {
    js$collapse("box2")
  })
  
  output$res <- renderPrint({
    list(box1_collapsed = input$iscollapsebox1, box2_collapsed = input$iscollapsebox2)
  })
}

shinyApp(ui, server) 

方案2:使用事件委托(适配大量动态Box场景)

如果需要生成数量不确定的box,事件委托更高效——通过监听父容器的事件,自动匹配后续动态生成的子元素,无需为每个box单独编写绑定代码。

修改后的完整代码:

library(shiny)
library(shinydashboard)
library(shinyjs)

jscode <- "
shinyjs.collapse = function(boxid) {
$('#' + boxid).closest('.box').find('[data-widget=collapse]').click();
}
// 事件委托:监听页面中所有box的折叠/展开事件
$(document).on('hidden.bs.collapse', '.box .collapse', function() {
  var boxId = $(this).closest('.box').attr('id');
  Shiny.onInputChange('iscollapse_' + boxId, true);
});
$(document).on('shown.bs.collapse', '.box .collapse', function() {
  var boxId = $(this).closest('.box').attr('id');
  Shiny.onInputChange('iscollapse_' + boxId, false);
});
"

ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(),
  dashboardBody(
    useShinyjs(),
    extendShinyjs(text = jscode, functions = c("collapse")),
    actionButton("bt1", "Collapse box1"),
    actionButton("bt2", "Collapse box2"),
    br(), br(),
    uiOutput("boxes"), 
    verbatimTextOutput(outputId = "res")
  )
)

server <- function(input, output) {
  output$boxes <- renderUI({
    tagList(
      box(id = "box1", collapsible = TRUE, p("Box 1")),
      box(id = "box2", collapsible = TRUE, p("Box 2"))
    )
  })
  
  observeEvent(input$bt1, {
    js$collapse("box1")
  })
  observeEvent(input$bt2, {
    js$collapse("box2")
  })
  
  output$res <- renderPrint({
    list(box1_collapsed = input$iscollapse_box1, box2_collapsed = input$iscollapse_box2)
  })
}

shinyApp(ui, server) 

方案1适合少量固定数量的动态box,方案2无需为每个box单独写绑定脚本,适配任意数量的动态生成box。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 03:33:22