在R Shiny中添加和删除DT数据表的行

13
我正在尝试为我的Shiny应用程序添加一个“保存输入”功能,其中保存的输入将保存在DT数据表中。如果用户单击“添加”按钮,则会将输入附加到数据表中。然后,用户可以通过选择一行并单击“删除”按钮来从此数据表中删除一行。我还需要将此表的值保存为全局变量,以便它在所有会话中保持持久性。
以下是示例代码。当我关闭会话时,表格(`this_table`)被正确更新,但是在应用程序期间这些更改不会实时显示。我尝试将这些输入按钮都放入`eventReactive`函数中,但是当其中一个按钮被选择多次时,这种方法不起作用。
有什么想法吗?
全局表:
`this_table = data.frame(bins = c(30, 50), cb = c(T, F))`
Shiny应用程序代码:
ui <- fluidPage(

   sidebarLayout(
      sidebarPanel(
         sliderInput("bins",
                     "Number of bins:",
                     min = 1,
                     max = 50,
                     value = 30),
         checkboxInput("cb", "T/F"),
         actionButton("add_btn", "Add"),
         actionButton("delete_btn", "Delete")
      ),

      mainPanel(
         DTOutput("shiny_table")
      )
   )
)

server <- function(input, output) {


  observeEvent(input$add_btn, {
    t = rbind(data.frame(bins = input$bins,
                         cb = input$cb), this_table)
    this_table <<- t
  })

  observeEvent(input$delete_btn, {
    t = this_table
    print(nrow(t))
    if (!is.null(input$shiny_table_rows_selected)) {
      t <- t[-as.numeric(input$shiny_table_rows_selected),]
    }
    this_table <<- t
  })

  output$shiny_table <- renderDT({
   datatable(this_table, selection = 'single', options = list(dom = 't'))
  })
}

shinyApp(ui = ui, server = server)

你应该看一下 rhandsontable 包:https://jrowen.github.io/rhandsontable/ - Vishesh Shrivastav
@VisheshShrivastav和OP:最近,handsontable(JS库,而不是R包)从FOSS更改为专有许可证,因此在尝试将该软件包纳入您的产品时请考虑这一点。为了未来的保障,我正在用DTs替换我的项目中的handsontable,尽管我更喜欢前者。 - Mali Remorker
1个回答

18
您可以使用reactiveVal添加可观察且可变的服务器端变量。这些变量的语法是将它们初始化为:
rV <- reactiveValue("init_value")

并更新它们

rV("new_value")

这些变量可以在响应式上下文中访问(基本上像input一样),使用以下方式:

rV()

这种语法对于R来说非常不寻常,可能需要一些时间才能习惯,但它绝对是解决此类问题的推荐方法。您还可以查看reactiveValues,它具有与R类list更接近的语义,提供类似的功能。

以下是如何将此技术应用于您的问题:

library(shiny)
library(DT)

this_table = data.frame(bins = c(30, 50), cb = c(T, F))

ui <- fluidPage(

  sidebarLayout(
    sidebarPanel(
      sliderInput("bins",
                  "Number of bins:",
                  min = 1,
                  max = 50,
                  value = 30),
      checkboxInput("cb", "T/F"),
      actionButton("add_btn", "Add"),
      actionButton("delete_btn", "Delete")
    ),

    mainPanel(
      DTOutput("shiny_table")
    )
  )
)

server <- function(input, output) {

  this_table <- reactiveVal(this_table)

  observeEvent(input$add_btn, {
    t = rbind(data.frame(bins = input$bins,
                         cb = input$cb), this_table())
    this_table(t)
  })

  observeEvent(input$delete_btn, {
    t = this_table()
    print(nrow(t))
    if (!is.null(input$shiny_table_rows_selected)) {
      t <- t[-as.numeric(input$shiny_table_rows_selected),]
    }
    this_table(t)
  })

  output$shiny_table <- renderDT({
   datatable(this_table(), selection = 'single', options = list(dom = 't'))
  })
}

shinyApp(ui = ui, server = server)

最后,我想补充一点的是@Vishesh Shrivastavs推荐使用rhandsontable包也是一种可行的方法,但这样做肯定会失去一些灵活性。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接