Changing a Shiny app UI based on user input

Employing tools acquired in the previous recipe, you will be able to go quite far exploring Shiny's possibilities.

However, there is a quite advanced topic that was excluded from the previous recipe: UI customization based on user input.

This is an amazing feature, and it is even more amazing if you think you don't have to learn JavaScript or any other language to apply it to your app. Only R code knowledge is needed. Our app will ask for a first question and consequently change the possible answers to a second question.

One last word; our app will be based on the Lord of the Rings characters. I hope you will appreciate this. Now, let's start without any ado; as Samwise Gamgee would say:

"It's the job that's never started as takes longest to finish."

Getting ready

In order to run our Shiny app, we will need to install and load the shiny and shinyBS packages:

Install.packages(c('shiny','shinyBS'))
library(shinyBS)
library(shiny)

Before looking at the actual recipe, I would like to recommend that you read the Developing a single-file Shiny app recipe in this chapter, which will help you gain knowledge of the basic features of the Shiny framework.

How to do it...

  1. Create an app.R file. You just have to create a new R script within your current directory and name it app.R.
  2. Create a ui object:
    ui <- fluidPage()
  3. Create a server object:
    server ← function(input,output) { }
  4. Put input controls into the UI:
      selectInput("first_choice", 
                  label = h1("First Answer a General Question"),
                  choices = list("select","A","B","C"),
                  selected = "select"
      ),
      
      #collapsable panel for second choice
      
      h1("then get into details"),
      
      bsCollapse(
        bsCollapsePanel( title = "details",
                         uiOutput("second_choice")
        ),
        id = "collapser", multiple = FALSE, open = NULL
      ),
      h2("first answer"),
      h3(textOutput("first_answer")),
      h2("second answer"),
      h3(textOutput("second_answer"))

    Within this chunk of code, you should notice collapsible panels have been inserted using the bsCollapse() function made available through the shinyBs package we previously installed.

  5. Put the server logic behind the UI's input control:
     #retrieve selected values and render text from selection
      
      output$first_answer  <- renderText({input$first_choice})
      output$second_answer <- renderText({input$dynamic})
      output$second_choice <- renderUI({
        
        switch(input$first_choice,
               "A" = checkboxGroupInput("dynamic", "Dynamic",
                                        choices = c("Aragon","Frodo"),
                                        selected = "option2"),
               "B" = checkboxGroupInput("dynamic", "Dynamic",
                                        choices = c("Bilbo","Gandalf","Sauron"),
                                        selected = "option2"),
               "C" = checkboxGroupInput("dynamic", "Dynamic",
                                        choices = c("Boromir","Legolas"),
                                        selected = "option2")
               
        )
        
      })

    In this chunk of code, we add server logic to the previously defined UI. You should notice the renderUI() reactive function, which is the actual core of this recipe.

    This function takes input$first_choice as input, which is the first choice performed by the user using control having the first_choice ID (look at the previous step). This choice is used to select one of three cases listed within the switch() function. The output of this function is one of three possible checkboxGroupInput, which are then retrieved in the uiOUtput() UI function (refer to the previous step again).

  6. Add an observer related to the first input:
    observe({
        if (input$first_choice != "select") {
          updateCollapse(session,"collapser",open = c('details'))     
        }
      })

    Observers are special types of reactive function. These functions can be considered always-active sentinels, which look for specific events (here, the value of input$first_choice) and consequently perform some action (here, collapsible panel update).

    The main difference between general reactive functions and observers is that observers do not produce an output value, but just perform an action.

  7. Run the UI and server lines.

    This step involves running the lines of code related to the ui and server objects. It is mandatory in order to make these objects available for the upcoming shinyApp() function.

    You can do this by sourcing your code file:

    source('app.R')
  8. Run your Shiny app:
    shinyApp(ui = ui, server = server)

    This will result in the following app:

    How to do it...

As you can see, after playing for a while with the app, choices within the second input control (then get into details one) will change based on the input of the first choice.

This is exactly what we were looking for: a dynamic UI able to change according to custom behavior.

See also

Shiny apps are a hot topic within the R community, particularly for the opportunity they offer for moving R closer to the data analytics production environment. You can, therefore, find a lot of great material on this topic online.

That said, if you want to deepen you knowledge of Shiny apps, you shouldn't miss visiting the following:

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset