点击DT行时更新data.frame逻辑列值,如何用reactive替代reactiveValues实现
问题根源
代码核心问题是tableData响应式表达式每次触发更新时,都会从头构建原始数据集,点击行时对ans的修改会被下一次响应式计算的初始值完全覆盖,因此看起来修改未生效。同时在响应式表达式内部调用DT::replaceData会和renderDataTable的自动渲染逻辑冲突,属于冗余操作。
修正代码
以下代码使用reactiveVal(属于响应式体系组件,满足你不用reactiveValues/observeEvent组合的需求)存储勾选状态,实现点击行切换逻辑列取值的效果:
library(shiny) library(DT) ui <- shiny::fluidPage( DT::dataTableOutput("myTable") ) server <- function(input, output, session) { # 存储当前勾选的行索引,初始值对应原始数据前3行TRUE的状态 selected_rows <- reactiveVal(1:3) # 响应行点击更新勾选状态 observeEvent(input$myTable_rows_selected, { curr_click <- input$myTable_rows_selected[1] current_selected <- selected_rows() selected_rows( if(curr_click %in% current_selected) { setdiff(current_selected, curr_click) } else { c(current_selected, curr_click) } ) # 清除选中状态,支持连续点击同一行切换 DT::selectRows(DT::dataTableProxy('myTable'), NULL) }, ignoreNULL = TRUE) tableData <- reactive({ ans <- data.frame( Name = LETTERS[1:6], stringsAsFactors = FALSE ) # 根据勾选状态渲染图标 ans$YesNo <- ifelse( 1:nrow(ans) %in% selected_rows(), as.character(shiny::icon("ok", lib = "glyphicon")), NA ) ans }) output$myTable <- DT::renderDataTable( tableData(), selection = list(mode = "single", target = "row"), style = "bootstrap", rownames = FALSE, colnames = c("Letter", "Yes?"), options = list(lengthMenu = c(5, 10, 25, 50, 100), pageLength = 5), escape = FALSE ) } shinyApp(ui, server)
关键修改说明
- 将状态存储和视图渲染完全分离,用
reactiveVal持久化存储勾选的行索引,不会随响应式计算重置 - 移除冗余的
replaceData调用,依赖响应式机制自动更新表格内容 - 点击行后主动清除选中状态,支持连续点击同一行切换取值
内容的提问来源于stack exchange,提问作者Karsten W.
相关产品推荐
相关产品推荐

