isolate()
is a function that does exactly what is expected; it isolates a piece of code. In a Shiny reactive context, this means that it prevents the execution of a piece of code unless, of course, certain condition is met. The condition that isolate()
takes in order to re-execute the piece of code is, however, not evaluated in the usual way (that is, in the way that returns TRUE
or FALSE
), it evaluates whether the object changes or not.
The object to evaluate the condition that is mostly used within isolate()
is the action button. The actionButton()
function, apart from drawing a button in the interface, creates an object, which is mainly a counter that whenever the button is hit, it increases its value by 1
. It becomes clear then why isolate is used mainly with actionButton()
; it is ideal to isolate a piece of code from the reactive context it is in until a button is hit.
Lastly, isolate()
is a function that can be called only within a reactive context, that is, inside a render-like function (renderPlot()
, for example), a reactive expression (reactive()
), or within observe()
, a function that is covered in this chapter.
In Chapter 5, Shiny in Depth – A Deep Dive into Shiny's World, we had explained a problem that appeared with the use of submitButton()
. Basically, as the button executes all the input changes at the same time, there was no possibility of ticking the box to change the dot colors that displayed the colors menu, select the color, and then hit the button to produce the output. With actionButton()
and isolate()
, it can be specified which input variable changes should be delayed until the button is hit and which ones should be executed immediately.
In this case, the checkbox that made the colors visible should be executed immediately, while the rest of the inputs should change only on the button hit. UI.R
changes only in the input widget that is passed and has both inputId
and label
:
library(shiny) # Starting line shinyUI(fluidPage( # Application title titlePanel("Submit Button Example"), # Sidebar with a numeric input # Sidebar sidebarLayout( sidebarPanel( numericInput("number", "Insert a number:", value = 30, min = 1, max = 50), #Checkbox to select color checkboxInput("selectcolor",label = "Change color"), #Conditional Panel. When the checkbox is ticked, it displays #the radio button options conditionalPanel("input.selectcolor == true", radioButtons("color", "Pick up the color:", c("red", "blue", "green"))), actionButton("run","Apply changes")), #The plot created in server.R is displayed mainPanel( conditionalPanel(condition= "input.number > 0", plotOutput("plot")) ) ) ))
In the following code of server.R
, the change of input$run
is set to be the condition of the output's re-execution:
library(shiny) #initialization of server.R shinyServer(function(input, output) { #Plot generation output$plot <- renderPlot({ #Isolation condition input$run isolate({ if(input$selectcolor){ plot(1/1:input$number, col=input$color) } else { plot(1/1:input$number) } }) }) })
The value of input$run
is a hit counter of actionButton()
. For this reason, whenever the button is hit, the value of input$run
changes and consequently, the code inside isolate()
is executed.
Although from a usability point of view, it would not make much sense, the condition variable to be used along with isolate()
can be anything. The following scripts, for example, create an application where the changes are done whenever the checkbox is ticked/unticked.
This is a standard frontend with a checkbox. The following is the code snippet for UI.R
:
library(shiny) # Starting line shinyUI(fluidPage( # Application title titlePanel("Example 1"), # Sidebar with a numeric input # Sidebar sidebarLayout( sidebarPanel( numericInput("number", "Insert a number:", value = 30, min = 1, max = 50), #Checkbox checkboxInput("selector",label = "Checkbox") ), #The plot created in server.R is displayed mainPanel( plotOutput("plot")) ) ))
In this case, the input$selector
variable changes from TRUE
to FALSE
instead of being an incremental integer. However, the behavior of the isolate()
clause is the same one. This is how server.R
looks like:
library(shiny) #initialization of server.R shinyServer(function(input, output) { #Plot generation output$plot <- renderPlot({ #Isolation condition input$selector isolate({ plot(1/1:input$number)}) }) })
In the preceding example, the plot is only updated if the user ticks/unticks the checkbox.