Home > database >  How to conditionally render output in R shiny?
How to conditionally render output in R shiny?

Time:08-06

In running the below demo code, if the user selects to view two rows of data via the radio button, I would like to show the output of renderPrint({dat()}) in the 2nd panel "choices2" (whereby the Values in the above dataframe are multiplied by 2), otherwise show the output of renderText("Select view 2 rows for results") in that same second panel "choices2". They both work fine when run on their own, but when I combine them into an conditional within an observeEvent() (shown in commented-out lines below), the App crashes. What am I doing wrong here?

I'm trying to better understand reactivity and observers. Maybe an observer isn't even required here, I don't know.

Demo code:

library(shiny)

data <- 
  data.frame(
    ID = c(1,1,1,2,2,2),
    Period = c(1, 2, 3, 1, 2, 3),
    Values = c(5, 10, 15, 0, 2, 4)
  )

ui <- fluidPage(
  
  h5(strong("Base data frame:")), 
  tableOutput("data"),
  radioButtons(inputId = "viewData",
               label = "View from original dataframe:",
               choiceNames = c('All','First 2 rows'),
               choiceValues = c('All','Two rows'),
               selected = 'All',
               inline = TRUE
  ),
  h5(strong("Reactive results of radio button:")), 
  verbatimTextOutput("choices"),
  h5(strong("Multiply above values by 2 when viewing 1st 2 rows:")),
  verbatimTextOutput("choices2")
)

server <- function(input, output, session) {
  
  output$data <- renderTable(data)
  
  rv <- reactiveValues(choices=c())
  
  observeEvent(input$viewData, {
    if(input$viewData == 'Two rows'){rv$choices <- data[1:2,]} 
    else {rv$choices <- data}
  })
  
  output[["choices"]] <- renderPrint({ rv$choices })
  
  dat <- reactive({
    dat <- rv$choices
    dat[, 3] <- 2 * dat[, 3]
    dat
  })
  
  output[["choices2"]] <- 
    renderPrint({dat()}) # this runs fine on outs own
    # renderText("Select view 2 rows for results") # this runs fine on outs own
  
  # The below observer doesn't work:  
  # observeEvent(input$viewData, { 
  #   if(input$viewData == 'Two rows'){renderPrint({dat()})}
  #   else {renderText("Select view 2 rows for results")}
  # })
    
}
shinyApp(ui, server)

CodePudding user response:

Maybe you can do the check inside the renderPrint:

  output[["choices2"]] <- renderPrint({
    if(input$viewData == 'Two rows'){
      dat()
    }
    else{
      cat("Select view 2 rows for results")
    }
  })

CodePudding user response:

Extending the answer from @PorkChop, use knitr::combine_words to get rid of [1] in output.

output[["choices2"]] <- renderPrint({
    if(input$viewData == 'Two rows'){
      dat()
    }
    else{
      knitr::combine_words("Select view 2 rows for results")
    }
  })

CodePudding user response:

You can use uiOutput(), which creates the UI based on a condition. In pseudocode (e.g. you will need to adapt it a bit):

# ui 
uiOutput("choices2")

# server
output$choices2 <- renderUI({
     if( your_condition_to_test ){
        h2("Select view 2 rows for results")
     } else {
        verbatimTextOutput(dat())
     }
  })
  • Related