Bookmarking state and dynamic output


#1

Hi everyone,

I have the exact same problem as the one posted at https://stackoverflow.com/questions/41679431/shiny-app-bookmarking-dynamic-ui-input-lost which hasn’t been answered on SO since January. Any more luck among the shiny experts here?

Thanks in advance. Sincerely,


#2
library(shiny)

ui = function() fluidPage(bookmarkButton(), uiOutput("X"), uiOutput("Y"))

server = function(input, output, session) {
  output$X = renderUI(selectInput("X", "select possible values of Y",
    letters, multiple = TRUE))
  output$Y = renderUI(selectInput("Y", "select Y", input$X, multiple = TRUE))
}

shinyApp(ui = ui, server = server, enableBookmarking = "url")

Bookmarking gets a little tricky when you have inputs that depend on other dynamically created inputs.

In this example, selectInput Y gets rendered twice on page load. The first time is when it gets initialized with its bookmarked value, but no choices since input$X doesn’t exist yet. When input$X does get initialized, selectInput Y renders again with choices, but no selected value since bookmarked state only gets restored once.

The quickest way out of this mess is make X a static input instead-

library(shiny)

ui = function(request) {
  fluidPage(
    bookmarkButton(),
    selectInput("X", "select possible values of Y", letters, multiple = TRUE),
    uiOutput("Y")
  )
}

server = function(input, output, session) {
  output$Y = renderUI(selectInput("Y", "select Y", input$X, multiple = TRUE))
}

shinyApp(ui = ui, server = server, enableBookmarking = "url")

#3

Thanks but I cannot make the first input static unfortunately, otherwise I would have :wink:

But now I understand the problem. Is there anyway I can “manually” extract the settings from the state that is passed by the URL and make a workaround specific for that input?


#4

Check out the onBookmark and onRestore callbacks. Also this article: https://shiny.rstudio.com/articles/advanced-bookmarking.html

I took a stab at making the example work with only dynamic inputs.

library(shiny)

ui = function(request) {
  fluidPage(
    bookmarkButton(),
    uiOutput("X"),
    uiOutput("Y")
  )
}

server = function(input, output, session) {

  output$X <- renderUI(selectInput("X", "select possible values of Y",
                                   letters, multiple = TRUE))
  output$Y <- renderUI(selectInput("Y", "select Y", character(0), multiple = TRUE))

  observeEvent(input$X, {
    choices <- if (!is.null(input$X)) input$X else character(0)
    updateSelectInput(session, "Y", choices = choices, selected = input$Y)
  }, ignoreNULL = FALSE, ignoreInit = TRUE)

  onRestore(function(state) {
    X <- state$input$X
    Y <- state$input$Y
    updateSelectInput(session, "X", selected = X)
    updateSelectInput(session, "Y", choices = X, selected = Y)
  })
}

shinyApp(ui = ui, server = server, enableBookmarking = "url")

#5

Sorry not to have replied earlier. This is perfect, thanks. I was looking for the state$input$*** part. I am nearly sure I tried to access it this way and failed but it might be cause I wasn’t in the right context.

Thanks!