Reputation: 23
Situation
I would like to use multiple reactive values (in example ab and cd) to create a new one (in example merge). It is possible that only some are available (in example ab or cd or both), because not every category available needs to be calculated. The idea is to check for the existence of the according reactive value and, depending on it, add or skip the according category.
Approaches not working
Proposed methods for checking/validating reactive values include req()
, validate()
, need()
and isTruthy()
, but these generate an error, not an (to my knowledge) usable return like TRUE or FALSE. exists()
seems not to be able to handle an non-existing reactive value, even though I would think it would be the ideal function (giving TRUE or FALSE depending on the existence of a variable).
Edit 1: is.null()
does not work either. When the according reactive value is not existent yet, the function is exited as with the other approaches. To clarify: It seems each time a non-existent reactive value is called the function is exited. Edit 1
Question
Is there a possibility to check for the existence of a reactive value in shiny, with result, not an error (or an idea for a workaround)?
Please see the code, in this example with exists()
.
ui <- fluidPage(
# inputs first reactive value
sliderInput("a",
"a",
1, 10, 2 ,1),
sliderInput("b",
"b",
1, 10, 4 ,1),
# calculate first reactive value
actionButton("ab", "calc a + b"),
# inputs second reactive value
sliderInput("c",
"c",
1, 10, 6 ,1),
sliderInput("d",
"d",
1, 10, 8 ,1),
# calculate second reactive value
actionButton("cd", "calc c + d"),
# outputs
verbatimTextOutput("result_ab"),
verbatimTextOutput("result_cd"),
verbatimTextOutput("result_merge")
)
server <- function(input, output, session) {
# outputs
output$result_ab <- renderPrint(ab())
output$result_cd <- renderPrint(cd())
output$result_merge <- renderPrint(merge())
# calculations
ab <- eventReactive(input$ab,{
ab <- input$a + input$b
ab
})
cd <- eventReactive(input$cd,{
cd <- input$c + input$d
cd
})
# merge of existing values
merge <- reactive({
merge <- c() # empty vector to be filled up
if(exists(ab())){
merge <- c(merge, ab())
}
if(exists(cd())){
merge <- c(merge, cd())
}
merge
})
}
shinyApp(ui, server)
Thank you!
Upvotes: 2
Views: 556
Reputation: 84519
I don't know the correct wording, but roughly speaking, since merge()
depends on ab()
and cd()
, it is "invalidated" (it does not run) as long as ab()
or cd()
do not "exist". At least this is what I think.
You can use reactive values and observers instead:
library(shiny)
ui <- fluidPage(
# inputs first reactive value
sliderInput("a",
"a",
1, 10, 2 ,1),
sliderInput("b",
"b",
1, 10, 4 ,1),
# calculate first reactive value
actionButton("ab", "calc a + b"),
# inputs second reactive value
sliderInput("c",
"c",
1, 10, 6 ,1),
sliderInput("d",
"d",
1, 10, 8 ,1),
# calculate second reactive value
actionButton("cd", "calc c + d"),
# outputs
verbatimTextOutput("result_ab"),
verbatimTextOutput("result_cd"),
verbatimTextOutput("result_merge")
)
server <- function(input, output, session) {
# outputs
output$result_ab <- renderPrint(ab())
output$result_cd <- renderPrint(cd())
output$result_merge <- renderPrint(merge())
# calculations
ab <- reactiveVal(NULL)
cd <- reactiveVal(NULL)
observeEvent(input$ab,{
ab(input$a + input$b)
})
observeEvent(input$cd,{
cd(input$c + input$d)
})
# merge of existing values
merge <- reactive({
merge <- c() # empty vector to be filled up
if(!is.null(ab())){
merge <- ab()
}
if(!is.null(cd())){
merge <- c(merge, cd())
}
merge
})
}
shinyApp(ui, server)
Upvotes: 1
Reputation: 10365
As long as your reactive
is not expected to return NULL
at some point, you can check if the return value of a reactive
is not NULL
:
merge <- reactive({
merge <- c() # empty vector to be filled up
if(!is.null(ab())){
merge <- c(merge, ab())
}
if(!is.null(cd())){
merge <- c(merge, cd())
}
merge
})
Upvotes: 0