I asked this question earlier - Write editable shiny Datatable to .csv file Trying to edit cells in a shiny datatable and replace the original data with the edited data.
I was able to figure out how to edit a single cell in the datatable, however if multiple cells are edited only the last edit is saved.
Code:
library(shiny)
library(shinydashboard)
library(tidyverse)
library(DT)
users <- reactiveFileReader(
intervalMillis = 1000,
NULL,
filePath = 'appData/userTest.csv',
readFunc = read.csv,
stringsAsFactors = FALSE
)
header <- dashboardHeader(title = "demo")
sidebar <- dashboardSidebar(uiOutput('sidebar'))
body <- dashboardBody(uiOutput("body"))
f1 <- fluidRow(
box(
dataTableOutput('userTable'),
width = 6
)
)
ui <- dashboardPage(title = 'admin function test', header, sidebar, body, skin='blue')
server <- function(input, output, session){
output$body <- renderUI({
tabItems(
tabItem(
tabName = 'admin', class = 'active', h2(f1)
)
)
})
output$sidebar <- renderUI({
sidebarMenu(id = 'sidebarmenu',
menuItem("admin", tabName = "admin", icon = icon("adjust")),
actionButton("do", 'save', icon = icon('redo'))
)
})
observeEvent(
input$do,{
write.csv(edited(),'appData/userTest.csv', row.names = FALSE)
})
output$userTable <- renderDataTable({
DT::datatable(users(),
editable = TRUE,
rownames = FALSE)
})
edited <- reactive({editData(users(), input$userTable_cell_edit, proxy = NULL, rownames = FALSE, resetPaging = FALSE)})
}
shinyApp(ui = ui, server = server)
Data:
userName start end
1 John 06/08/2019 01/10/2019
2 Mary 01/01/2019 01/10/2019
3 Mike 23/10/2019 01/10/2019
4 Steve 25/07/2019 07/02/2015
5 Kate 01/01/2019 29/04/2019
I imagine this is because the editData()
function records only a single edit at a time.
How can multiple cells be edited and saved in one go?
See below, this will allow multiple changes and each one is tracked.
library(shiny)
library(shinydashboard)
library(tidyverse)
library(DT)
header <- dashboardHeader(title = "demo")
sidebar <- dashboardSidebar(
sidebarMenu(id = 'sidebarmenu',
menuItem("admin", tabName = "admin", icon = icon("adjust")),
downloadButton("downloadResults","Download Results")
)
)
body <- dashboardBody(
tabItems(
tabItem(
tabName = 'admin', class = 'active',
fluidRow(
box(
dataTableOutput('userTable'), width = 6
)
)
)
)
)
ui <- dashboardPage(title = 'admin function test', header, sidebar, body, skin='blue')
server <- function(input, output, session){
dat <- data.frame(userName = c("John","Mary","Mike"), start = c("06/08/2019","01/01/2019","23/10/2019"), stringsAsFactors = FALSE)
output$userTable <- renderDataTable({
DT::datatable(isolate(dat),
editable = TRUE,
rownames = FALSE)
})
###Tracking Changes###
rvs <- reactiveValues(
data = NA #dynamic data object
)
observe({
rvs$data <- dat
})
proxy = dataTableProxy('userTable')
observe({
DT::replaceData(proxy, rvs$data, rownames = FALSE, resetPaging = FALSE)
})
observeEvent(input$userTable_cell_edit, {
rvs$data <<- editData(rvs$data, input$userTable_cell_edit, rownames = FALSE)
})
# observeEvent(
# input$do,{
# write.csv(rvs$data,'userTest.csv', row.names = FALSE)
# })
output$downloadResults <- downloadHandler(
filename = function(){paste("userTest.csv.csv", sep = "")},
content = function(file){write.csv(rvs$data, file, row.names = FALSE)}
)
}
shinyApp(ui = ui, server = server)
If you want multiple cells to be editable at the same time, add this line to your datatable:
editable = list(target = "all") #can be all, row, or column
Few tips when posting in the future:
renderUI
's for the body and sidebar just clutters your code.