Editing a reactive DT table that remembers the filtering context without page flickering

shiny
dt
#1

Hello!

I've been working on an app that I first described under this link. Since it's growing I'm facing new issues that I'm trying to overcome:

  1. How do make sure that when a user edits the values of the DT table in a filtering context, the table doesn't unfilter?

  2. How to prevent page flickering when the editable table get updated and it's values get populated into the second table to update it?

I've tried a couple solutions I found on the web which eventually boil down to something like this:

    proxy_x2 = dataTableProxy("x2")
    
    observeEvent(input$x2_cell_edit, {
      info = input$x2_cell_edit
      i = info$row
      j = info$col
      v = info$value

      rec_val$iris[i, j] <- isolate(DT::coerceValue(v, rec_val$iris[i, j]))

      DT::replaceData(proxy_x2, rec_val$iris, resetPaging = FALSE, clearSelection = "none")

    })

where I need to use a proxy of the table that is being updated using resetPaging and clearSelection options along with isolate() on top of DT::coerceValue. Unfortunately, none of these really helped in this case. What's the best way of achieving points 1 & 2?

0 Likes

#2

Also as an addition I did some testing:

I took this code (link) that show's that functionality and is working without any problems:

library(shiny)
library(DT)
shinyApp(
  ui = fluidPage(
    DTOutput('x1')
  ),
  server = function(input, output, session) {
    x = iris
    x$Date = Sys.time() + seq_len(nrow(x))
    output$x1 = renderDT(x, selection = 'none', rownames = F, editable = T)
    
    proxy = dataTableProxy('x1')
    
    observeEvent(input$x1_cell_edit, {
      info = input$x1_cell_edit
      str(info)
      i = info$row
      j = info$col + 1  # column index offset by 1
      v = info$value
      x[i, j] <<- DT::coerceValue(v, x[i, j])
      replaceData(proxy, x, resetPaging = FALSE, rownames = FALSE)
    })
  }
)

And I changed it to something applicable to my example: with an update button using eventReactive, observe and reactiveValues:

library(shiny)
library(DT)

shinyApp(
  ui = fluidPage(
    actionButton(
      inputId = "go",
      label = "Update"
    ),
    DTOutput('x1')
  ),
  server = function(input, output, session) {
    
    ### This is new ###
    
    evt_go_iris <- eventReactive(input$go, {
      x = iris
      x$Date = Sys.time() + seq_len(nrow(x))
      x <- as.data.frame(x)
    })
    
    rec_val = reactiveValues(df = NULL)
    
    observe({
      rec_val$iris   <- evt_go_iris()
    })
    
    ### This is new ###
    
    output$x1 = renderDT(rec_val$iris, selection = 'none', filter = "top", rownames = F, editable = T)
    
    proxy = dataTableProxy('x1')
    
    observeEvent(input$x1_cell_edit, {
      info = input$x1_cell_edit
      str(info)
      i = info$row
      j = info$col + 1  # column index offset by 1
      v = info$value
      rec_val$iris[i, j] <<- DT::coerceValue(v, rec_val$iris[i, j])
      replaceData(proxy, rec_val$iris, resetPaging = FALSE, rownames = FALSE)
    })
  }
)

After making that change the 1st code doesn't work anymore which points to observe & reactiveValues not being properly applied in this context. I see where the error is but I don't understand it or know how to debug. Hope that helps somebody else understanding my use case!

0 Likes