'DT Multiple tables not updating after edit using ReactiveValues

I want to use reactiveValues to update multiple tables but the edits do not show after my first edit and only load after my second edit. Is there something wrong with one of my DT settings? Editing table 5 should update both table 5 and 6 but nothing happens after my first edit.

library(shiny)
library(DT)

dt_output = function(title, id) {
  fluidRow(column(
    12, h1(paste0('Table ', sub('.*?([0-9]+)$', '\\1', id), ': ', title)),
    hr(), DTOutput(id)
  ))
}
render_dt = function(data, editable = 'cell', server = TRUE, ...) {
  renderDT(data, selection = 'none', server = server, editable = editable, ...)
}

shinyApp(
  ui = fluidPage(
    title = 'Double-click to edit table cells',
    
    dt_output('client-side processing (editable = "cell")', 'x1'),
    dt_output('client-side processing (editable = "row")', 'x2'),
    dt_output('client-side processing (editable = "column")', 'x3'),
    dt_output('client-side processing (editable = "all")', 'x4'),
    
    dt_output('server-side processing (editable = "cell")', 'x5'),
    dt_output('server-side processing (editable = "row")', 'x6'),
    dt_output('server-side processing (editable = "column")', 'x7'),
    dt_output('server-side processing (editable = "all")', 'x8'),
    
    dt_output('server-side processing (no row names)', 'x9'),
    dt_output('edit rows but disable certain columns (editable = list(target = "row", disable = list(columns = c(2, 4, 5))))', 'x10')
  ),
  
  server = function(input, output, session) {
    r1 = iris
    r1$Date = Sys.time() + seq_len(nrow(r1))
    t <- reactiveValues(
      d10 = r1,
      d9 = r1,
      d8 = r1,
      d7 = r1,
      d6 = r1,
      d5 = r1,
      d4 = r1,
      d3 = r1,
      d2 = r1,
      d1 = r1
    )
    
    options(DT.options = list(pageLength = 5))
    
    # client-side processing
    output$x1 = render_dt(t$d1, 'cell', FALSE)
    output$x2 = render_dt(t$d2, 'row', FALSE)
    output$x3 = render_dt(t$d3, 'column', FALSE)
    output$x4 = render_dt(t$d4, 'all', FALSE)
    
    observe(str(input$x1_cell_edit))
    observe(str(input$x2_cell_edit))
    observe(str(input$x3_cell_edit))
    observe(str(input$x4_cell_edit))
    
    # server-side processing
    output$x5 = render_dt(t$d5, 'cell')
    output$x6 = render_dt(t$d6, 'row')
    output$x7 = render_dt(t$d7, 'column')
    output$x8 = render_dt(t$d8, 'all')
    
    output$x9 = render_dt(t$d9, 'cell', rownames = FALSE)
    output$x10 = render_dt(t$d10, list(target = 'row', disable = list(columns = c(2, 4, 5))))
    
    # edit a single cell
    proxy5 = dataTableProxy('x5')
    observeEvent(input$x5_cell_edit, {
      info = input$x5_cell_edit
      str(info)  # check what info looks like (a data frame of 3 columns)
      t$d5 <<- editData(t$d5, info)
      replaceData(proxy5, t$d5, resetPaging = FALSE)  # important
      # the above steps can be merged into a single editData() call; see examples below
      t$d6 <<- editData(t$d6, input$x5_cell_edit, 'x6') #edit both tables.
    })
    
    # edit a row
    observeEvent(input$x6_cell_edit, {
      t$d6 <<- editData(t$d6, input$x6_cell_edit, 'x6')
    })
    
    # edit a column
    observeEvent(input$x7_cell_edit, {
      t$d7 <<- editData(t$d7, input$x7_cell_edit, 'x7')
    })
    
    # edit all cells
    observeEvent(input$x8_cell_edit, {
      t$d8 <<- editData(t$d8, input$x8_cell_edit, 'x8')
    })
    
    # when the table doesn't contain row names
    observeEvent(input$x9_cell_edit, {
      t$d9 <<- editData(d9, input$x9_cell_edit, 'x9', rownames = FALSE)
    })
    
    # edit rows but disable columns 2, 4, 5
    observeEvent(input$x10_cell_edit, {
      t$d10 <<- editData(t$d10, input$x10_cell_edit, 'x10')
    })
    
  }
)


Solution 1:[1]

If you use a proxy, you don't need to use a reactive dataframe in renderDT. It's not nice to use a reactive dataframe, because the table is re-rendered each time this dataframe changes. This seems to work:

  server = function(input, output, session) {
    r1 = iris
    r1$Date = Sys.time() + seq_len(nrow(r1))
    t <- list(
      d10 = r1,
      d9 = r1,
      d8 = r1,
      d7 = r1,
      d6 = r1,
      d5 = r1,
      d4 = r1,
      d3 = r1,
      d2 = r1,
      d1 = r1
    )
    
    options(DT.options = list(pageLength = 5))
    
    # client-side processing
    output$x1 = render_dt(t$d1, 'cell', FALSE)
    output$x2 = render_dt(t$d2, 'row', FALSE)
    output$x3 = render_dt(t$d3, 'column', FALSE)
    output$x4 = render_dt(t$d4, 'all', FALSE)
    
    observe(str(input$x1_cell_edit))
    observe(str(input$x2_cell_edit))
    observe(str(input$x3_cell_edit))
    observe(str(input$x4_cell_edit))
    
    # server-side processing
    output$x5 = render_dt(t$d5, 'cell')
    output$x6 = render_dt(t$d6, 'row')
    output$x7 = render_dt(t$d7, 'column')
    output$x8 = render_dt(t$d8, 'all')
    
    output$x9 = render_dt(t$d9, 'cell', rownames = FALSE)
    output$x10 = render_dt(t$d10, list(target = 'row', disable = list(columns = c(2, 4, 5))))

    # proxies
    ids <- paste0("x", 1:10)
    proxies <- setNames(
      lapply(ids, dataTableProxy), ids
    )

    # edit a single cell
    observeEvent(input$x5_cell_edit, {
      info = input$x5_cell_edit
      str(info)  # check what info looks like (a data frame of 3 columns)
      t$d5 <<- editData(t$d5, info)
      replaceData(proxies$x5, t$d5, resetPaging = FALSE)  # important
      # the above steps can be merged into a single editData() call; see examples below
      t$d6 <<- editData(t$d6, info, proxies$x6) #edit both tables.
    })
    
    # edit a row
    observeEvent(input$x6_cell_edit, {
      t$d6 <<- editData(t$d6, input$x6_cell_edit, proxies$x6)
    })
    
    # edit a column
    observeEvent(input$x7_cell_edit, {
      t$d7 <<- editData(t$d7, input$x7_cell_edit, proxies$x7)
    })
    
    # edit all cells
    observeEvent(input$x8_cell_edit, {
      t$d8 <<- editData(t$d8, input$x8_cell_edit, proxies$x8)
    })
    
    # when the table doesn't contain row names
    observeEvent(input$x9_cell_edit, {
      t$d9 <<- editData(t$d9, input$x9_cell_edit, proxies$x9, rownames = FALSE)
    })
    
    # edit rows but disable columns 2, 4, 5
    observeEvent(input$x10_cell_edit, {
      t$d10 <<- editData(t$d10, input$x10_cell_edit, proxies$x10)
    })
    
  }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Stéphane Laurent