How to filter (search) formatted columns in R DT (DataTable)

Tags: , , ,



When applying formatting to a column in DT::datatable(), the DataTables automatic column filter is not working. For example:

library(DT)
a <- letters[1:10]
b <- 1:10
df <- data.frame(a, b)
datatable(df, filter="bottom") %>% formatCurrency(columns = "b", currency = "$")

The filter for column b fails.

I think this is a common enough problem that there has to be a solution. I have been searching, but without success so far. Would be grateful if someone points me to where this has been solved.

I am aware that by using the JS callback function on the DT website (https://rstudio.github.io/DT/options.html see 4.5 Row rendering and run it with filter="top"), one can filter with formatted columns. But I am trying to implement a general solution for an R package, so I was hoping for an R solution.

Workaround

I have an approach that works in some cases. The approach is to copy the raw numbers column to a new column that is hidden on rendering. But ‘link’ the formatted numbers (column) to the raw numbers column (values_column) in formatStyle. Then, luckily, and not exactly sure why, searching on the formatted column works. But only in the case of suffixes (like %), but not for prefixes ($) or big number formatting with commas for thousands.

Code for each of these cases is below.

I don’t mind using this workaround, but don’t know enough about the inner workings of DT to make prefixes and other formats work.

Suffix works

library(DT)
a <- letters[1:10]
b <- 1:10
df <- data.frame(a, b)

xx <- 
  datatable(
  data = df,
  filter = "bottom",
  options = list(columnDefs = list(list(
    targets = which(stringr::str_detect(colnames(df), "hide")), visible = FALSE
  )))
)

xx$x$data$hide_b <- xx$x$data$b
xx$x$data$b <- paste(xx$x$data$b, "%")
attr(xx$x, "colnames") <- colnames(xx$x$data)

xx %>% 
  formatStyle(
    columns = "b",
    valueColumns = "hide_b"
  )

Prefix fails

library(DT)
a <- letters[1:10]
b <- 1:10
df <- data.frame(a, b)

xx <- 
  datatable(
    data = df,
    filter = "bottom",
    options = list(columnDefs = list(list(
      targets = which(stringr::str_detect(colnames(df), "hide")), visible = FALSE
    )))
  )

xx$x$data$hide_b <- xx$x$data$b
xx$x$data$b <- paste("$", xx$x$data$b)
attr(xx$x, "colnames") <- colnames(xx$x$data)

xx %>% 
  formatStyle(
    columns = "b",
    valueColumns = "hide_b"
  )

Big number fails

library(DT)
a <- letters[1:10]
b <- 1:10*10^6

df <- data.frame(a, b)

xx <- 
  datatable(
    data = df,
    filter = "bottom",
    options = list(columnDefs = list(list(
      targets = which(stringr::str_detect(colnames(df), "hide")), visible = FALSE
    )))
  )

xx$x$data$hide_b <- xx$x$data$b
xx$x$data$b <- format(xx$x$data$b,digits = 1, scientific = FALSE, big.mark = ",")
attr(xx$x, "colnames") <- colnames(xx$x$data)

xx %>% 
  formatStyle(
    columns = "b",
    valueColumns = "hide_b"
  )

Answer

Using DR::renderDT with server=TRUE (the default) inside a Shiny app solves this problem using the regular DT::format* functions. Outside Shiny context, the examples still don’t work. But that is irrelevant in my case, as the tables will go in a Shiny app.



Source: stackoverflow