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."
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.
app.R
file. You just have to create a new R script within your current directory and name it app.R
.ui
object:ui <- fluidPage()
server
object:server ← function(input,output) { }
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.
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).
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.
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')
shinyApp(ui = ui, server = server)
This will result in the following app:
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.
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:
In this website, you can find everything, from introductory tutorials for beginners to detailed articles on advanced topics.