jrowen / rhandsontable

A htmlwidgets implementation of Handsontable.js
http://jrowen.github.io/rhandsontable/
Other
383 stars 148 forks source link

R rhandsontable renderer does not follow column sorting despite being reactive #412

Open mzuer opened 2 years ago

mzuer commented 2 years ago

Dear all,

I am working in a shiny app that displays a rhandsontable. I use a "renderer" to customize cell color and border. In addition, I would like to allow the user to perform column sorting. Here is my problem: when columns are sorted, the borders and the colors defined in the renderer do not follow the sorting. Indeed, they stay at the same position in the table, despite their coordinates are computed in a reactive code block. It looks like the sorting is not detected as a "trigger" of the reactive part. See for example the dummy reproducible example here below:

library(rhandsontable)
library(shiny)
border_width <- 4
border_col <- "green"
ui <- fluidPage(
  rHandsontableOutput('table'),
)
server <- function(input, output) {
  get_data <- reactive({
    if(is.null(input$table)) {
      show_dt <- mtcars
      show_dt[,"cyl4"] <- show_dt$cyl == 4
    } else {
      show_dt <- hot_to_r(input$table)
      show_dt[,"cyl4"] <- as.logical(show_dt[,"cyl4"])
    }
    return(show_dt)
  })
  output$table <- rhandsontable::renderRHandsontable({
    show_dt <- get_data() 
    row_highlight <- which( show_dt$cyl == 4)
    rows21 <- which(show_dt$mpg > 30) - 1
    col21 <- which(colnames(show_dt) == "mpg") -1 
    mycells <- list()
    for(i in seq_along(rows21)) {
      mycells[[i]] <- list(
        range = list(from = list(row = rows21[i], col = col21),
                     to = list(row = rows21[i], col = col21)),
        top = list(width = border_width, color = border_col),
        left = list(width = border_width, color = border_col),
        bottom = list(width = border_width, color = border_col),
        right = list(width = border_width, color = border_col))
    }
    rhandsontable(show_dt, height = 500, row_highlight=row_highlight-1) %>%
      hot_cols(columnSorting = TRUE) %>%
      hot_cols(renderer = "
            function(instance, td, row, col, prop, value, cellProperties) {
                Handsontable.renderers.TextRenderer.apply(this, arguments);
                if (instance.params) {
                    hrows = instance.params.row_highlight
                    hrows = hrows instanceof Array ? hrows : [hrows]
                }
                if (instance.params && hrows.includes(row)) td.style.background = '#FFC5C5';
            }")  %>%  hot_col(col = "cyl4",
                              renderer = "
              function (instance, td, row, col, prop, value, cellProperties) {
                  Handsontable.renderers.CheckboxRenderer.apply(this, arguments);
                  if (value) {
                      td.style.background = '#FFC5C5';
                  } else {
                   td.style.background = '#C3FA9A';
                  }
              }
          ") %>% hot_table(customBorders = mycells)

  })
}
shinyApp(ui, server)

Does anyone has an explanation why it does not work as expected ? Do you know how I could make the reactvive code block sensitive to column sorting (so that it re-calculates the correct positions upon sorting) ?