Passing parameter to custom renderer in rhandsontable does not work inside a Shiny App
Asked Answered
S

1

6

I need to pass some parameters into a custom rhandsontable renderer. It works fine when executed inside RStudio, but does not render anything when used inside a Shiny App.

Here is the code for the custom renderer that sets bold font:

renderSheet <- function(df, bold) {
    rhandsontable(
        df,
        col_bold = bold$col,
        row_bold = bold$row) %>%  
    hot_cols(renderer = "
        function(instance, td, row, col, prop, value, cellProperties) {
          Handsontable.renderers.TextRenderer.apply(this, arguments);

          tbl = this.HTMLWidgets.widgets[0]

          col_bold = tbl.params.col_bold
          col_bold = col_bold instanceof Array ? col_bold : [col_bold] 
          row_bold = tbl.params.row_bold
          row_bold = row_bold instanceof Array ? row_bold : [row_bold] 

          if (col_bold.includes(col) && row_bold.includes(row)) {
            td.style.fontWeight = 'bold';
          }

          return td;
    }"
    ) }

Here is how to run it in RStudio:

df = data.frame(a = c("a1", "a2"), b = c("b1", "b2"))
bold <- data.frame(row = c(1, 1), col = c(0, 1))
renderSheet(df, bold)

Here is a minimal Shiny App to demonstrate that it won't render:

library(rhandsontable) 
library(shiny)

df = data.frame(a = c("a1", "a2"), b = c("b1", "b2"))
bold <- data.frame(row = c(1, 1), col = c(0, 1))


ui <- shinyUI(fluidPage(  
    rHandsontableOutput("hot") 
))

server <- shinyServer(function(input, output, session) {           

    output$hot = renderRHandsontable({
        renderSheet(df, bold)   
    }) 
})

shinyApp(ui, server)

The line causing problems inside a Shiny app is tbl = this.HTMLWidgets.widgets[0], and I don't know how to fix it.

Are there any alternative ways of passing parameters into a custom renderer?

NOTE: rhandsontable's help page states that inside a Shiny app we have to be careful, but I cannot make use of the code snippet provided in the help page (jrowen.github.io/rhandsontable/#custom_renderer)

HTMLWidgets.widgets.filter(function(widget) {
  // this should match the table id specified in the shiny app
  return widget.name === "hot"
})[0];

How can we apply the above code snippet to my problem?

Szechwan answered 15/2, 2019 at 12:22 Comment(0)
D
1

In shiny, don't use tbl = this.HTMLWidgets.widgets[0]. Sufficient is to directly use instance:

library(rhandsontable)
library(shiny)

df = data.frame(a = c("a1", "a2"), b = c("b1", "b2"))
bold <- data.frame(row = c(1, 1), col = c(0, 1))

renderSheet <- function(df, bold) {
  rhandsontable(df,
                col_bold = bold$col,
                row_bold = bold$row) %>%
    hot_cols(
      renderer = "
        function(instance, td, row, col, prop, value, cellProperties) {
          Handsontable.renderers.TextRenderer.apply(this, arguments);
          if (instance.params) {
            col_bold = instance.params.col_bold
            col_bold = col_bold instanceof Array ? col_bold : [col_bold]
            row_bold = instance.params.row_bold
            row_bold = row_bold instanceof Array ? row_bold : [row_bold]
          }
          if (instance.params && col_bold.includes(col) && row_bold.includes(row)) {
            td.style.fontWeight = 'bold';
          }
          return td;
        }"
    )
}

ui <- shinyUI(fluidPage(rHandsontableOutput("hot")))

server <- shinyServer(function(input, output, session) {
  output$hot = renderRHandsontable({
    renderSheet(df, bold)
  })
})

shinyApp(ui, server)
Dis answered 21/5 at 18:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.