user2945234
user2945234

Reputation: 428

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

Upvotes: 9

Views: 3797

Answers (3)

kimman
kimman

Reputation: 421

The above example may not work if shiny UI involves date. Here is a minor change for date handling.

library(shiny)

shinyApp(
  ui = fluidPage(
    dateInput("date", "date", "2012-01-01"),
    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]]))
        )
        temp=as.character(as.Date(values$date, origin = "1970-01-01"))
        updateDateInput(session, inputId="date", label ="date", value = temp)
      }
    })
  }
)

Upvotes: 0

jff
jff

Reputation: 320

Now with bookmarking is possible to save the state of your shinyapp. You have to put the bookmarkButton on your app and also the enableBookmarking.

Upvotes: 1

DeanAttali
DeanAttali

Reputation: 26313

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]]))
              )
      }
    })
  }
)

Upvotes: 9

Related Questions