glin / reactable

Interactive data tables for R
https://glin.github.io/reactable
Other
627 stars 80 forks source link

fantastic and amazing #5

Closed timelyportfolio closed 5 years ago

timelyportfolio commented 5 years ago

Sorry to pollute the issues with some praise, but this is simply fantastic and amazing. Please let me know any way that I can help. The examples really demonstrate the power of this package.

I thought I would have a little fun with it.

#devtools::install_github("https://github.com/glin/reactable")
#devtools::install_github("https://github.com/react-R/roffice")

library(reactable)
library(roffice)
library(reactR)

mtcars$slider <- NA

browsable(
  tagList(
    reactR::html_dependency_react(),
    roffice::roffice_deps(),
    reactable(
      mtcars,
      columns = list(
        slider = colDef(render = JS(
          '(cell) => React.createElement(Fabric.Slider, {defaultValue: cell.row.carb})'
        ))
      )
    )
  )
)

browsable(
  tagList(
    reactR::html_dependency_react(),
    roffice::roffice_deps(),
    reactable(
      mtcars,
      columns = list(
        slider = colDef(
          render = JS(
            '(cell) => React.createElement(Fabric.Rating, {rating: cell.row.carb, readOnly: true, max: 10})'
          ),
          width = 210,
          resizable = FALSE
        )
      )
    )
  )
)

Unsurprisingly due to the quality of your work thus far, it renders perfectly. Sort doesn't update the slider, but I think that is because of the slider component, since if I just use '(cell) => React.createElement("div", null, cell.row.carb)' all works great.

glin commented 5 years ago

Thanks, and those are some cool examples! I think the slider never updates because it uses defaultValue. It could be forced to re-render with a key on it:

(cell) => React.createElement(Fabric.Slider, {key: cell.index, defaultValue: cell.row.carb})

or maybe you could use value instead:

(cell) => React.createElement(Fabric.Slider, {value: cell.row.carb})
timelyportfolio commented 5 years ago

This single package makes the efforts on reactR worthwhile. Please let me know how I can help. Thanks for your efforts.

timelyportfolio commented 5 years ago

I thought it would be worthwhile to show a little more complicated but also more useful example with Semiotic sparklines.

library(htmltools)
library(reactR)
library(reactable)
library(lubridate)
library(data.table)

dep_semiotic <- htmltools::htmlDependency(
  name = "semiotic",
  version = "1.9.11",
  src = c("href" = "https://unpkg.com/semiotic"),
  script = HTML("dist/semiotic.min.js")
)

# get some built in R time series data
data(EuStockMarkets)
# convert dates to something usable
dates <- as.Date(lubridate::date_decimal(as.numeric(time(EuStockMarkets))))
# use data.table or dplyr or whatever you prefer
dat <- data.table(
  Year = format(dates, "%Y"),
  Month = format(dates, "%m"),
  Day = format(dates, "%d"),
  EuStockMarkets
)

# see it in raw form with no transformation or adornment
reactable(dat)

# now let's make a sparkline by year for each index
semiotic_template <- "
function(cell) {
  const y = cell.row.Year;

  return React.createElement(
    Semiotic.SparkXYFrame,
    {
      lines: {
        coordinates: cell.row.%1$s.map( (d,i) => {
          return {
            date: new Date([y, cell.row.Month[i], cell.row.Day[i]].join('-')),
            value: d / cell.row.%1$s[0] - 1
          }
        })
      },
      yAccessor: 'value',
      xAccessor: 'date',
      lineStyle: {stroke: '#ac58e5', fill: '#ac58e5'},
      axes: [{orient: 'left', tickValues: [0] }],
      size: [cell.width, 30]
    }
  )
}
"

# sparkline by year
rt <- reactable(
  dat[
    order(Year, Month, Day),
    lapply(.SD, list),
    by = .(Year)
  ],
  columns = list(
    Month = colDef(show = FALSE),
    Day = colDef(show = FALSE),
    DAX = colDef(cell = htmlwidgets::JS( sprintf(semiotic_template, "DAX")), sortable = FALSE),
    CAC = colDef(cell = htmlwidgets::JS( sprintf(semiotic_template, "CAC")), sortable = FALSE),
    SMI = colDef(cell = htmlwidgets::JS( sprintf(semiotic_template, "SMI")), sortable = FALSE),
    FTSE = colDef(cell = htmlwidgets::JS( sprintf(semiotic_template, "FTSE")), sortable = FALSE)
  ),
  striped = TRUE
)

browsable(tagList(
  html_dependency_react(),
  dep_semiotic,
  rt
))

image

glin commented 5 years ago

Woah, that's awesome! Thanks for sharing. Also, I didn't know you could reuse arguments in sprintf like that :open_mouth: - very nifty.