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

表格单元格内SelectInput在依赖输入变更或重触actionButton后无法读取input$ID值

问题根源
  • 核心问题1:将DT::renderDataTable嵌套在observeEvent(input$go)中属于Shiny开发反模式,每次点击Go按钮都会重新生成render绑定,旧DOM元素和Shiny输入绑定未被正确清理,重复ID的输入组件出现绑定冲突,导致input$student_row*无法被正确识别
  • 核心问题2:未在UI中初始化shinyjs,导致显隐逻辑失效
  • 核心问题3:缺失必要的依赖包声明,直接运行会报错
  • 核心问题4:班级切换逻辑和Go按钮触发逻辑未对齐,出现状态不一致
修复后的完整可运行代码
master_table <- data.frame("class_col" = c("A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "C", "C", "C", "C", "C"), 
                           "all_student"=c("CA1", "CA2", "CA3", "CA4", "CA5", "CB1", "CB2", "CB3", "CB4", "CB5", "CC1", "CC2", "CC3", "CC4", "CC5"))

# 加载所有依赖包
library(shiny)
library(shinyjs)
library(shinyWidgets)
library(DT)
library(data.table)

ui <- fluidPage(
  shinyjs::useShinyjs(), # 初始化shinyjs
  fluidRow(
    selectInput("class_input", label = "Class", choices= sort(c("Select Class"='', unique(master_table$class_col))), selected=NULL),
    shinyjs::hidden(tags$div(id="alert", tags$h5("* Please Select Class ", style = "color:red"))),
    actionBttn(inputId = 'go', label='Go!'),
    shinyjs::hidden(tags$div(id='hidden_table', DT::dataTableOutput('student_select_table'))),
    textOutput("text_output_for_selected_Student_at_Row1")
  )
)

server <- function(input, output, session) {
  # 存储点击Go后确认的选中班级
  selected_class <- reactiveVal("")
  
  # 监听Go按钮点击
  observeEvent(input$go, {
    if(nchar(input$class_input)<1){
      shinyjs::showElement("alert")
      shinyjs::hideElement("hidden_table")
      selected_class("")
    } else {
      shinyjs::hideElement("alert")
      shinyjs::showElement("hidden_table")
      selected_class(input$class_input)
    }
  })
  
  # 根据选中的班级生成带下拉框的表格数据
  student_reactive <- reactive({
    req(selected_class())
    student_table = data.table('student_input_col' = 1:5)
    cur_choices = sort(c("Select Student"='', master_table$all_student[master_table$class_col == selected_class()]))
    for (i in 1:nrow(student_table)){
      student_table$student_input_col[i] <- as.character(selectInput(inputId = paste0("student_row", i),
                                                                     label=NULL,
                                                                     choices = cur_choices))
    }
    return(student_table)
  })
  
  # 独立渲染DT表格,不嵌套在observe中
  output$student_select_table <- DT::renderDataTable({
    req(student_reactive())
    datatable(student_reactive(),
              class= "cell-border",
              rownames = FALSE, width = "80%",escape = FALSE,
              selection = "single",
              options = list(dom='t', paging=FALSE, ordering=FALSE, info=FALSE,
                             rowCallback = JS("function(r,d) {$(r).attr('height', '40px')}"),
                             preDrawCallback = JS('function() { Shiny.unbindAll(this.api().table().node()); }'),
                             drawCallback = JS('function() { Shiny.bindAll(this.api().table().node()); } '))
    )
  })
  
  output$text_output_for_selected_Student_at_Row1 <- renderText(paste0("Text for Student at Row1 = ", input$student_row1))
}

runApp(shinyApp(ui = ui, server = server))
修复效果

现在切换班级后点击Go按钮重新生成表格,或是多次点击Go按钮,下拉框的选中值都可以被正常读取,文本输出会实时同步更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 10:48:01