Search code examples
rshinydata.tableflexdashboard

How can I build multiple inputs into my shiny app with both updating and multiple selection?


I am building a flex dashboard / shiny app with a datatable and trying to build in two inputs as selections for this datatable with an "All" choice for each selection. First question is how can I limit the second selection "user" by the selection of the first choice "team"?

Then, using these inputs, I'd like to subset my data to any combination of the two selections ex. Team All, user "Darwin D" would return a single line datatable with his name, team and other metrics to be added etc.

All code for a flex markdown document below:

---
title: "example"
output: 
  flexdashboard::flex_dashboard:
    orientation: columns
    vertical_layout: fill
    runtime: shiny
---

```{r setup, include=FALSE}
library(shiny)
library(shinydashboard)
library(flexdashboard)
library(magrittr)
library(feather)
library(anytime)
library(data.table)
library(DT)
library(datasets)


Name <- c("Allan A","Barbara B","Charles C","Darwin D","Evelyn E","Frank F","Greg G","Hans H")
Team <- c(1,2,3,3,2,1,2,2)
users <- data.frame(Name,Team)
remove(Name,Team)
```



Inputs {.sidebar}
=======================================================================

### Input Variables

```{r global_input}
# input variable to call selection, name of field, selections/options variable
dateRangeInput('dateRange',
     label = 'Date range input: yyyy-mm-dd',
     start = Sys.Date() - 8,
     end = Sys.Date() - 1,
     min = "2013-01-01",
     max = Sys.Date() -1
   )

selectInput("teaminput","Team", c("All",unique(users$Team)))

observe({
    if( input$teaminput == "All" ) {
        subDT <- copy( users )
    } else {
        subDT <- users[ users$Team == input$teaminput, ]
    }

    updateSelectInput(
        "userinput",
        label = "User Name",
        choices = c( "All", unique(subDT$Name ) )
    )
})
```

### Intake Coordinator KPIs

```{r daily_table}
# reactive data object based on inputs above
daily_dt <- reactive({
  if(input$teaminput == "All"){
      subDT
}  else{
    subset(subDT$Team == input$teaminput)
}
  })

# render DT datatable object with sorts/search
renderDataTable(daily_dt())
```

Solution

  • You might want to use 2 reactive, the first one to filter the data.frame by Team, the second to filter the result of the first one by Name :

    ---
    title: "example"
    output: 
      flexdashboard::flex_dashboard:
        orientation: columns
        vertical_layout: fill
        runtime: shiny
    ---
    
    ```{r setup, include=FALSE}
    library(DT)
    
    users <- data.frame(
      Name = c("Allan A","Barbara B","Charles C","Darwin D","Evelyn E","Frank F","Greg G","Hans H"),
      Team = c(1,2,3,3,2,1,2,2), stringsAsFactors = FALSE)
    ```
    
    Inputs {.sidebar}
    =======================================================================
    ### Input Variables
    
    ```{r global_input}
    selectInput("teaminput","Team",c("All", unique(users$Team)), selected="All")
    selectInput("userinput","User Name", c("All", unique(users$Name) ), selected="All")
    
    teamFiltered <- reactive(users[input$teaminput=="All" | users$Team==input$teaminput,])
    
    observe(updateSelectInput(session,"userinput", choices = c("All", unique(teamFiltered()$Name)), selected="All"))
    ```
    
    Results
    =======================================================================
    ### Intake Coordinator KPIs
    
    ```{r daily_table}
    userFiltered <- reactive(teamFiltered()[input$userinput=="All" | teamFiltered()$Name==input$userinput,])
    
    renderDataTable(userFiltered())
    ```