Rprogrammer
Rprogrammer

Reputation: 57

How to save edits made in DT while using SelectInput in correct position

When using editable DataTable (package DT) where input is chosen by SelectInput the edits made isn't saved where it should be.

Choosing a specific variable shows for example rows 50-60 from datatable in first rows. Editing them saves the edits on the first rows instead of in rows 50-60.

In example below you can choose variable versicolor and delete setosa. Then edit Petal.Length to random number. Edit should be saved in row 51 but instead it is saved in row 1.

I am thinking about a workaround based on an index-column so the edits are saved in row number (indexrow). But I am not sure how to do that.

#Packages
library(shiny)
library(shinyalert)
library(shinydashboard)
library(leaflet)
library(leaflet.extras)
library(DT)

#data
iris = iris

#Shiny-app (ui)
header = dashboardHeader(title = "SelectInput DataTable example")

sidebar = dashboardSidebar(selectInput("species", "Choose species:  ",    choices = iris$Species, selected = "setosa",  multiple = TRUE))

body = dashboardBody(fluidRow(dataTableOutput("table")))

ui = dashboardPage(skin = "red", header, sidebar, body)

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


  output$table = DT::renderDataTable(iris[iris$Species %in% input$species,], editable = TRUE)

  proxy = dataTableProxy('table')

  observeEvent(input$table_cell_edit, {
    info = input$table_cell_edit
    str(info)
    i = info$row
    j = info$col
    v = info$value
    iris[i, j] <<- DT::coerceValue(v, iris[i, j])
    replaceData(proxy, iris, resetPaging = FALSE)  # important
  })
}

shinyApp(ui = ui, server = server)

Upvotes: 2

Views: 1177

Answers (1)

St&#233;phane Laurent
St&#233;phane Laurent

Reputation: 84619

Try this:

#Packages
library(shiny)
library(shinydashboard)
library(DT)

#data
iris = iris

#Shiny-app (ui)
header = dashboardHeader(title = "SelectInput DataTable example")

sidebar = dashboardSidebar(selectInput("species", "Choose species: ", 
                                       choices = iris$Species, selected = "setosa",  multiple = TRUE))

body = dashboardBody(fluidRow(DT::dataTableOutput("table")))

ui = dashboardPage(skin = "red", header, sidebar, body)

# Javascript 
js <- function(rows){
  c(
    "function(settings){",
    "  var table = settings.oInstance.api();",
    sprintf("  var indices = [%s];", paste0(rows-1, collapse = ",")),
    "  table.rows(indices).remove().draw();",
    "}"
  )
}

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

  dat <- reactiveVal(iris)

  Rows <- reactive({
    which(iris$Species %in% input$species)
  })

  output$table = DT::renderDataTable({
    rows <- setdiff(1:nrow(iris), Rows())
    datatable(
      dat(), 
      editable = TRUE,
      options = list(
        initComplete = JS(js(rows))
      )
    )
  }, server = FALSE)

  observeEvent(input$table_cell_edit, {
    info = input$table_cell_edit
    info$row = Rows()[info$row+1] - 1
    dat(editData(dat(), info))
  })
}

shinyApp(ui = ui, server = server)

Upvotes: 2

Related Questions