0

I am creating a table in which I want users to have the ability to first filter the data with widgets to reduce the dataset, but still want users to be able to use the built-in DT filters to further reduce the data. However, when taking this approach I find that the built-in filters still contain values present in the original dataset which are not actually present in the data being passed along to be rendered.

For example in this case only 'setosa' and 'versicolor' are included in the table, but 'virginica' is still an option in the built-in filter.

Issue Example Image

Is there a way to make it so the built in filter only includes choices that are present in the input dataset?

Here is example code demonstrating the issue:

##### Load Libraries #####
library(shiny)
library(shinyWidgets)
library(shinythemes)
library(DT)
library(shinyBS)
library(rgdal)
library(tidyverse)
library(shinyjs)

ui <- fluidPage(
  mainPanel(
    pickerInput("SpeciesPick","Select Species",choices=c("setosa","versicolor","virginica"),multiple=TRUE),
    div(DT::dataTableOutput("Table1"),filter="top")
    
  )
)

server <- function(input, output) {
  
  iris1<-reactive(iris[,])
  iris2<-reactive({iris1()%>%filter(Species%in%input$SpeciesPick)})
  
  #### Datatable 1 #####
  
  output$Table1<-DT::renderDT(
    iris2(),extensions=c('Buttons','Select','Scroller'),
    options=list(
      scrollX=TRUE,
      scrollY=400,
      scroller=TRUE,
      select=list(style='os',items='row'),
      dom='Blfrtip',
      buttons = list(list(extend='selectAll',className='selectAll',
                          text="Select All Visible",
                          action=DT::JS("function () {
                            var table = $('#Table1 table.dataTable').DataTable();
                            table.rows({ search: 'applied'}).deselect();
                            table.rows({ search: 'applied'}).select();
            }")
      ), list(extend='selectNone',className='selectNone',
              text="Deselect All Visible",
              action=DT::JS("function () {
                            var table = $('#Table1 table.dataTable').DataTable();
                            table.rows({ search: 'applied'}).select();
                            table.rows({ search: 'applied'}).deselect();

            }")
      ),'selectAll','selectNone','copy','csv')),
    selection='none',
    class="display nowrap compact",
    filter="top",
    server = FALSE
  )
}

shinyApp(ui = ui, server = server)

1 Answers1

0

That's because iris$Species is a factor and the DT filter uses the levels of this factor, which still are setosa, virginica and versicolor after the dplyr filtering, even though some of them have 0 occurence. To drop the levels with 0 occurence, use the droplevels function:

iris2 <- reactive({
  droplevels(iris1() %>% filter(Species %in% input$SpeciesPick))
})
Stéphane Laurent
  • 75,186
  • 15
  • 119
  • 225