1
votes

I'm trying to restore the state of an app that includes a selectizeInput() generated with renderUI() inside a Shiny module. Because the number of choices is large (in my real app), I'm using server-side selectize--which I think is the main stumbling block.

Why doesn't the following example app restore the selections for the ns("choices") input after making selections, bookmarking, and then copying and pasting into new browser tab?

library(shiny)
choices <- c("a", "b", "c")

insert_choices_ui <- function(id) {
  ns <- NS(id)
  tags$div(
    id = ns("main"),
    selectInput(inputId = ns("select"), label = "Select", choices = c("no", "yes")),
    uiOutput(ns("ui1"))
  )
}

insert_choices_server <- function(id) {
  moduleServer(
    id,
    function(input, output, session) {
      ns <- session$ns
      
      output$ui1 <- renderUI({
        req(input$select)
        if (input$select == "yes") {
          tags$div(selectizeInput(
            inputId = ns("choices"),
            label = "Choices",
            choices = NULL,
            multiple = TRUE
          ))
        }
      })
      
      observeEvent(input$select, ignoreNULL = FALSE, ignoreInit = FALSE,  {
        updateSelectizeInput(
          session,
          inputId = "choices",
          choices = choices,
          server = TRUE
        )
      })
    })
}

ui <- function(request) {
  fluidPage(
    id = "main",
    actionButton("addButton", "Add Options"),
    bookmarkButton()
  )
}

server <- function(input, output, session) {
  observeEvent(input$addButton, ignoreNULL = TRUE, ignoreInit = TRUE, {
    insertUI(selector = "#main", ui = {
      insert_choices_ui(paste0("id", input$addButton))
    })
    insert_choices_server(id  = paste0("id", input$addButton))
  })
  
  onRestore(function(state) {
    for (i in seq_len(input$addButton)) {
      insertUI("#main", ui = insert_choices_ui(id = paste0("id", i)))
      
      insert_choices_server(id = paste0("id", i))
    }
  })
  
  onRestored(function(state) {
    if (!is.null(state$input$addButton) && state$input$addButton > 0) {
      for (i in seq_len(input$addButton)) {
        updateSelectizeInput(
          session,
          paste0("id", i, "-choices"),
          choices = choices,
          selected = state$input[[paste0("id", i, "-choices")]],
          server = TRUE
        )
      }
    }
  })
}

enableBookmarking(store = "server")
shinyApp(ui, server)
1

1 Answers

-1
votes

The issue here is that your call to insert_choices_server is getting triggered after onRestored sets the value and you're running this part of your code, which de-selects what your bookmark has selected:

      observeEvent(input$select, ignoreNULL = FALSE, ignoreInit = FALSE,  {
        updateSelectizeInput(
          session,
          inputId = "choices",
          choices = choices,
          server = TRUE
        )
      })

Remove those lines and change your renderUI function to pass in the choices:

      output$ui1 <- renderUI({
        req(input$select)
        if (input$select == "yes") {
          tags$div(selectizeInput(
            inputId = ns("choices"),
            label = "Choices",
            choices = choices,
            multiple = TRUE
          ))
        }
      })

(omitted the rest of the code as it is unchanged)