Search code examples
rshinydatatabledtpickerinput

How to select rows and columns and filter with DT in Shiny?


I am trying to create a Shiny app capable to select rows and columns depending on user's choice. For selecting columns I use pickerInput and for selecting rows the extension "Select" and more options that you can see in the code (I saw this post that it worked perfectly.)

The thing is that I get this warning and I think that it is not compatible the type of selections. I am afraid that something that I am not seeing could produce more errors.

Warning: The Select extension is not able to work with the server-side processing mode properly. It's recommended to use the Select extension only in the client-side processing mode (by setting server = FALSE in DT::renderDT()) or use DT's own selection implementations (see the selection argument in ?DT::datatable).

On the other hand, I don't know how to hide the "Selection Input" from `pickerInput" and the action button when I select "rows".

This is the code:

    library(shiny)
    library(shinyWidgets)
    library(dplyr)

ui <- fluidPage(
  
  # Application title
  titlePanel("Old Faithful Geyser Data"),
  
  # Sidebar with a slider input for number of bins 
  sidebarLayout(
    sidebarPanel(
      radioButtons("type_select", "What do you want to select?",
                   c("Rows" = "Rows",
                     "Columns" = "Columns")),
      uiOutput("picker"),
      actionButton("view", "View Selection")
      
    ),
    
    # Show a plot of the generated distribution
    mainPanel(
      h2('Mydata'),
      DT::dataTableOutput("table"),
    )
  )
)

library(shiny)
library(DT)

server <- function(session, input, output) {
  
  data <- reactive({
    iris
  })
  
  output$picker <- renderUI({
    pickerInput(inputId = 'pick', 
                label = 'Choose', 
                choices = colnames(data()),
                options = list(`actions-box` = TRUE),multiple = T)
  })
  
  datasetInput <- eventReactive(input$view,{
    
    datasetInput <- data() %>% 
      select(input$pick)
    
    return(datasetInput)
    
  })
  
  output$table <- renderDT({
    if(input$type_select == "Rows"){
        datatable(
          data(),
          selection = "none",
          filter="top", 
          rownames = FALSE,
          extensions = c("Buttons", "Select"),
          
          options = list(
            select = TRUE,
            dom = 'Blfrtip',
            buttons =
              list('copy', 'print', list(
                extend = 'collection',
                buttons = list(
                  list(extend = 'csv', filename = "File", title = NULL,
                       exportOptions = list(modifier = list(selected = TRUE))),
                  list(extend = 'excel', filename = "File", title = NULL,
                       exportOptions = list(modifier = list(selected = TRUE)))),
                text = 'Download'
              ))
          ),
          class = "display"
        )
    }else{
        datatable(
          datasetInput(),
          filter="top", 
          rownames = FALSE,
          extensions = 'Buttons',
          
          options = list(
            dom = 'Blfrtip',
            buttons =
              list('copy', 'print', list(
                extend = 'collection',
                buttons = list(
                  list(extend = 'csv', filename = "File", title = NULL),
                  list(extend = 'excel', filename = "File", title = NULL)),
                text = 'Download'
              ))
          ),
          class = "display"
        )
      }
  })
}


# Run the application 
shinyApp(ui = ui, server = server)

Next, I am going to show you some screenshots from the app, to explain how it works.

If you select "rows": Rows

If you select "columns": columns

In fact, if you want to check if the selection went well, you can download a file (excel, for example) and you will see that your selection is okay.

However, I don't know how to solve the problems that I explained above.

Does anyone can help me, please? I am desperated.

Thanks very much in advance


Solution

  • I found the entire solution for all the problems:

    • Warning (thanks to Ronak Shah's answer)

    • How to hide the "Selection Input" from `pickerInput" and the action button when I select "rows". Thanks to this post.

      library(shiny)
      library(shinyWidgets)
      library(dplyr)
      
      ui <- fluidPage(
      
      # Application title
      titlePanel("Old Faithful Geyser Data"),
      
      # Sidebar with a slider input for number of bins 
      sidebarLayout(
        sidebarPanel(
          radioButtons("type_select", "What do you want to select?",
                       c("Rows" = "Rows",
                         "Columns" = "Columns")),
      
          conditionalPanel(
            condition = "input.type_select == 'Columns'",
            uiOutput("picker"),
            actionButton("view", "View Selection")        
          )
      
        ),
      
        # Show a plot of the generated distribution
        mainPanel(
          h2('Mydata'),
          DT::dataTableOutput("table"),
        )
      )
      )
      
      
      library(shiny)
      library(DT)
      
      server <- function(session, input, output) {
      
      data <- reactive({
        iris
      })
      
      output$picker <- renderUI({
        pickerInput(inputId = 'pick', 
                    label = 'Choose', 
                    choices = colnames(data()),
                    options = list(`actions-box` = TRUE),multiple = T)
      })
      
      datasetInput <- eventReactive(input$view,{
      
        datasetInput <- data() %>% 
          select(input$pick)
      
        return(datasetInput)
      
      })
      
      output$table <- DT::renderDataTable(server = FALSE,{
        if(input$type_select == "Rows"){
          datatable(
            data(),
            selection = "none",
            filter="top", 
            rownames = FALSE,
            extensions = c("Buttons", "Select"),
      
            options = list(
              select = TRUE,
              dom = 'Blfrtip',
              buttons =
                list('copy', 'print', list(
                  extend = 'collection',
                  buttons = list(
                    list(extend = 'csv', filename = "File", title = NULL,
                         exportOptions = list(modifier = list(selected = TRUE))),
                    list(extend = 'excel', filename = "File", title = NULL,
                         exportOptions = list(modifier = list(selected = TRUE)))),
                  text = 'Download'
                ))
            ),
            class = "display"
          )
        }else{
          datatable(
            datasetInput(),
            filter="top", 
            rownames = FALSE,
            extensions = 'Buttons',
      
            options = list(
              dom = 'Blfrtip',
              buttons =
                list('copy', 'print', list(
                  extend = 'collection',
                  buttons = list(
                    list(extend = 'csv', filename = "File", title = NULL),
                    list(extend = 'excel', filename = "File", title = NULL)),
                  text = 'Download'
                ))
            ),
            class = "display"
          )
        }
      })
      }
      
      
      # Run the application 
      shinyApp(ui = ui, server = server)
      

    Some screenshots after adding the conditionalPanel:

    If you select rows...

    rows

    If you select columns...

    columns

    WARNING. This solution doesn't work if you only want to select X number of columns in order to download them (for example, you only want to download 25 entries, but if you download the file you won't have 25 entries, you will have everything.