0
votes

I am building an Rshiny dashboard and am working to integrate some of shiny's more interactive features, and am currently working with the renderUI function, which (should, I believe) create additional widgets / input parameters based on the value of another input parameter. I am running into a simple error, but am having difficulty debugging. Below is a demo with the relevant code:

choices = c('All', 'None')
names(choices) = choices
ui <- fluidPage(theme = shinytheme('united'),

     # create permanent input for shot chart type (should be 5 options)
     selectInput(inputId = 'choice.input', label = 'Select a choice', multiple = FALSE,
                 choices = choices, selected = 'All'),

     uiOutput('secondinput')

)

server <- shinyServer(function(input, output) {

  if(input$choice.input == 'All') {

    my.second.input <- c('a', 'b', 'c', 'd', 'e')
    names(my.second.input) <- my.second.input

    # player parameter for player whose shot chart will be shown
    output$secondinput <- renderUI({
      selectInput(inputId = 'another.input', label = 'Check this input', multiple = FALSE,
                  choices = my.second.input, selected = 'a')
    })
  }
})

shinyApp(ui, server)

I'm not sure what's wrong here - I thought my use of renderUI() in the server function, with the names matching (output$secondinput, uiOutput('secondinput')), was corrent, but this is throwing an error at me...

Note that my full code has several options for choice.input, and I would like to have an if() case in the server for each of the (4-5) choice.input() values. Any help with what's wrong here is appreciated, thanks!

EDIT - to clarify, the select input choice.input, with label 'Select a Choice', should be displaying always. When this input is set to 'All', then I'd like for an additional input, secondinput, to be displayed. If choice.input is not set to 'All', then I don't want the second input to be displayed. Hope this helps.

1

1 Answers

1
votes

Here's a version of your code that works. I'm not sure if this is exactly what you want, it was a bit hard to tell, but hopefully you can take it from there.

choices = c('All', 'None')
names(choices) = choices
ui <- fluidPage(
  # create permanent input for shot chart type (should be 5 options)
  selectInput(inputId = 'choice.input', label = 'Select a choice', multiple = FALSE,
              choices = choices, selected = 'All'),
  uiOutput('secondinput')
)

server <- shinyServer(function(input, output) {
  # player parameter for player whose shot chart will be shown
  output$secondinput <- renderUI({
    if(input$choice.input == 'All') {

      my.second.input <- c('a', 'b', 'c', 'd', 'e')
      names(my.second.input) <- my.second.input
      selectInput(inputId = 'another.input', label = 'Check this input', multiple = FALSE,
                  choices = my.second.input, selected = 'a')    

    } else{
      return(NULL)
    }
  })
})

shinyApp(ui, server)

The error that happened told you that you're trying to access a reactive value without a reactive context. You were trying to access the input value (which is reactive) outside of a render function or an observe function, which are reactive contexts.

If you don't understand what that means, I highly suggest you read this section on a shiny tutorial I wrote, reactivity 101.

The second issue here was that you were trying to "nest" a render function, which can work but is the wrong way to think about it, and suggests that you may not really grasp the concept of reactivity and render functions fully. Notice that I moved the render function to the outside, that's generally the correct way to program in shiny. If you have a bit of time, I suggest watching Joe Cheng's (the author of shiny) videos "effective reactive programming I and II" from the 2016 shiny conference https://www.rstudio.com/resources/webinars/shiny-developer-conference/