'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 |
