DT icon indicating copy to clipboard operation
DT copied to clipboard

Enabling R styling via a new param `formatter`

Open shrektan opened this issue 4 years ago • 4 comments

Closes #938 #652 #990

DT implements many nice JS wrappers on styling the columns. However, R users may still find they want to implement their own style, as the love for beautiful table never ends. They can do it in two ways:

  1. On JS side: Write a JS function and set it in render options, i.e., datatable(..., options = list( columnDefs = list( list(targets = 1, render = JS(...)))))
  2. On R side: Transform the R data.frame object's relevent column into characters, then pass it to DT, probably need to set the escape argument to FALSE.

Unfortunately, those two methods are either difficult to implement or contain side-effects:

  1. JS method:
  • Many R users are not aware of the existence of the columnDefs.render option
  • Write the JS function correctly is not easy, especially when the "style" is complicated
  • You can't leverage the existing R packages like formattable
  1. R method:
  • Probably lose the ability to sort, filter or search correctly as the raw "data" is tranformed into formatted "data"
  • Probably need additional efforts to "unescape" data, align text, etc.

The new param formatter allows users to write formatting functions in R without losing the ability to sort, filter or search by retaining the raw data "untouched" as it creates invisible helper columns.

TODO

  • [ ] support formatter type like list(function() ... , targets = ...)
  • [ ] figure out a way when the formatter need other info from the data, like other column
  • [ ] try out all the possible corner cases in case of unexpected happening
  • [ ] state clear the limitations in doc (probably cause issues when editing data
  • [ ] need to triger updating the hidden formatted columns when source is updated, e.g, via proxy, or editing
  • [ ] NEWS
  • [ ] Add an example into inst/example
  • [ ] Add an example into site
  • [ ] add tests

Example

set.seed(100)
x <- rnorm(10)
rk <- rank(x)
prefix <- sample(LETTERS[1:3], replace = TRUE, 10)
tbl <- data.frame(V1 = x, V2 = x, V3 = x, V4 = x, RK = rk)
DT::datatable(tbl, rownames = FALSE, filter = "top", formatter = list(
  V2 = function(x) paste0(prefix, round(x * 100, 2), "%"),
  V3 = formattable::percent,
  V4 = function(x) round(x * 100, 2),
  V4 = formattable::color_tile(min.color = "yellow", max.color = "red")
))
image

shrektan avatar Dec 05 '21 11:12 shrektan

Now I think this feature is not suitable for DT as it becomes more complicated than I thought. I don't wanna introduce any complexity into DT as it's already a big project.

Close it for now.

shrektan avatar Jan 20 '22 15:01 shrektan

It's was a very good try. Thanks. (Sob). Perhaps later ? :)

philibe avatar Jan 20 '22 19:01 philibe

@yihui , @shrektan

This reopened issue gives me the opportunity to thank you for your work on DT.

When I first installed DT in early 2018, for me it was a simple adaptation of datatable.net, but now that I'm trying to use datatable.net with Flask Rest and VueJs 3 I see that I have to rewrite a lot of things which I thought was in datatable.net but actually written in the server side of DT, and I understand how your API wrapping initial datatable.net ones in the front side.

philibe avatar Apr 08 '22 10:04 philibe

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

CLAassistant avatar Nov 08 '23 16:11 CLAassistant