0
votes

I am trying to add an editable datatable in r shiny. I have two components to it. First being allowing the user to add a new row and delete a selected row. Secondly when the user changes any value in the cell it should update the corresponding cell. The issue I am facing first off is to unable to delete selected rows. I am able to add those but not delete. Below is the code which I am using. Also I am trying to reset to a default table but it wont reset to the default table. How can I fix this. Thank you.

### Libraries
library(shiny)
library(dplyr)
library(DT)

### Data
input_data <- data.frame(aa = c("Brand1", "Brand2","Brand3"),
                         bb = c(2000, 3000, 4000),
                         cc = c (.5, .5, .5),
                         dd = c(2000, 3000, 4000),
                         ee = c (.5, .5, .5),
                         ff = c (.5, .5, .5),
                         gg = c (.5, .5, .5),
                         stringsAsFactors = FALSE)

### Shiny App
shinyApp(
  ui = basicPage(
    mainPanel(

      actionButton("reset", "Reset"),
      actionButton("add_btn", "Add"),
      actionButton("delete_btn", "Delete"),
      tags$hr(),
      DT::dataTableOutput("mod_table")    )
  ),
  server = function(input, output) {

    #demodata<-input_data

    this_table <- reactiveVal(input_data)

    observeEvent(input$add_btn, {
      t = rbind(data.frame(aa = "default",
                           bb = 1000000,cc = 2.0,dd = 20000, ee = 40,ff = 00 , gg = 00), 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)
    })
observeEvent(input$reset, {
       this_table <- input_data # your default data
     })

    output$mod_table <- DT::renderDataTable({
      datatable(this_table(), selection = 'single',editable = TRUE, options = list(dom = 't'))

    })
    }
)

2
does the answer work for you? - Tonio Liebrand

2 Answers

1
votes

Deleting rows:

You get the selected rows with input$tableId_rows_selected. Your tableId is mod_table.

So, if you change from input$shiny_table_rows_selected to input$mod_table_rows_selected it will work.

Resetting table:

If you switch from assigning to this_table to using this_table() as a "set function" it will work. I think its just a small typo as you already use this syntax for the "delete part" correctly:

observeEvent(input$reset, {
  this_table(input_data)
})

Reproducible code:

library(shiny)
library(dplyr)
library(DT)

### Data
input_data <- data.frame(aa = c("Brand1", "Brand2","Brand3"),
                         bb = c(2000, 3000, 4000),
                         cc = c (.5, .5, .5),
                         dd = c(2000, 3000, 4000),
                         ee = c (.5, .5, .5),
                         ff = c (.5, .5, .5),
                         gg = c (.5, .5, .5),
                         stringsAsFactors = FALSE)

### Shiny App
shinyApp(
  ui = basicPage(
    mainPanel(

      actionButton("reset", "Reset"),
      actionButton("add_btn", "Add"),
      actionButton("delete_btn", "Delete"),
      tags$hr(),
      DT::dataTableOutput("mod_table")    )
  ),
  server = function(input, output) {

    #demodata<-input_data

    this_table <- reactiveVal(input_data)

    observeEvent(input$add_btn, {
      t = rbind(data.frame(aa = "default", bb = 1000000,cc = 2.0, dd = 20000, 
                           ee = 40,ff = 00 , gg = 00), this_table())
      this_table(t)
    })

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

    observeEvent(input$reset, {
      this_table(input_data)
    })

    output$mod_table <- DT::renderDataTable({
      datatable(this_table(), selection = 'single',editable = TRUE, 
                options = list(dom = 't'))
    })
  }
)
0
votes

A JavaScript solution:

library(shiny)
library(DT)

### Data
input_data <- data.frame(aa = c("Brand1", "Brand2","Brand3"),
                         bb = c(2000, 3000, 4000),
                         cc = c (.5, .5, .5),
                         dd = c(2000, 3000, 4000),
                         ee = c (.5, .5, .5),
                         ff = c (.5, .5, .5),
                         gg = c (.5, .5, .5),
                         stringsAsFactors = FALSE)

### Callback
callback <- c(
  '$("#add_btn").on("click", function(){',
  '  var newrow = ["default", 1000000, 2, 20000, 40, 0, 0];',
  '  table.row.add(newrow).draw();',
  '});',
  '$("#delete_btn").on("click", function(){',
  '  var rows = table.rows(".selected");',
  '  rows.remove().draw();',
  '});'
)

### Shiny App
shinyApp(
  ui = basicPage(
    mainPanel(
      br(),
      actionButton("reset", "Reset"),
      actionButton("add_btn", "Add"),
      actionButton("delete_btn", "Delete"),
      tags$hr(),
      DTOutput("mod_table")
    )
  ),

  server = function(input, output) {

    output$mod_table <- renderDT({
      input$reset
      datatable(input_data, selection = 'single', editable = TRUE, 
                rownames = FALSE, 
                options = list(dom = 't'), callback = JS(callback))
    }, server = FALSE)

  }
)