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

Shiny中修改用户筛选后的表格并同步更新主表的实现问题

问题描述

我参考了DT仓库的相关代码实现Shiny表格的用户编辑功能,当前需求如下:

  • 基于大型数据库实现编辑前先按material字段筛选,再进行表格编辑,重点支持stockobj列的修改
  • 筛选后的编辑表和全量主表需同步展示所有历史修改

预期应用效果如下图:
App效果预览

现有代码
library(DT)
library(tidyverse)

df<- tibble(material=c(12345,12345,12345,12345,12345, 67891,67891,67891,67891,67891),
            centro=c("H01", "H02", "H03", "H04","H05","H01", "H02", "H03",  "H04","H05" ),
            rotaSem= c(0.66,0.55,0.43,0.45, 0.33, 0.34,0.78, 0.31,0.89,0.87),
            stockobj=c(1,2,1,1,3,1,1,1,2,1))


shinyApp(
  ui = fluidPage(
    titlePanel("My app"),
    selectInput("mate", "Select material", choices = unique(df$material)),
    h3("Edit table"),
    DTOutput('x1'),
    h3("Main table"),
    DTOutput("x2")
  ),
  server = function(input, output, session) {
    x = df

  
    categ<-reactive({
      x %>% filter(material==input$mate)
    })
    
    output$x1 <- renderDT(categ(), selection = 'none', rownames = F, editable = T)
    output$x2 <- renderDT({
      x
    })
    
    
    proxy = dataTableProxy('x1')
    
    observeEvent(input$x1_cell_edit, {
      
      info = input$x1_cell_edit
      str(info)
      i = info$row
      j = info$col + 1  # column index offset by 1
      v = info$value
      x[i, j] <<- DT::coerceValue(v, x[i, j])
      replaceData(proxy, x, resetPaging = FALSE, rownames = FALSE)
    })
  }
)
问题核心

编辑筛选后的表格需要修改reactive返回的对象,直接修改无法实现,求可行思路。

解决方案

核心修改思路如下:

  1. 用reactiveVal存储全量主表,保证数据变更可以触发所有依赖组件的自动更新
  2. 给原始数据增加唯一行标识,避免筛选后行号错位导致修改错误
  3. 编辑时通过唯一行标识定位全量表中的对应行,修改后更新reactiveVal存储的主表,两个表格会自动同步变更

修改后可直接运行的完整代码:

library(DT)
library(tidyverse)

df<- tibble(material=c(12345,12345,12345,12345,12345, 67891,67891,67891,67891,67891),
            centro=c("H01", "H02", "H03", "H04","H05","H01", "H02", "H03",  "H04","H05" ),
            rotaSem= c(0.66,0.55,0.43,0.45, 0.33, 0.34,0.78, 0.31,0.89,0.87),
            stockobj=c(1,2,1,1,3,1,1,1,2,1)) %>% 
  mutate(row_id = row_number()) # 新增唯一行标识


shinyApp(
  ui = fluidPage(
    titlePanel("My app"),
    selectInput("mate", "Select material", choices = unique(df$material)),
    h3("Edit table"),
    DTOutput('x1'),
    h3("Main table"),
    DTOutput("x2")
  ),
  server = function(input, output, session) {
    # 用reactiveVal存储全量主表,支持响应式更新
    raw_df = reactiveVal(df)
    
    # 筛选后的编辑用子表
    categ<-reactive({
      raw_df() %>% filter(material==input$mate) %>% select(-row_id) # 隐藏行标识列
    })
    
    output$x1 <- renderDT(categ(), selection = 'none', rownames = F, editable = T)
    # 主表直接渲染全量数据
    output$x2 <- renderDT({
      raw_df() %>% select(-row_id)
    }, rownames = F)
    
    
    proxy = dataTableProxy('x1')
    
    observeEvent(input$x1_cell_edit, {
      info = input$x1_cell_edit
      i = info$row
      j = info$col + 1  # 列索引偏移
      v = info$value
      
      # 拿到当前筛选子表对应的全量表行id
      target_row_id = raw_df() %>% filter(material==input$mate) %>% pull(row_id) %>% .[i]
      # 更新全量表
      new_df = raw_df()
      new_df[new_df$row_id == target_row_id, j] <- DT::coerceValue(v, new_df[new_df$row_id == target_row_id, j])
      raw_df(new_df)
      
      # 替换编辑表数据
      replaceData(proxy, categ(), resetPaging = FALSE, rownames = FALSE)
    })
  }
)

内容的提问来源于stack exchange,提问作者Manuel Vásquez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 21:27:03