Shiny如何捕获交互式表格手动输入修改并导出至数据库
问题根因
你的判断完全准确:开启可编辑属性的DT表格,用户在前端手动修改单元格的内容不会自动同步回后端存储的fruit_df$df响应式值。DT组件会把所有单元格编辑操作封装为input$<表格输出ID>_cell_edit的输入事件,你没有监听该事件同步更新数据源,自然无法捕获手动编辑的内容。
实现逻辑
要同时捕获两类修改,只需要补全数据源同步链路:
- 新增DT单元格编辑事件的监听,每次用户手动修改表格,就将修改后的值校验类型后同步更新到
fruit_df$df - 所有数据库写入操作统一取已经同步了全量修改的
fruit_df$df作为数据源,不管修改来自下拉选择框还是手动编辑,都能完整写入 - 注意DT返回的单元格列索引从0开始计数,和R语言数据框从1开始的索引差1位,需要做偏移;同时要用
DT::coerceValue做类型适配,避免修改后列类型变化导致写库报错。
修正后完整代码
library(shiny) library(shinydashboard) library(DT) library(DBI) ui <- dashboardPage( dashboardHeader(title = "test"), dashboardSidebar(), dashboardBody( shiny::selectizeInput(inputId = "apple_lbs_filter", label = "Apple lbs", choices = c(1:10)), shiny::selectizeInput(inputId = "cherry_lbs_filter", label = "Cherry lbs", choices = c(1:10)), shiny::selectizeInput(inputId = "pineapple_lbs_filter", label = "Pineapple lbs", choices = c(1:10)), shiny::selectizeInput(inputId = "pear_lbs_filter", label = "Pear lbs", choices = c(1:10)), shiny::actionButton(inputId = "update_lbs",label = "Update lbs"), DT::DTOutput("fruit") ) ) server <- function(input, output, session) { fruit_df <- shiny::reactiveValues() fruit_df$df <- data.frame( fruit_name = c("apple","cherry","pineapple","pear"), fruit_lbs = c(2,5,6,3) ) output$fruit <- DT::renderDT({ DT::datatable( fruit_df$df, editable = TRUE, extensions = 'Buttons', options = list(dom = 'frtBip', buttons = c('csv')) ) }) # 监听表格手动编辑事件,同步更新到后端数据源 observeEvent(input$fruit_cell_edit, { edit <- input$fruit_cell_edit # 索引偏移+类型适配,保证数据格式一致 fruit_df$df[edit$row, edit$col + 1] <- DT::coerceValue(edit$value, fruit_df$df[edit$row, edit$col + 1]) }) observeEvent(input$update_lbs, { # 同步下拉选择框的数值到数据源 fruit_df$df$fruit_lbs <- c( input$apple_lbs_filter, input$cherry_lbs_filter, input$pineapple_lbs_filter, input$pear_lbs_filter ) # 直接取同步完全量修改的df写库即可 # conn <- DBI::dbConnect(drv, user, password) # DBI::dbWriteTable(conn = conn, SQL(schema.tbl), fruit_df$df, overwrite = TRUE) # DBI::dbDisconnect(conn) }) } shinyApp(ui, server)
扩展说明
如果不需要点击按钮手动触发写库,需要做到修改即同步,只需要把写库逻辑封装成独立函数,分别在下拉选更新、单元格编辑两个监听事件里调用即可,不需要额外维护多份数据源。
内容的提问来源于stack exchange,提问作者ds_worthington
相关产品推荐
相关产品推荐

