英文:
How to retain the filtered (or different page) view of a datatable after editing in a Shiny app?
问题
我正在编写一个Shiny应用程序,其中我正在呈现一个可编辑的数据表。在某些情况下,我希望用户可以筛选表格或转到不同的页面,然后对表格进行编辑。在进行编辑之后,我希望表格的当前视图保持不变,同时显示表格中的编辑内容。对列的编辑还会更改另一列中的值,因此这两个编辑需要同时显示在保持视图的同时。
这是我迄今为止编写的代码:
library(shiny)
library(DT)
# 创建一个包含50个条目的示例数据框
df <- data.frame(
name = paste0("Person ", 1:50),
age = sample(20:60, 50, replace = TRUE),
salary = sample(2000:5000, 50, replace = TRUE),
stringsAsFactors = FALSE
)
# 创建一个Shiny应用程序
ui <- fluidPage(
DTOutput("table")
)
server <- function(input, output, session) {
# 创建一个reactiveValues对象来存储数据框
rv <- reactiveValues()
rv$df <- df
# 渲染表格
output$table <- renderDT({
datatable(
rv$df,
rownames = FALSE,
editable = TRUE,
filter = "top",
selection = "none",
extensions = c(
"ColReorder",
"Buttons"
),
options = list(
dom = "lBRrftpi",
autoWidth = FALSE,
pageLength = 20,
scrollX = FALSE,
ColReorder = TRUE,
buttons = list(list(extend = 'csv', filename= 'data'), 'print', 'copy')
)
)
})
# 在编辑后更新表格
observeEvent(input$table_cell_edit, {
info <- input$table_cell_edit
i <- info$row
j <- info$col
v <- info$value
new_i <- i
new_j <- j + 1
new_val <- v * 100
new_info <- data.frame(
row = new_i,
col = new_j,
value = new_val
)
rv$df <- editData(rv$df, info, rownames = FALSE)
if(j == 1){
rv$df <- editData(rv$df, new_info, rownames = FALSE)
}
replaceData(proxy = dataTableProxy("table"), data = rv$df, resetPaging = FALSE)
})
}
# 运行应用程序
shinyApp(ui, server)
尽管表格中的编辑和另一列的相关更改确实有效,但表格视图在编辑单元格后重置。有人可以帮助我编写代码,以在编辑后保持视图吗?
英文:
I am writing a Shiny app where I am rendering an editable datatable. In some instances I would like the user to filter the table or go to a different page and then make edits to the table. After this editing, I would like the current view of the table to remain while showing the edits in the table. The editing of a column also changes the values in another column, so both these edits need to be displayed while retaining the view.
This is the code I have come up with so far
library(shiny)
library(DT)
# create a sample data frame with 50 entries
df <- data.frame(
name = paste0("Person ", 1:50),
age = sample(20:60, 50, replace = TRUE),
salary = sample(2000:5000, 50, replace = TRUE),
stringsAsFactors = FALSE
)
# create a shiny app
ui <- fluidPage(
DTOutput("table")
)
server <- function(input, output, session) {
# create a reactiveValues object to store the data frame
rv <- reactiveValues()
rv$df <- df
# render the table
output$table <- renderDT({
datatable(
rv$df,
rownames = F,
editable = T,
filter = "top",
selection = "none",
extensions = c(
"ColReorder",
"Buttons"
),
options = list(
dom = "lBRrftpi",
autoWidth = F,
pageLength = 20,
scrollX = F,
ColReorder = T,
buttons = list(list(extend = 'csv', filename= 'data'), 'print', 'copy')
)
)
})
# update the table when edited
observeEvent(input$table_cell_edit, {
info <- input$table_cell_edit
i <- info$row
j <- info$col
v <- info$value
new_i <- i
new_j <- j + 1
new_val <- v * 100
new_info <- data.frame(
row = new_i,
col = new_j,
value = new_val
)
rv$df <<- editData(rv$df, info, rownames = F)
if(j == 1){
rv$df <<- editData(rv$df, new_info, rownames = F)
}
replaceData(proxy = dataTableProxy("table"), data = rv$df, resetPaging = FALSE)
})
}
# run the app
shinyApp(ui, server)
While the edits in the table and the dependant changes in the other column do work, the table view resets as soon as I edit a cell. Can someone please help me with code that retains the view after editing?
答案1
得分: 1
你观察到的情况是因为你使用的数据对象是响应式的,当你更新它时,表格会在更新发生时重新渲染。使用代理的一个很酷的地方是你不需要一个响应式数据对象。此外,你可以将代理对象传递给editData
,然后就不需要replaceData
了。
library(shiny)
library(DT)
# 创建一个包含50条条目的示例数据框
df <- data.frame(
name = paste0("Person ", 1:50),
age = sample(20:60, 50, replace = TRUE),
salary = sample(2000:5000, 50, replace = TRUE),
stringsAsFactors = FALSE
)
# 创建一个Shiny应用程序
ui <- fluidPage(
DTOutput("table")
)
server <- function(input, output, session) {
# 渲染表格
output$table <- renderDT({
datatable(
df,
rownames = FALSE,
editable = TRUE,
filter = "top",
selection = "none",
extensions = c(
"ColReorder",
"Buttons"
),
options = list(
dom = "lBRrftpi",
autoWidth = FALSE,
pageLength = 20,
scrollX = FALSE,
ColReorder = TRUE,
buttons = list(list(extend = 'csv', filename= 'data'), 'print', 'copy')
)
)
})
proxy <- dataTableProxy("table")
# 当编辑时更新表格
observeEvent(input$table_cell_edit, {
info <- input$table_cell_edit
i <- info$row
j <- info$col
v <- info$value
new_i <- i
new_j <- j + 1
new_val <- v * 100
new_info <- data.frame(
row = new_i,
col = new_j,
value = new_val
)
df <- editData(df, info, proxy, rownames = FALSE)
if(j == 1){
df <- editData(df, new_info, proxy, rownames = FALSE)
}
})
}
英文:
What you observe is occuring because the data object you use is reactive and you update it, and then the table is re-rendered when the update occurs. The cool thing with a proxy is that you don't need a reactive data object. Also, you can pass the proxy object to editData
and then there's no need of replaceData
.
library(shiny)
library(DT)
# create a sample data frame with 50 entries
df <- data.frame(
name = paste0("Person ", 1:50),
age = sample(20:60, 50, replace = TRUE),
salary = sample(2000:5000, 50, replace = TRUE),
stringsAsFactors = FALSE
)
# create a shiny app
ui <- fluidPage(
DTOutput("table")
)
server <- function(input, output, session) {
# render the table
output$table <- renderDT({
datatable(
df,
rownames = F,
editable = T,
filter = "top",
selection = "none",
extensions = c(
"ColReorder",
"Buttons"
),
options = list(
dom = "lBRrftpi",
autoWidth = F,
pageLength = 20,
scrollX = F,
ColReorder = T,
buttons = list(list(extend = 'csv', filename= 'data'), 'print', 'copy')
)
)
})
proxy <- dataTableProxy("table")
# update the table when edited
observeEvent(input$table_cell_edit, {
info <- input$table_cell_edit
i <- info$row
j <- info$col
v <- info$value
new_i <- i
new_j <- j + 1
new_val <- v * 100
new_info <- data.frame(
row = new_i,
col = new_j,
value = new_val
)
df <<- editData(df, info, proxy, rownames = F)
if(j == 1){
df <<- editData(df, new_info, proxy, rownames = F)
}
})
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论