How to subset data based on inputs from renderUI

81 Views Asked by At

I am trying to subset my data based on inputs from renderUI. This data would then be passed to further work in an observe chunk.

Below is an example, where there is an issue with the server code. I am having difficulties with the code recognising the input to an if clause - or more accurately it starts of NULL and then "Every row" from the input is recognised. If I uncomment carbData() in observe below I get the following error. Also receive a similar error if I move the subset inside the observe environment.

Listening on http://127.0.0.1:7400
NULL ### from check()
Warning: Error in if: argument is of length zero
61: reactive:carbData [#9]
45: carbData
44: [#17]
1: runApp

Is this due to some delayed evaluation from using renderUI? If so, or otherwise how do I fix it please?

My code:

server <- function(input, output) {

    amData <- reactive({ mtcars[am %in% input$am, ] }) 
    output$gear <- renderUI({ selectInput("Gear", "GEAR", 
                                choices=unique(amData()[, "gear"]), selected=4 ) })
    
    gearData <- reactive({ amData()[gear %in% input$Gear, ] }) 
    output$carb <- renderUI({ selectInput("Carb", "CARB", 
                                choices=c("Every row", unique(gearData()[, "carb"])), selected="Every row") })
    
    carbData <-  reactive({ if(input$Carb %in% "Every row") gearData() else gearData()[ carb %in% input$Carb ] }) #### PROBLEM
    
    # Some text where it can be seen that input$Carb  is initially NULL
    check <-  reactive({ p <- input$Carb; print(p) }) 
    
    observe({ 
      check(); 
        
      # problems with if clause in both of these:
      # carbData() 
        
      # Moving the data subset inside `observe` doesn't help
      # df <- if(input$Carb %in% "Every row") gearData() else gearData()[ carb %in% input$Carb ]
      })
}

And the rest of the code to allow it to run:

library(shiny)
library(shinydashboard)

data(mtcars); data.table::setDT(mtcars)

ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(
   sidebarMenu(
       selectInput("am", "AM", unique(mtcars$am), selected = "0"),
       uiOutput("gear"),
       uiOutput("carb")
       )),
  dashboardBody())

runApp(shinyApp(ui, server))
1

There are 1 best solutions below

0
On

I'm a bit uncertain whether this question is closed. However, I took the luxury of editing your codes to locate the problem.

I used tibbles instead of data.table as I am not familiar with the syntax. So far @stefan is absolutely correct, req(input$Carb) will relieve you of your troubles.

The reason that gear %in% input$Gear works, and input$Carb %in% "Every row" does not, is that the reactive-hierachy does not favor input$Carb, and as it is null at startup, you are essentially testing NULL %in% "Every Row". Where as gear exists by construction at app start up.

This is not, as Im certain that you are aware of, the same as input$Carb %in% "NULL", or NULL for that matter.

This is your code that I played around with,

server <- function(input, output) {
        amData <- reactive({
                mtcars %>% filter(am %in% input$am)
                
                
        })
        
        gearData <- reactive({
                amData() %>% filter(gear %in% input$Gear)
                
                
        })
        
        
        output$gear <- renderUI({
                selectInput("Gear",
                            "GEAR",
                            choices = unique(amData()[, "gear"]),
                            selected = 4)
        })
        
        
        output$carb <- renderUI({
                selectInput(
                        "Carb",
                        "CARB",
                        choices = c("Every row", unique(gearData()[, "carb"])),
                        selected = "Every row"
                )
        })
        
        carbData <-
                reactive({
                        
                        req(input$Carb)
                        
                        if (input$Carb %in% "Every row")
                                gearData()
                        else
                                gearData() %>% filter(carb %in% input$Carb)
                }) #### PROBLEM
        
        # Some text where it can be seen that input$Carb  is initially NULL
        check <-  reactive({
                p <- input$Carb
                print(p)
        })
        
        observe({
                check()
                
                
                # problems with if clause in both of these:
                carbData()
                
        })
}