I've built an R-shiny application that allows users to either manually type data into an RHandsonTable or to upload a csv file. Independently, these work just fine. However, I'm unable to get changes to stick if the user first uploads a file, then tries to edit the table manually.
If you run the example below you'll see that if you check some boxes and hit the "Go" button then the Boolean values are correctly displayed in the output table. Similarly, if you upload a simple csv file (example file also below) and hit "Go" then the Booleans are correctly displayed in the output table. But, if you upload a file then try to check or uncheck the boxes they immediately revert to the uploaded values and will only display the uploaded values until the app is restarted. Any ideas for how to recode this so that it can handle the upload and then allow users to edit that upload?
MRE:
library(shiny)
library(rhandsontable)
library(shinythemes)
library(data.table)
ui <- fluidPage(
actionButton("go", "Go"),
fileInput('file',label=''),
rHandsontableOutput('table1'),
tableOutput('table2')
)
DF1 <- data.frame(col1 = rep(F,3),col2 = rep(F,3))
server <- function(input, output, session) {
values <- reactiveValues()
observe({
if (!is.null(input$table1)) {
DF1 <- hot_to_r(input$table1)
} else {
if (is.null(values$DF1))
DF1 <- DF1
else
DF1 <- values$DF1
}
values$DF1 <- DF1
})
output$table1 <- renderRHandsontable({
if (!is.null(input$file)){
inputfile <- fread(input$file$datapath)
values$DF1 <- inputfile
rhandsontable(values$DF1)
} else {
if (!is.null(values$DF1)) rhandsontable(values$DF1)
}
})
observeEvent(input$go,{values$DF2<-values$DF1})
output$table2 <- renderTable(values$DF2)
}
shinyApp(ui, server)
For a simple file to upload, a csv like so proves the point:
col1,col2
TRUE,FALSE
FALSE,TRUE
TRUE,FALSE
Inside renderRHandsontable()
you check if (!is.null(input$file))
and if this is true, the values for the rhandsontable
are taken from the input file. However, the condition is always fulfilled after an upload and therefore the table can't be edited anymore after an upload.
Instead, you could take this away from the renderRHandsontable
and put it inside an observeEvent
on input$file
which replaces the values for the table once when an upload is done (this event just fires once after an upload):
library(shiny)
library(rhandsontable)
library(shinythemes)
library(data.table)
ui <- fluidPage(
actionButton("go", "Go"),
fileInput('file', label = ''),
rHandsontableOutput('table1'),
tableOutput('table2')
)
DF1 <- data.frame(col1 = rep(F, 3), col2 = rep(F, 3))
server <- function(input, output, session) {
values <- reactiveValues()
observe({
if (!is.null(input$table1)) {
DF1 <- hot_to_r(input$table1)
} else if (is.null(values$DF1)){
DF1 <- DF1
}
values$DF1 <- DF1
})
observeEvent(input$file, {
inputfile <- fread(input$file$datapath, drop = 1)
values$DF1 <- inputfile
})
output$table1 <- renderRHandsontable({
req(values$DF1)
rhandsontable(values$DF1)
})
observeEvent(input$go, {
values$DF2 <- values$DF1
})
output$table2 <- renderTable(values$DF2)
}
shinyApp(ui, server)