Search code examples
rshinydplyrreactivemagrittr

Use dplyr conditional filter in reactive function in Shiny


I'm using dplyr in a Shiny app reactive function. I have an interactive widget in the UI that users can use to select status and data will be shown based on selected status. However I also want to give the option to show everything, which is a status that I have called 'All'.

I know how to achieve this without dplyr:

library(tibble)
library(shiny)

# Test Data -----
test_data <- tribble(
  ~id, ~status,
  1, 'active',
  2, 'inactive',
  3, 'test'
)

# Ui ----
ui = fluidPage(
  selectInput("status", "Choose a status:",
              choices = list("All","active","inactive","test")
  ),
  tableOutput('result')
)

# Server ----
server = function(input, output) {

  table <- reactive({
    if(input$status != 'All')
    {
      test_data <- test_data[test_data$status == input$status,]
    } else {
      test_data
    }
  })

  output$result <- renderTable(table(), rownames = FALSE)

}

# App ---
shinyApp(ui = ui, server = server)

However, I would like to be consistent with the rest of my code and use dplyr. Is there a way to do something like the below?

library(tibble)
library(dplyr)
library(shiny)

# Test Data -----
test_data <- tribble(
  ~id, ~status,
  1, 'active',
  2, 'inactive',
  3, 'test'
)

# Ui ----
ui = fluidPage(
  selectInput("status", "Choose a status:",
              choices = list("All","active","inactive","test")
  ),
  tableOutput('result')
)

# Server ----
server = function(input, output) {

  table <- reactive({
    test_data %>%
      filter(ifelse(input$status != 'All', status == input$status, status == ***pass***))
  })

  output$result <- renderTable(table(), rownames = FALSE)

}

# App ---
shinyApp(ui = ui, server = server)

In other words, is there a way to use ifelse inside filter function to not filtering under a certain condition?

Thanks!


Solution

  • I do not think that is possible. You could do as follows:

    if(input$status!="All")
      test_data %>% filter(status %in% input$status)
    else
      test_data
    

    So you only filter if the input is not "All". If you have a very long dplyr chain and you do not want to break it into pieces, you could also do:

    if(input$status=="All")
      my_filter=unique(test_data$status)
    else
      my_filter = input$status
    
    test_data %>%
      filter(status %in% my_filter) %>%
      ..... %>%
      .....
    

    Hope this helps.