Advanced Inputs
Reactive Expressions
Previously, we have seen the case of input being used to directly create outputs. However, there is third tool in the Shiny toolkit and it is called reactive expressions. Reactive expressions are useful because they take inputs and produce outputs and they cache, or store, their output. This can be very useful for three reasons:
- When a step is present multiple times in your code and this step that is either computationally intensive or requires interacting with outside databases, Shiny will only need to carry out the task once rather than each time the process is called since the output will be cached for future uses
- It makes your code cleaner because you only need to maintain the code for a repetitive step in a single place
- They are needed to use action buttons (discussed in the next section)
Below we see relationship between input and output that we have seen up to this point:
As we see once we add a reactive expression, it functions as a intermediary between inputs and outputs.
When we use a reactive expression, we will wrap it within a reactive() function. We will use a reactive() function in the next section when we use an action button.
Note: You can also have multiple reactive expressions that connect to each other in between inputs and outputs.
Isolate
In Shiny, you may find that you will want to limit the reactivity as we did in the previous example. However, you might want only partial reactivity and this is where the isolate() feature can be quite helpful. You can create a non=-reactive scope around an expression using isolate. The syntax for using isolate() is:
isolate(<non_reactive_expression>)
We can create a similar app to the one above but edit the code to use isolate. In this example, we will see that the first slider is completely reactive, however the second slider is only reacts once the action button has been clicked:
library(shiny)
ui <- fluidPage(
sliderInput("slider_input_1", "Select a number", value = 5, min = 1, max = 10),
sliderInput("slider_input_2", "Select a number", value = 5, min = 1, max = 10),
actionButton("calculate", "Multiply!"),
textOutput("product")
)
server <- function(input, output) {
output$product <- renderText({
input$calculate
input$slider_input_1 * isolate(input$slider_input_2)
})
}
shinyApp(ui = ui, server = server)
This app would look like:
Note: If we had used
isolate(input$slider_input_1 * input$slider_input_2)instead ofinput$slider_input_1 * isolate(input$slider_input_2), then this app would function similarly to the app from the previous section since there are now two sliders’ widget inputs are within theisolate()function.
Exercise
Create an app that asks the user Yes or No if they know any programming languages. If they do, provide a handful of progrmaming languages in a checkbox group. Once the user has made their selection, allow to hit an action put to display the languages that they selected. The app should look like:
library(shiny)
ui <- fluidPage(
radioButtons("radio_button_input", "Do you know any programming languages?", choices = c("No", "Yes")),
conditionalPanel(
condition = "input.radio_button_input == 'Yes'",
checkboxGroupInput("checkbox_group_language_input", "Which programming languages do you know?", choices = c("R", "Perl", "Python", "Ruby", "C++"), inline = TRUE),
),
actionButton("languages_action_button", "Submit!", class = "btn-primary"),
textOutput("languages")
)
server <- function(input, output) {
output$languages <- renderText({
input$languages_action_button
isolate(input$checkbox_group_language_input)
})
}
shinyApp(ui = ui, server = server)