1

When I run my Shiny app, it loads multiple data files. In a tab you can enter an input that modifies a value in a loaded dataframe. I would like to save the modified dataframe for new sessions, but I would also like to use the modified dataframe in another tab during the same session.

I have the following reproducible example in the server side:

user_base is the original dataframe loaded in global.R



server = function(input, output, session) {

my_data=reactiveVal()
my_data(user_base)

observeEvent(input$send, {
if (isTRUE(input$text4!=input$text5)==T){
      user_base[which(user_base[,1]==input$text4), 2]=input$text5      
      save(user_base, file="user_base.RData")
      
}
})

}

When I navigate to the other tab it doesn't read the modified file, but the orifinal file, which is not what I want. However, the modified file is saved for the next session.

Citizen
  • 121
  • 15

1 Answers1

1

First things first, your likelihood of getting useful answers increases tremendously if you provide a Minimal Reproducible Example

Having said that, here's an example app which shows the idea:

  1. When loading the data, you load it into a reactiveVal (my_data). This should hold the actual copy of your data and all data operations should update my_data accordingly.
  2. When consuming some of the data, you do not reload the data, but instead use my_data.
  3. Likewise, when you store it, you use my_data.

In this way you keep stored and live data in sync.

Reprex

Play with the app to get the idea. You can modify the data in the corresponding tab and decide to store it permanently. If you do so and reload the app, you will see that the changes made are persistently stored. You cna also reste the data to its default.

library(shiny)
library(here)
library(glue)

data_dir <- here("datasets")

if (!dir.exists(data_dir)) {
   dir.create(data_dir)
}


ui <- fluidPage(
   titlePanel("Modify and Save Data"),
   sidebarLayout(
      sidebarPanel(
         selectInput("data_src", 
                     "Data:",
                     c("mtcars", "iris", "ChickWeight", 
                       "ToothGrowth", "PlantGrowth")),
         actionButton("save", "Save  Dataset", icon("save"))
      ),
      
      mainPanel(
         tabsetPanel(
            tabPanel("Modify Data",
                     p("Current Data:", textOutput("data_info", inline = TRUE)),
                     actionButton("add", "Add Random Column"),
                     actionButton("remove", "Remove Random Row"),
                     actionButton("reset", "Reset Data")),
            tabPanel("Table", tableOutput("table"))
         )
      )
   )
)

server <- function(input, output, session) {
   
   get_filename <- function(data_name) {
      here(data_dir, paste0(data_name, ".Rdata"))
   }

   trigger_reload <- reactiveVal(0)
   my_data <- reactiveVal(NULL)
   
   observeEvent(list(input$data_src, trigger_reload()), {
      fn <- get_filename(req(input$data_src))
      if (!file.exists(fn)) {
         my_data(get(input$data_src))
      } else {
         my_data(readRDS(fn))
      }
   })
   
   observeEvent(input$save, {
      fn <- get_filename(req(input$data_src))
      saveRDS(req(my_data()),
              fn)
   })
   
   observeEvent(input$reset, {
      fn <- get_filename(req(input$data_src))
      ## unlink does not throw error for non existing file
      unlink(fn) 
      trigger_reload(trigger_reload() + 1) ## retrigger-reload
   })
   
   observeEvent(input$add, {
      dat <- my_data()
      nm <- make.unique(c(names(dat), paste0("n", ncol(dat) + 1)))
      dat <- cbind(dat, round(rnorm(nrow(dat)), 2))
      names(dat) <- nm
      my_data(dat)
   })
   
   observeEvent(input$remove, {
      dat <- my_data()
      if (nrow(dat)) {
         my_data(dat[-sample(nrow(dat), 1), , drop = FALSE])
      }
   })

   
   output$table <- renderTable(req(my_data()))
   
   output$data_info <- renderText({
      dat <- req(my_data())
      dat_nm <- req(input$data_src)
      glue("{dat_nm} ({ncol(dat)} cols / {nrow(dat)} rows)")
   })
}

shinyApp(ui, server)
thothal
  • 16,690
  • 3
  • 36
  • 71
  • I have modified the code above, but it doesn't work. In the same session, the data does not keep the changes. It does work in the next session, since the changes are saved – Citizen Jun 10 '22 at 16:54