rshiny

How to display data table in r shiny with selectInput(multiple = T)?


I would like to allow multiple selection in my shiny app, and display the filtered dataset. The code is as below:

library(shiny)
library(ggplot2)  
library(dplyr)  

result_table  = mtcars

fluidPage(
  tabsetPanel(
    tabPanel("Import data",
      titlePanel("Test"),
      
      # Create a new Row in the UI for selectInputs
      fluidRow(
        column(4,
               selectInput("cyl",
                           "cyl:",
                           c("All",
                             unique(as.character(result_table$cyl)))
                          )
        ),
        column(4,
               selectInput("vs",
                           "vs:",
                           c("All",
                             unique(as.character(result_table$vs))),
                           multiple = T)
        ),
        
      ),
      # Create a new row for the table.
      DT::dataTableOutput("table")
    ),
    tabPanel("test2",
      titlePanel("test"),
      
      # Create a new Row in the UI for selectInputs
      fluidRow(
        column(4,
               selectInput("cyl",
                           "cyl:",
                           c("All",
                             unique(as.character(result_table$cyl)))
                          )
        ),
        column(4,
               selectInput("vs",
                           "vs:",
                           c("All",
                             unique(as.character(result_table$vs))),
                           multiple = T)
        ),
      )
   )
 )
)


# Load the ggplot2 package which provides
# the 'mpg' dataset.
library(ggplot2)

function(input, output) {
  
  # Filter data based on selections
  output$table <- DT::renderDataTable(DT::datatable({
    data <- result_table 
    if (input$cyl!= "All") {
      data <- data[data$cyl== input$cyl,]
    }
    if (!(input$vs%in%  "All")) {
      data <- data[(data$vs%in% input$vs),]
    }
    data
  }))
  
}

When I run the code, the following error popped up: enter image description here

I suspected that the error appeared because of if function in the server side...But I cannot figure out the reason. Maybe the format of input is not the same as data?

Please give me some suggestions. Thank you.


Solution

  • There are two issues with your code. First, when using multiple=TRUE the selected= argument defaults to no value. That's why you an error as input$vs is NULL when you start your app. To prevent that set a selected value or account for the case of a NULL value in your server. Second, all input ids have to be unique, whereas you used the same ids for the selectInputs in both tabPanels. Hence, I renamed them to XXX2.

    library(shiny)
    
    result_table <- mtcars
    
    ui <- fluidPage(
      tabsetPanel(
        tabPanel(
          "Import data",
          titlePanel("Test"),
    
          # Create a new Row in the UI for selectInputs
          fluidRow(
            column(
              4,
              selectInput(
                "cyl",
                "cyl:",
                c(
                  "All",
                  unique(as.character(result_table$cyl))
                )
              )
            ),
            column(
              4,
              selectInput("vs",
                "vs:",
                c(
                  "All",
                  unique(as.character(result_table$vs))
                ),
                selected = "All",
                multiple = TRUE
              )
            ),
          ),
          # Create a new row for the table.
          DT::dataTableOutput("table")
        ),
        tabPanel(
          "test2",
          titlePanel("test"),
          fluidRow(
            column(
              4,
              selectInput(
                "cyl2",
                "cyl:",
                c(
                  "All",
                  unique(as.character(result_table$cyl))
                )
              )
            ),
            column(
              4,
              selectInput("vs2",
                "vs:",
                c(
                  "All",
                  unique(as.character(result_table$vs))
                ),
                selected = "All",
                multiple = TRUE
              )
            ),
          )
        )
      )
    )
    
    server <- function(input, output) {
      # Filter data based on selections
      output$table <- DT::renderDataTable(DT::datatable({
        data <- result_table
        if (input$cyl != "All") {
          data <- data[data$cyl == input$cyl, ]
        }
        if (!(input$vs %in% "All")) {
          data <- data[data$vs %in% input$vs, ]
        }
        data
      }))
    }
    
    shinyApp(ui, server)
    #> 
    #> Listening on http://127.0.0.1:8331