Jacqueline Nolis
Jacqueline Nolis

Reputation: 1547

Shiny reactiveUI reseting value on reload

One can use reactiveUI interfaces in shiny to selectively show inputs variables that are relevant only at certain times. Here is an example with a variable "a", which depending on the value causes the interface to show variables "c" or "d":

ui.R

shinyUI(fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectInput("a","choose selection",list("c","d")),
        uiOutput("b")),
      mainPanel(verbatimTextOutput("text"))
    )))

server.R

choice_list <- list(
  "c" = selectInput("c", "first set of choices", choices = list("cat","dog","house")),
  "d" = selectInput("d", "second set of choices", choices = list("money","power","fame")))
shinyServer(function(input, output) {
  output$b <- renderUI({
    choice_list[input$a]
  })  
  output$text <- renderText(paste0(input$c,input$d))
})

So this works good and well, as you can see depending on the context you can select different items. My issue is that each time you switch a the value of what you switch to (either c or d) resets to its default. That isn't a problem here with only one input being shown at a time, but if you imagine that many different input parameters are being shown at once having them all reset each time you switch them in would be awful. Is there any way to store the previous values so that when shiny reloads the UI they don't reset?

Just for a bit more detail, this is just an example of what I am doing with a much larger set of code. I have different analyses the user could run, and each have their own lists of input objects. However they also have a large overlap --many of the input objects in one list show up in another. Currently each time you switch between which analysis you want to do, the entire set of inputs resets, which is very annoying for the users.

Each analysis has some code that it uses to run, and also a list of UI objects to use. These objects live in a different file, which is similar to how the choice_list lives outside of the shinyServer function.

Upvotes: 4

Views: 3057

Answers (1)

Matthew Plourde
Matthew Plourde

Reputation: 44614

Here's one way. Here I store the current selections as global variables and the selectInput calls as expressions, which I evaluate afresh each time input$a changes.

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectInput("a","choose selection",list("c","d")),
        uiOutput("b")),
      mainPanel(verbatimTextOutput("text"))
    ))

c.selected <- 'cat'
d.selected <- 'money'

choice_list <- list(
  "c" = quote(selectInput("c", "first set of choices", choices = list("cat","dog","house"), selected=c.selected)),
  "d" = quote(selectInput("d", "second set of choices", choices = list("money","power","fame"), selected=d.selected))
  )

server <- function(input, output) {
  output$b <- renderUI({
    eval(choice_list[[input$a]])
  })  

  observe({
    c.selected <<- input$c
  })

  observe({
    d.selected <<- input$d
  })


  output$text <- renderText(paste0(input$c,input$d))
}

runApp(list(ui=ui, server=server))

Upvotes: 1

Related Questions