在Shiny中用reactable实现行内selectInput联动修改quantity列
解决Shiny+reactable动态表格联动问题:选中"Sell"时自动清零对应行quantity
问题根源
之前的实现没有持久化存储每行的修改状态,导致新行触发更新时,旧行的修改被原始数据覆盖,无法保留已设置的0值。
解决方案
使用reactiveValues持久化表格数据,监听每个transaction选项的变化,仅更新当前行的quantity值,同时保留其他行的修改状态。
完整代码示例
library(shiny) library(reactable) library(tibble) ui <- fluidPage( reactableOutput("dynamic_table") ) server <- function(input, output, session) { # 初始化带状态的表格数据 rv <- reactiveValues( table_data = tibble( id = 1:3, transaction = c("Buy", "Sell", "Buy"), quantity = c(10, 20, 30) ) ) # 监听所有transaction选择框的变化,更新对应行quantity observeEvent( eventExpr = lapply(1:nrow(rv$table_data), function(i) input[[paste0("trans_", i)]]), handlerExpr = { req(rv$table_data) updated_data <- rv$table_data # 遍历每一行,根据transaction状态更新quantity for (row_idx in 1:nrow(updated_data)) { current_trans <- input[[paste0("trans_", row_idx)]] if (!is.null(current_trans) && current_trans == "Sell") { updated_data$quantity[row_idx] <- 0 } # 若需选回Buy时恢复原始值,可在此添加逻辑,比如从原始数据中读取 } rv$table_data <- updated_data }, ignoreInit = TRUE ) output$dynamic_table <- renderReactable({ reactable( rv$table_data, columns = list( transaction = colDef( cell = function(value, index) { selectInput( inputId = paste0("trans_", index), label = NULL, choices = c("Buy", "Sell"), selected = value ) } ), quantity = colDef( cell = function(value, index) { numericInput( inputId = paste0("qty_", index), label = NULL, value = rv$table_data$quantity[index], min = 0 ) } ) ), editable = FALSE ) }) } shinyApp(ui, server)
关键说明
- 状态持久化:用
reactiveValues存储表格数据,所有修改都会被保留,不会被初始数据覆盖 - 唯一输入ID:每个
selectInput和numericInput的ID拼接行号(如trans_1、qty_1),避免组件冲突 - 精准更新:遍历所有行,仅对选中"Sell"的行设置
quantity=0,其他行保持现有状态 - 动态行支持:若需添加动态行,只需在
rv$table_data中新增行即可,监听逻辑会自动适配行数变化
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

