Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Saving state of Shiny app to be restored later

I have a shiny application with many tabs and many widgets on each tab. It is a data-driven application so the data is tied to every tab.

I can save the application using image.save() and create a .RData file for later use.

The issue I am having how can I get the state restored for the widgets?

If the user has checked boxes, selected radio buttons and specified base line values in list boxes can I set those within a load() step?

I have found libraries such as shinyURL and shinystore but is there a direct way to set the environment back to when the write.image was done?

I am not sure where to even start so I can't post code.

edit: this is a cross-post from the Shiny Google Group where other solutions have been suggested

like image 354
user2945234 Avatar asked Oct 03 '15 11:10

user2945234


1 Answers

This is a bit hacky, but it works. It uses an "internal" function (session$sendInputMessage) which is not meant to be called explicitly, so there is no guarantee this will always work.

You want to save all the values of the input object. I'm getting all the widgets using reactiveValuesToList(input) (note that this will also save the state of buttons, which doesn't entirely make sense). An alternative approach would be to enumerate exactly which widgets to save, but that solution would be less generic and you'd have to update it every time you add/remove an input. In the code below I simply save the values to a list called values, you can save that to file however you'd like (RDS/text file/whatever). Then the load button looks at that list and updates every input based on the value in the list.

There is a similar idea in this thread

library(shiny)

shinyApp(
  ui = fluidPage(
    textInput("text", "text", ""),
    selectInput("select", "select", 1:5),
    uiOutput("ui"),
    actionButton("save", "Save"),
    actionButton("load", "Load")
  ),

  server = function(input, output, session) {

    output$ui <- renderUI({
      tagList(
        numericInput("num", "num", 7),
        checkboxGroupInput("chk", "chk", 1:5, c(2,4))
      )
    })

    observeEvent(input$save, {
      values <<- lapply(reactiveValuesToList(input), unclass)
    })

    observeEvent(input$load, {
      if (exists("values")) {
       lapply(names(values),
              function(x) session$sendInputMessage(x, list(value = values[[x]]))
              )
      }
    })
  }
)
like image 70
DeanAttali Avatar answered Oct 18 '22 17:10

DeanAttali