Reputation: 17
The result page in my program aims to respond differently to the different options the user enters. I feel observeEvent seems relevant but when I wrote this way it only displays the latest observeEvent (which is the female one).
Here is the simplified version of my code:
library(shiny)
ui <- fluidPage(
mainPanel(
tabsetPanel(type = "tabs",
tabPanel("Personal Information",
selectInput(
"gender",
"What is your biological gender?:",
c("--" = "null","male" = "gender1","female" = "gender2")
)
),
tabPanel("Result",
verbatimTextOutput("result")
)
)
)
)
server <- function(input, output) {
#Events
observeEvent(
{input$gender == "gender1"},
output$result <- renderPrint ("You are a male.")
)
observeEvent(
{input$gender == "gender2"},
output$result <- renderPrint ("You are a female.")
)
}
shinyApp(ui, server)
Upvotes: 1
Views: 2363
Reputation: 9809
Or you could place all in 1 observeEvent and depending on the condition, change the desired text and use it then in a renderPrint function like this:
server <- function(input, output) {
observeEvent(input$gender, {
if (input$gender == "gender1") {
txt <- "You are a male."
} else if (input$gender == "gender2") {
txt <- "You are a female."
} else {
txt <- NULL
}
output$result <- renderPrint(txt)
})
}
Allthough i would also favor the solution from @divibisan.
You could although use a reactiveValue, where the text is stored. In this way, you can access the text everywhere in your server function and you dont have to nest the rnderPrint function inside the observeEvent. This is what you would do with the server function:
server <- function(input, output) {
reactTXT <- reactiveValues(txt=NULL)
observeEvent(input$gender, {
if (input$gender == "gender1") {
txt <- "You are a male."
} else if (input$gender == "gender2") {
txt <- "You are a female."
} else {
txt <- NULL
}
reactTXT$txt <- txt
})
output$result <- renderPrint({
reactTXT$txt
})
}
First you create the reactiveValue reactTXT
. In the observeEvent you assign the text to the reactiveValue with reactTXT$txt <- txt
. And in the renderPrint function you just pass the reactiveValue reactTXT$txt
to print it.
Upvotes: 0
Reputation: 12165
You should use one observeEvent
that triggers whenever input$gender
changes. Then have a conditional inside that which determines what value to return. You actually don't need the observeEvent
at all, since any reactive expression (including a renderPrint
) will update if any reactive values in it are invalidated. So the best way to do what you want is to replace bout observeEvent
functions with the below:
output$result <- renderPrint({
if (input$gender == 'gender1') {
return("You are a male.")
} else if (input$gender == 'gender2') {
return("You are a female.")
}
})
The difference with using an event
function vs a render*
is that the code block is considered to be in an isolate
block and only the change of the eventExpr
will trigger the code to run. That's good if you want to make the code only run when an Update button is pressed, but if you want it to be reactive to changing values (like in your example) you shouldn't use an event
function.
Also, you are strongly encouraged not to nest reactive expressions as you do above. If you must have an event
function drive a renderPrint
function (as in your example), the reccomended way of doing that is with an eventReactive
:
gender_input <- eventReactive(input$update, {
if (input$gender == 'gender1') {
return("You are a male.")
} else if (input$gender == 'gender2') {
return("You are a female.")
}
})
output$result <- renderPrint({gender_input()})
Upvotes: 1