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

3.1k views Asked by At

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

2

There are 2 answers

0
emr2 On BEST ANSWER

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.

3
Ronak Shah On

To get rid of warning change renderDT to DT::renderDataTable and set server = FALSE in it.

Here is the complete code -

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 <- 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)