Search code examples
rshinydt

Combining editable DT with `add row` functionality


I am trying to address two specific needs:

  • User needs to be able to add a row to the DataTable
  • Datatable needs to be editable

Currently, I have the 'add row' functionality set up, as well as the editable functionality, but the edits don't persist table sorting, or when new rows are added.

When you run the below code, notice how you can add/delete rows, but when you edit a field and then add/delete a row, you lose the edits.

I am hoping someone can help me combine these two requirements!

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'), editable = T)
  })
}

shinyApp(ui = ui, server = server)

Solution

  • You will need to use observeEvent to update the table data after an edit. You can extract the relevant table row, column, and newly edited value from input$shiny_table_cell_edit. Try adding this code to your server function:

    observeEvent(input$shiny_table_cell_edit, {
        info <- input$shiny_table_cell_edit
        edit_row <-  info$row
        edit_col <-  info$col   
        edit_value <-  info$value
    
        t = this_table()
        t[edit_row,edit_col] <- edit_value
        this_table(t)
    })