0

I am trying to create a drop down list to view the values within each column, similar to in excel. But I am unable to create the dropdown list. I am unable to understand where to make changes to create this list. Any suggestions, highly appreciated.

code:

Server.R

library(shiny)
library(DT)

shinyServer(function(input, output, session) {

  mtcars2 = data.frame(
    name = rownames(mtcars), mtcars[, c('mpg', 'hp')],
    stringsAsFactors = FALSE
  )
 
  output$tbl = DT::renderDataTable(
    mtcars2, filter = 'top', server = TRUE, rownames = FALSE,
    options = list(autoWidth = TRUE)
  )
})

ui.r

library(shiny)

shinyUI(fluidPage(
  title = 'Column Filters on the Server Side',
  fluidRow(
    DT::dataTableOutput('tbl')
  )
))
Stéphane Laurent
  • 75,186
  • 15
  • 119
  • 225
KApril
  • 632
  • 1
  • 8
  • 20

1 Answers1

1

Try this.

library(shiny)
library(DT)

dat <- mtcars

sketch <- htmltools::tags$table(
  tableHeader(c("", names(dat))),
  tableFooter(rep("", 1+ncol(dat)))
)

js <- c(
  "function(){", 
  "  this.api().columns().every(function(i){",
  "    var column = this;",
  "    var select = $('<select><option value=\"\"></option></select>')",
  "      .appendTo( $(column.footer()).empty() )", 
  "      .on('change', function(){",
  "        select.val(null);",
  "      });",
  "    var data = column.data();",
  "    if(i == 0){",
  "      data.each(function(d, j){",
  "        select.append('<option value=\"'+d+'\">'+d+'</option>');",
  "      });",
  "    }else{",
  "      data.unique().sort().each(function(d, j){",
  "        select.append('<option value=\"'+d+'\">'+d+'</option>');",
  "      });",
  "    }",
  "    select.select2({width: '100%'});",
  "  });",
  "}")


ui <- fluidPage(
  tags$head(
    tags$link(rel = "stylesheet", href = "https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/css/select2.min.css"),
    tags$script(src = "https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.min.js")
  ),
  br(),
  DTOutput("dtable")
)

server <- function(input, output, session){
  output[["dtable"]] <- renderDT({
    datatable(
      dat, container=sketch, 
      options = list(
        initComplete = JS(js),
        columnDefs = list(
          list(targets = "_all", className = "dt-center")
        )
      )
    )
  }, server = FALSE)
}

shinyApp(ui, server)

enter image description here


Edit: dropdowns at the top of the table

library(shiny)
library(DT)
library(htmltools)

dat <- mtcars

sketch <- tags$table(
  tags$thead(
    tags$tr(
      tags$th(),
      lapply(names(dat), tags$th)
    ),
    tags$tr(
      tags$th(id = "th0"),
      tags$th(id = "th1"),
      tags$th(id = "th2"),
      tags$th(id = "th3"),
      tags$th(id = "th4"),
      tags$th(id = "th5"),
      tags$th(id = "th6"),
      tags$th(id = "th7"),
      tags$th(id = "th8"),
      tags$th(id = "th9"),
      tags$th(id = "th10"),
      tags$th(id = "th11")
    )
  )
)

js <- c(
  "function(){", 
  "  this.api().columns().every(function(i){",
  "    var column = this;",
  "    var select = $('<select><option value=\"\"></option></select>')",
  "      .appendTo( $('#th'+i).empty() )", 
  "      .on('change', function(){",
  "        select.val(null);",
  "      });",
  "    var data = column.data();",
  "    if(i == 0){",
  "      data.each(function(d, j){",
  "        select.append('<option value=\"'+d+'\">'+d+'</option>');",
  "      });",
  "    }else{",
  "      data.unique().sort().each(function(d, j){",
  "        select.append('<option value=\"'+d+'\">'+d+'</option>');",
  "      });",
  "    }",
  "    select.select2({width: '100%'});",
  "  });",
  "}")


ui <- fluidPage(
  tags$head(
    tags$link(rel = "stylesheet", href = "https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/css/select2.min.css"),
    tags$script(src = "https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.min.js")
  ),
  br(),
  DTOutput("dtable")
)

server <- function(input, output, session) {
  output[["dtable"]] <- renderDT({
    datatable(
      dat, container=sketch, 
      options = list(
        orderCellsTop = TRUE,
        initComplete = JS(js),
        columnDefs = list(
          list(targets = "_all", className = "dt-center")
        )
      )
    )
  }, server = FALSE)
}

shinyApp(ui, server)
Stéphane Laurent
  • 75,186
  • 15
  • 119
  • 225
  • Is there a way to simplify this? I read some article using Datatable function https://blogs.oregonstate.edu/cgrb/2019/08/06/r-tips-a-table-makeover-with-dt/ – KApril Jun 22 '23 at 11:41
  • @KApril There's no such dropdown list in your link. What is the problem with my solution? It is nice. You can even search in the dropdown list. – Stéphane Laurent Jun 22 '23 at 11:47
  • Your code is very good, but the problem is the values in the filters are not getting selected. I don't know where to make changes in the JS code. – KApril Jun 23 '23 at 07:59
  • @KApril What do you mean by "selected"? You want to filter? I understood that you only wanted to display the values. Please be clear. – Stéphane Laurent Jun 23 '23 at 08:01
  • Hi Mr. Stéphane Laurent , Sorry if I wasn't clear. I want filter to select the values in each column, similar to in excel. – KApril Jun 23 '23 at 08:23
  • @KApril I don't know Excel. Is it what you want: ? – Stéphane Laurent Jun 23 '23 at 08:28
  • May you are a genius – KApril Jun 23 '23 at 08:30
  • Hi Mr. Stéphane Laurent, I tried to move the filters on top by using your code from the above link. Somehow it is not working for me. Could you please help me with this? – KApril Jun 23 '23 at 08:41
  • @KApril You use `mtcars` as data, right? It has 11 columns, so the `sketch` is not appropriate. Use the `sketch` as in my edit of the present post. – Stéphane Laurent Jun 23 '23 at 08:44
  • Works like a charm, thanks a lot Mr. Stéphane Laurent. I have a question about creating a button to add a new row. But somehow it doesn't work. When I click on add button the app is getting closed. I will open a new question for his. Could you be kind to respond? – KApril Jun 23 '23 at 09:29
  • @KApril Maybe search in my posts first. It's possible I already replied to such a question. And could you please upvote my answer? It took me a valuable time. – Stéphane Laurent Jun 23 '23 at 10:36
  • Mr. Stéphane Laurent, Yes I did with much gratitude. I will also search for the question you have already posted. Thanks a lot! – KApril Jun 23 '23 at 10:38