rshinyshiny-servershiny-reactivity

Why is the saved selectize info in R shiny not loaded when the page is refreshed?


I'm developing an R Shiny application and I'm looking to save user inputs so that they can be loaded again later (I know I'll need to run this on Shiny Server to do so, working on that currently). Basically, the app saves the user inputs from several selectize inputs, appends them to a list, and saves the list server side. Everything in the Shiny app seems to be working as expected when I run it locally, except that when the page is refreshed then the saved groupings disappear until you either save a new group or restart the application. MWE below.

I'm proficient in R but still pretty new to Shiny apps. Any suggestions on how to preserve the saved groups if/when the page is refreshed would be appreciated!

library(shiny)
savedGroups = list()
saveRDS(savedGroups, file="./savedGroups.rdata")
ui<-
  fluidPage(
    fluidRow(
      column(4,
             selectizeInput(inputId = 'species', 
                            label = 'Select Species:', 
                            choices = iris$Species, 
                            selected = NULL, 
                            multiple = TRUE),
             selectizeInput(inputId = 'petalLength',
                            label = 'Select Petal Length:',
                            choices = sort(iris$Petal.Length),
                            selected = NULL,
                            multiple = TRUE),
             selectizeInput(inputId = 'petalWidth',
                            label = 'Select Petal Width:',
                            choices = sort(iris$Petal.Width),
                            selected = NULL,
                            multiple = TRUE)
      ),
      column(4,
             selectizeInput(inputId = 'savedGroup',
                            label = 'Saved Groups:',
                            choices = sort(names(readRDS('./savedGroups.rdata'))),
                            selected = '',
                            multiple = F),
             actionButton(inputId = "loadGroup", label = "Load Saved Group"),
             HTML('<br>'),
             HTML('<br>'),
             HTML('<br>'),
             textInput(inputId = 'newGroupName', label = 'New Group Name:', value = "", width = '12vw', placeholder = NULL),
             actionButton(inputId = "saveGroup", label = "Save Group"))
    )
  )

server<-function(input,output,session){
  
  observeEvent(input$loadGroup, 
               {
                 savedGroups = readRDS('./savedGroups.rdata')
                 loadSpecies = savedGroups[[input$savedGroup]]$species
                 loadPetalLength = savedGroups[[input$savedGroup]]$petalLength
                 loadPetalWidth = savedGroups[[input$savedGroup]]$petalWidth
                 # Clear fields
                 updateSelectizeInput(session = getDefaultReactiveDomain(),
                                      inputId = 'species',
                                      selected = '')
                 updateSelectizeInput(session = getDefaultReactiveDomain(),
                                      inputId = 'petalLength',
                                      selected = '')
                 updateSelectizeInput(session = getDefaultReactiveDomain(),
                                      inputId = 'petalWidth',
                                      selected = '')
                 # Update fields
                 updateSelectizeInput(session = getDefaultReactiveDomain(),
                                      inputId = 'species',
                                      selected = savedGroups[[input$savedGroup]]$species)
                 updateSelectizeInput(session = getDefaultReactiveDomain(),
                                      inputId = 'petalLength',
                                      selected = savedGroups[[input$savedGroup]]$petalLength)
                 updateSelectizeInput(session = getDefaultReactiveDomain(),
                                      inputId = 'petalWidth',
                                      selected = savedGroups[[input$savedGroup]]$petalWidth)
               }
  )
  observeEvent(input$saveGroup, 
               {
                 #save data field entries to new list
                 newGroup = list(newgroup = list(species = input$species,
                                                 petalLength = input$petalLength,
                                                 petalWidth = input$petalWidth))
                 names(newGroup) = input$newGroupName                         # rename list with user's group name
                 savedGroups <<- append(savedGroups, newGroup)                # append existing list
                 saveRDS(savedGroups, file="./savedGroups.rdata")        # save list data file to server
                 updateSelectizeInput(session = getDefaultReactiveDomain(),   # update saved allocation group choices
                                      inputId = 'savedGroup',
                                      choices = sort(names(readRDS("./savedGroups.rdata")))
                 )
                 updateTextInput(session = getDefaultReactiveDomain(),
                                 inputId = 'newGroupName',
                                 value = '')
               })  
  
}
shinyApp(ui, server)

I've tried making the saved group list a global object and also tried reading it in explicitly every time and nothing seems to prevent the saved list from disappearing on a refresh.


Solution

  • The reason that the selectize info isn't loading after refreshing is that you have the selectizeInput with inputID = 'savedGroup', in particular the corresponding readRDS, inside the ui. This has to be rearranged into the server. Below is one example using renderUI and uiOutput. Notice that I also added an onInitalize such that newly saved groups do not get selected automatically.

    enter image description here

    library(shiny)
    savedGroups = list()
    saveRDS(savedGroups, file="./savedGroups.rdata")
    
    ui<-
        fluidPage(
            fluidRow(
                column(4,
                       selectizeInput(inputId = 'species', 
                                      label = 'Select Species:', 
                                      choices = iris$Species, 
                                      selected = NULL, 
                                      multiple = TRUE),
                       selectizeInput(inputId = 'petalLength',
                                      label = 'Select Petal Length:',
                                      choices = sort(iris$Petal.Length),
                                      selected = NULL,
                                      multiple = TRUE),
                       selectizeInput(inputId = 'petalWidth',
                                      label = 'Select Petal Width:',
                                      choices = sort(iris$Petal.Width),
                                      selected = NULL,
                                      multiple = TRUE)
                ),
                column(4,
                       uiOutput('savedGroup'),
                       actionButton(inputId = "loadGroup", label = "Load Saved Group"),
                       HTML('<br>'),
                       HTML('<br>'),
                       HTML('<br>'),
                       textInput(inputId = 'newGroupName', label = 'New Group Name:', value = "", width = '12vw', placeholder = NULL),
                       actionButton(inputId = "saveGroup", label = "Save Group"))
            )
        )
    
    server<-function(input,output,session){
        
        output$savedGroup <- renderUI({
            selectizeInput(inputId = 'savedGroup',
                                      label = 'Saved Groups:',
                                      choices = sort(names(readRDS('./savedGroups.rdata'))),
                                      selected = ' ',
                                      multiple = F,
                           options = list(
                               onInitialize = I('function() { this.setValue(""); }')
                           ))
            })
        
        observeEvent(input$loadGroup, 
                     
                     {
                         savedGroups = readRDS('./savedGroups.rdata')
                         loadSpecies = savedGroups[[input$savedGroup]]$species
                         loadPetalLength = savedGroups[[input$savedGroup]]$petalLength
                         loadPetalWidth = savedGroups[[input$savedGroup]]$petalWidth
                         # Clear fields
                         updateSelectizeInput(session = getDefaultReactiveDomain(),
                                              inputId = 'species',
                                              selected = '')
                         updateSelectizeInput(session = getDefaultReactiveDomain(),
                                              inputId = 'petalLength',
                                              selected = '')
                         updateSelectizeInput(session = getDefaultReactiveDomain(),
                                              inputId = 'petalWidth',
                                              selected = '')
                         # Update fields
                         updateSelectizeInput(session = getDefaultReactiveDomain(),
                                              inputId = 'species',
                                              selected = savedGroups[[input$savedGroup]]$species)
                         updateSelectizeInput(session = getDefaultReactiveDomain(),
                                              inputId = 'petalLength',
                                              selected = savedGroups[[input$savedGroup]]$petalLength)
                         updateSelectizeInput(session = getDefaultReactiveDomain(),
                                              inputId = 'petalWidth',
                                              selected = savedGroups[[input$savedGroup]]$petalWidth)
                     }
        )
        observeEvent(input$saveGroup, 
                     {
                         #save data field entries to new list
                         newGroup = list(newgroup = list(species = input$species,
                                                         petalLength = input$petalLength,
                                                         petalWidth = input$petalWidth))
                         names(newGroup) = input$newGroupName                         # rename list with user's group name
                         savedGroups <<- append(savedGroups, newGroup)                # append existing list
                         saveRDS(savedGroups, file="./savedGroups.rdata")        # save list data file to server
                         updateSelectizeInput(session = getDefaultReactiveDomain(),   # update saved allocation group choices
                                              inputId = 'savedGroup',
                                              choices = sort(names(readRDS("./savedGroups.rdata")))
                         )
                         updateTextInput(session = getDefaultReactiveDomain(),
                                         inputId = 'newGroupName',
                                         value = '')
                     })  
    }
    
    
    shinyApp(ui, server)