Lokesh Mano
NBIS, SciLifeLab
14-Apr-2025
Functions with reactive context
reactive()
: Defines an expressionreactiveVal()
: Defines single valuereactiveValues()
: Defines a list of valuesRegular function fn <- function()
: Runs wherever it is is used
Reactive function fn <- reactive()
: Runs only when input changes
Reactive values cannot be accessed outside a reactive context
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| components: [editor, viewer]
shinyApp(
ui = fluidPage(
numericInput("num", "Enter number",
value = 1),
textOutput("result")
),
server = function(input, output) {
val = input$num^2
output$result <- renderText({
paste("Squared number is:", val)
})
}
)
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| components: [editor, viewer]
shinyApp(
ui=fluidPage(
numericInput("num_input",label="Observations",value=50),
textOutput("text_output")),
server=function(input,output) {
output$text_output <- renderText({
mean(rnorm(input$num_input))
})
})
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| components: [editor, viewer]
shinyApp(
ui=fluidPage(
numericInput("num_input",label="Observations",value=50),
textOutput("text_output1"), textOutput("text_output2")),
server=function(input,output) {
output$text_output1 <- renderText({
mean(rnorm(input$num_input))
})
output$text_output2 <- renderText({
mean(rnorm(input$num_input))
})
})
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| components: [editor, viewer]
shinyApp(
ui=fluidPage(
numericInput("num_input",label="Observations",value=50),
textOutput("text_output1"), textOutput("text_output2")),
server=function(input,output) {
rand <- function(x) rnorm(x)
output$text_output1 <- renderText({
mean(rand(input$num_input))
})
output$text_output2 <- renderText({
mean(rand(input$num_input))
})
})
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| components: [editor, viewer]
shinyApp(
ui=fluidPage(
numericInput("num_input",label="Observations",value=50),
textOutput("text_output1"), textOutput("text_output2")
),
server=function(input,output) {
rand <- reactive({ rnorm(input$num_input) })
output$text_output1 <- renderText({
mean(rand())
})
output$text_output2 <- renderText({
mean(rand())
})
})
reactVal()
reactValues()
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| components: [editor, viewer]
shinyApp(
ui = fluidPage(
actionButton("add","Add"),
actionButton("subtract","Subtract"),
textOutput("counter")
),
server = function(input, output) {
reactive_values <- reactiveValues(counter = 0)
observeEvent(input$add, {
reactive_values$counter <- reactive_values$counter + 1
})
observeEvent(input$subtract, {
reactive_values$counter <- reactive_values$counter - 1
})
output$counter <- renderText({
reactive_values$counter
})
}
)
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| components: [editor, viewer]
shinyApp(
ui = fluidPage(
h3("Temperature Converter"),
numericInput("celsius", "Degrees Celsius:", value = 0),
actionButton("btn_go", "Go!"),
textOutput("fahrenheit")
),
server = function(input, output) {
evr <- eventReactive(input$btn_go, {
paste(input$celsius, "°C is ", (input$celsius * 9/5) + 32, " °F")
})
output$fahrenheit <- renderText({
evr()
})
#output$fahrenheit <- renderText({
# paste(input$celsius, "°C is ", (input$celsius * 9/5) + 32, " °F")
# }) |>
# bindEvent(input$btn_go)
})
Reactive functions that automatically re-executes whenever its dependencies change. Usually used for side-effects rather than returning a value.
observe()
Doesn’t return a value. Constantly runs as long as the app is alive.
observeEvent()
Similar to observe()
, but only re-executes on specific event (like a button click). Doesn’t return a value.
eventReactive()
Similar to observeEvent()
, but returns a value.
bindEvent()
Bind an action to a specific event. Similar to observeEvent()
, but allows for the event to be determined dynamically. Links an input (like a button) to an output and ensures that reactive expressions are only updated when bound event is triggered.
observe({})
monitors for a conditional changeserver=function(input,output,session) {
observe({
if(something) {
updateSelectInput(session,"select-input",label="selectInput",choices=c("D","E","F"))
updateNumericInput(session,"numeric-input",label="numericInput",value=10,min=1,max=10)
updateSliderInput(session,"slider-input",label="sliderInput",value=8,min=1,max=10)
}
})
}
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| components: [editor, viewer]
shinyApp(
ui = fluidPage(
selectInput("data", "Choose a dataset:", choices = c("mtcars", "iris", "faithful")),
selectInput("variable", "Choose a variable:", choices = names(mtcars))
),
server = function(input, output, session) {
dataset <- reactive({
switch(input$data,
"mtcars" = mtcars,
"iris" = iris,
"faithful" = faithful)
})
observe({
updateSelectInput(session,"variable",choices=names(dataset()))
})
}
)
Input function | Update function |
---|---|
checkboxInput() |
updateCheckboxInput() |
checkboxGroupInput() |
updateCheckboxGroupInput() |
radioButtons() |
updateRadioButtons() |
dateInput() |
updateDateInput() |
dateRangeInput() |
updateDateRangeInput() |
fileInput() |
|
numericInput() |
updateNumericInput() |
sliderInput() |
updateSliderInput() |
textInput() |
updateTextInput() |
textAreaInput() |
updateTextAreaInput() |
passwordInput() |
|
selectInput() |
updateSelectInput() |
actionButton() |
|
submitButton() |
|
tabsetPanel() |
updateTabsetPanel() |
navbarPage() |
updateNavbarPage() |
validate()
can be used to check inputvalidate()
using need()
shinyApp(
ui=fluidPage(
selectInput("data_input",label="Select data",
choices=c("","mtcars","faithful","iris")),
tableOutput("table_output")
),
server=function(input, output) {
getdata <- reactive({
validate(need(try(input$data_input),"Please select a data set"))
get(input$data_input,'package:datasets')
})
output$table_output <- renderTable({head(getdata())})
})
validate()
using custom functionvalfn <- function(x) if(is.null(x) | is.na(x) | x=="") return("Input data is incorrect.")
shinyApp(
ui=fluidPage(
selectInput("data_input",label="Select data",
choices=c("","mtcars","faithful","iris")),
tableOutput("table_output")
),
server=function(input,output) {
getdata <- reactive({
validate(valfn(try(input$data_input)))
get(input$data_input,'package:datasets')
})
output$table_output <- renderTable({head(getdata())})
})
shiny::req()
checks input variable and silently stops executiondownloadHandler()
functionshinyApp(
ui=fluidPage(
selectInput("data_input",label="Select data",
choices=c("mtcars","faithful","iris")),
textOutput("text_output"),
downloadButton("button_download","Download")
),
server=function(input, output) {
getdata <- reactive({ get(input$data_input, 'package:datasets') })
output$text_output <- renderText(paste0("Selected dataset: ",input$data_input))
output$button_download <- downloadHandler(
filename = function() {
paste0(input$data_input,".csv")
},
content = function(file) {
write.csv(getdata(),file,row.names=FALSE,quote=F)
})
})
shinyApp(
ui=fluidPage(
selectInput("data_input",label="Select data",
choices=c("mtcars","faithful","iris")),
textOutput("text_output"),
plotOutput("plot_output",width="400px"),
downloadButton("button_download", "Download")
),
server=function(input, output) {
getdata <- reactive({ get(input$data_input, 'package:datasets') })
output$text_output <- renderText(paste0("Selected dataset: ",input$data_input))
output$plot_output <- renderPlot({hist(getdata()[, 1])})
output$button_download <- downloadHandler(
filename = function() {
paste0(input$data_input,".png")
},
content = function(file) {
png(file)
hist(getdata()[, 1])
dev.off()
})
})
Slide inspirations: Roy Francis (NBIS, RaukR2024)