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

如何在R Shiny中将单个对象的操作按钮整合为单个selectInput()

实现统一选择框删除rhandsontable表格的解决方案

原Shiny应用支持添加带独立删除按钮的rhandsontable表格,现需将分散的删除按钮替换为单个selectInput(),让用户选择要删除的表格。以下是修改后的完整代码及关键改动说明:

修改后的完整代码

library(shiny)
library(rhandsontable)

data1 <- data.frame(row.names = c("A","B","C","Sum"),"Tbl 1"=c(1,1,0,2),check.names=FALSE)

ui <- fluidPage(
  br(),
  actionButton("addTbl","Add table"),
  br(), br(),
  # 添加选择框和统一删除按钮
  selectInput("tableToDelete", "选择要删除的表格", choices = "Tbl 1"),
  actionButton("deleteSelected", "删除选中表格", class = "btn btn-danger"),
  br(), br(),
  tags$div(id="placeholder", tags$div(id = "div_01", rHandsontableOutput("hottable1")))
)

server <- function(input, output, session) {
  uiTbl <- reactiveValues(div_01_tbl = data1) 
  # 新增:维护表格元数据(divID、显示名称、数据键名)
  tableMeta <- reactiveValues(
    div_01 = list(displayName = "Tbl 1", dataKey = "div_01_tbl")
  )                
  
  # 处理初始表格的输入更新
  observeEvent(input$hottable1, {
    uiTbl$div_01_tbl <- hot_to_r(input$hottable1)
  })
  
  output$hottable1 <- renderRHandsontable({
    rhandsontable(uiTbl$div_01_tbl, useTypes = TRUE)
  })
  
  # 添加表格逻辑
  observeEvent(input$addTbl, {
    tblNum <- input$addTbl + 1
    divID <- paste0("div_", if(tblNum < 10){"0"}, tblNum)
    dtID <- paste0(divID, "_DT")
    dataKey <- paste0(divID, "_tbl")
    displayName <- paste0("Tbl ", tblNum)
    
    # 初始化表格数据
    uiTbl[[dataKey]] <- data1 
    # 记录表格元数据
    tableMeta[[divID]] <- list(displayName = displayName, dataKey = dataKey)
    
    # 插入表格UI
    insertUI(selector = "#placeholder",
             ui = tags$div(id = divID,
                           rHandsontableOutput(dtID)
             )
    )
    
    # 渲染新表格
    output[[dtID]] <- renderRHandsontable({
      req(uiTbl[[dataKey]])
      rhandsontable(uiTbl[[dataKey]], useTypes = TRUE)
    })
    
    # 处理新表格的输入更新
    observeEvent(input[[dtID]], {
      uiTbl[[dataKey]] <- hot_to_r(input[[dtID]])
    }, ignoreInit = TRUE)
    
    # 更新选择框选项
    updateSelectInput(session, "tableToDelete", 
                      choices = unlist(lapply(reactiveValuesToList(tableMeta), function(x) x$displayName)))
  })
  
  # 统一删除逻辑
  observeEvent(input$deleteSelected, {
    req(input$tableToDelete)
    # 找到选中表格对应的divID
    metaList <- reactiveValuesToList(tableMeta)
    targetDivID <- names(metaList)[sapply(metaList, function(x) x$displayName == input$tableToDelete)]
    
    if(length(targetDivID) > 0 && targetDivID != "div_01"){ # 禁止删除初始表格(可选,根据需求调整)
      # 删除UI
      removeUI(selector = paste0("#", targetDivID))
      # 清理数据
      uiTbl[[metaList[[targetDivID]]$dataKey]] <- NULL
      tableMeta[[targetDivID]] <- NULL
      # 更新选择框选项
      updateSelectInput(session, "tableToDelete", 
                        choices = unlist(lapply(reactiveValuesToList(tableMeta), function(x) x$displayName)))
    }
  }, ignoreInit = TRUE)
  
  # 列名更新逻辑(保持原功能)
  observe({
    tables_list <- reactiveValuesToList(uiTbl)
    tables_list <- tables_list[order(names(tables_list))]
    table_lengths <- lengths(tables_list)
    cumsum_table_lengths <- cumsum(table_lengths)[table_lengths != 0L]
    for(i in seq_along(cumsum_table_lengths)){
      names(uiTbl[[names(cumsum_table_lengths[i])]]) <- paste("Col", cumsum_table_lengths[i])
    }
  })
  
}

shinyApp(ui, server)

关键改动说明

  • UI层优化:新增selectInput用于选择待删除表格,以及一个统一的删除按钮,移除了原代码中每个表格下方的独立删除按钮。
  • 表格元数据管理:用tableMeta存储每个表格的divID、显示名称和数据存储键名,实现对所有表格的统一追踪。
  • 动态更新选择框:每次添加或删除表格后,自动更新selectInput的可选选项,确保列表与当前存在的表格同步。
  • 集中删除逻辑:通过单个observeEvent处理删除按钮点击,根据选中的表格名称匹配对应的divID,执行UI移除和数据清理操作。
  • 可选限制:代码中默认禁止删除初始表格("Tbl 1"),如果需要允许删除初始表格,只需移除targetDivID != "div_01"的判断条件。

内容的提问来源于stack exchange,提问作者Village.Idyot

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 20:05:13