KLDavenport
KLDavenport

Reputation: 679

ReactiveUI based on a ReactiveUI Issues

My code is below and the demo site is here: http://glimmer.rstudio.com/kdavenport/test1/

The first input (dropdown) loads a dataframe defined in global.R

The second input (dropdown) filters this dataframe by the "Service" column of the df

The third input (checkboxes) filters the dataframe further by the "Round" column of df

The problem is that all checkboxes available for the dataframe at step one are shown rather than the checkboxes available after filtering by "Service" in step 2. Below I have 1. clientData > serviceFiltered_clientData > roundFiltered_clientData

shinyServer(function(input, output) {

  # First UI input (Service column) filter clientData 
  output$serviceControls <- renderUI({
    if (is.null(clientData()))
      return("No client selected")
    selectInput("service_select", 
                "Choose Service:", 
                choices = as.character(levels(clientData()$Service.Name)),
                selected = input$service_select
    )
  })

  # Second UI input (Rounds column) filter service-filtered clientData  
  output$roundControls <- renderUI({
    if (is.null(serviceFiltered_clientData()))
      return("No service selected")
    checkboxGroupInput("round_select", 
                       "Choose Round:", 
                       choices = as.character(levels(serviceFiltered_clientData()$Round)))
  })  

  # First data load (client data)
  clientData <- reactive({
    if (is.null(input$client_select))
      return(NULL)
    get(input$client_select)
  })

  # Second data load (filter by service column)
  serviceFiltered_clientData <- reactive({
    dat <- clientData()
    if (is.null(dat))
      return(NULL)
    if (!is.null(input$service_select)) # !
      dat <- dat[dat$Service.Name %in% input$service_select,]
    return(dat)
  })

  # Third data load (filter by round column)
  roundFiltered_clientData <- reactive({
    dat <- serviceFiltered_clientData()
    if (is.null(dat))
      return(NULL)
    if (!is.null(input$round_select)) # !
      dat <- dat[dat$Round %in% input$round_select,]
    return(dat)
  })


  # Audit count panel
  output$auditsCount <- renderText({
    if (is.null(roundFiltered_clientData()))
      return("No client selected")
    paste("Total Audits:",nrow(roundFiltered_clientData()))
  })

Upvotes: 2

Views: 437

Answers (2)

KLDavenport
KLDavenport

Reputation: 679

The reactivity daisy chaining was working all along, the issue was with the "Round" column being loaded as a factor, and factors persist as a dataframe attribute after subsetting. Thus I needed to use droplevels() after subsetting the data. I added dat <- droplevels(dat) below:

  # Second data load (filter by service column)
  serviceFiltered_clientData <- reactive({
    dat <- clientData()
    if (is.null(dat))
      return(NULL)
    if (!is.null(input$service_select)) # !
      dat <- dat[dat$Service.Name %in% input$service_select,]
    dat <- droplevels(dat) # This is what fixed it
    return(dat)
  })

Upvotes: 2

Ram Narasimhan
Ram Narasimhan

Reputation: 22506

You can fix this by grouping checkboxInputs and using conditionalPanel to selectively show and hide as appropriate.

Steps:

  1. For each case of filtering by service, make a dynamic list of which checkboxes make sense.
  2. Create a condition, based on your dropdown #2 (Service) selection made.
  3. Show only the only the checkbox choices that pass the condition.

Pseudocode

# Only show this panel if a certain Service is selected
      conditionalPanel(
         condition = "input.service.option == 'filter2'",
         checkboxInput(inputId = "opt.col1", label = "label1", value = FALSE),
         checkboxInput(inputId = "opt.col3", label = "label3", value = FALSE),
         )

See this example by the RStudio folks, and the accompanying code. (Esp. the part of the code in UI.R where multiple conditionalPanel's are used.)

Upvotes: 1

Related Questions