使用 DT 的 Shiny 应用程序中反应性 editable table 中的持久数据

Persistent data in reactive editable table in Shiny app using DT

我有一个应用程序,它从 SQL-db 获取数据,然后允许用户编辑它,这应该保存到数据库中。在 repex 中我使用了一个 CSV 文件,但逻辑应该仍然是可比较的。

但是,一旦我编辑了列值,数据就会保存在会话中,但是如果我切换输入或关闭应用程序并重新打开,它会恢复到原来的状态。编辑未反映在摘要中 table。我做错了什么?

# Load libraries
library(DT)
library(gt)
library(shiny)
library(shinydashboard)
library(dplyr)

# Load data (run once for replication; in real use case will be a DB-connection)
#gtcars_tbl <- gtcars
#write.csv(gtcars_tbl, "gtcars_tbl.csv", row.names = FALSE)

# Simple UI
sidebar <- dashboardSidebar(
  sidebarMenu(
    menuItem("Summary table", tabName = "summary", icon = icon("project-diagram")),
    menuItem("Edit table", tabName = "edit", icon = icon("project-diagram")),
    uiOutput("country")
  )
)

body <- dashboardBody(
  tabItems(
    tabItem(tabName = "summary",
            h2("Summary of GT Cars"),
            gt_output(outputId = "gt_filt_tbl")
    ),
    
    tabItem(tabName = "edit",
            h2("Editer GT Cars"),
            DTOutput("edit")
    )
  )
)

ui <- dashboardPage(
  dashboardHeader(title = "GT Cars"),
  sidebar,
  body)


# Define server functions

server <- function(input, output, session) {

  # Load data
  gtcars_tbl <- read.csv("gtcars_tbl.csv")  
  
  countries <- sort(as.vector(unique(gtcars_tbl$ctry_origin)))
  
  # Create dropdown output
  output$country <- renderUI({
    selectInput("country", "Country", countries)
  })

  # Create reactive table
  
  gt_tbl_react <- reactiveVal(NULL)
  gt_tbl_react(gtcars_tbl)
  
  # Create filtered table
  gt_filt_tbl <- reactive({
    req(input$country)
    gt_tbl_react() %>%
      filter(ctry_origin == input$country)
    
  })

  # Render summary table
  output$gt_filt_tbl <- render_gt({
    gt_filt_tbl() %>%
      group_by(ctry_origin, mfr) %>%
      summarise(
        N = n(),
        Avg_HP = mean(hp),
        MSRP = mean(msrp)
      ) %>%
      gt(
        rowname_col = "ctry_origin",
        groupname_col = "mfr")
      
  }) 

  # Render editable table
  
  output$edit <- renderDT(
    gt_tbl_react() %>%
      filter(ctry_origin == input$country),
    selection = 'none', editable = TRUE, 
    rownames = TRUE,
    extensions = 'Buttons'
  )
  
  observeEvent(input$edit_cell_edit, {
    gtcars_tbl[input$edit_cell_edit$row,input$edit_cell_edit$col] <<- input$edit_cell_edit$value
    write.csv(gtcars_tbl, "gtcars_tbl.csv", row.names = FALSE)
  })
  
}

# Run app
shinyApp(ui, server)

问题是 input$edit_cell_edit$rowinput$edit_cell_edit$col 是根据显示的子集数据框提供的,而您正在更改完整数据框的值。

observeEvent-

中使用这个
observeEvent(input$edit_cell_edit, {
    inds <- which(gtcars_tbl$ctry_origin == input$country)
    gtcars_tbl[inds[input$edit_cell_edit$row],input$edit_cell_edit$col] <- input$edit_cell_edit$value
    write.csv(gtcars_tbl, "gtcars_tbl.csv", row.names = FALSE)
  })