Saving state of Shiny app to be restored later
Asked Answered
T

3

9

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

Trotline answered 3/10, 2015 at 11:48 Comment(1)
Here you can find a related answer using shiny's built-in capabilities to create bookmarks.Deferential
A
9

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]]))
              )
      }
    })
  }
)
Alpenglow answered 3/10, 2015 at 23:26 Comment(1)
I have had great success with the answers here and threads suggested. Thank you all for the support. I do have a follow up question. I use both rhandsontable and renderUI. For the rhandsontable I am able to use the technique here to save and update it. I need to make sure the widget is activated so the callback is fired when the app is saved. Is there a way to force this in the code? renderUI is still a mystery any suggestions would be great.Trotline
P
1

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.

Phox answered 30/12, 2018 at 10:50 Comment(0)
H
0

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)
      }
    })
  }
)
Hyperbaton answered 10/8, 2019 at 7:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.