1

I'm using reactable to display a table within my shiny app. Reactable allows for custom cell rendering using either a R function or a JS function. I am trying to render a custom <div> and manipulate that <div> with a JS function when hovering the cell.

Here is a shiny example:

shiny::shinyApp(ui = shiny::fluidPage(reactable::reactableOutput(outputId = "table")),
                server = function(input, output, session){
                  
                  data <- tibble::tibble(words = do.call(paste0, replicate(8, sample(LETTERS, 20, TRUE), FALSE))) |>
                    dplyr::rowwise() |>
                    dplyr::mutate(
                      same_content = as.character(
                        shiny::div(class = "same", style = "background-color: yellow", "HOVER ME")
                      ),
                      diff_content = as.character(
                        shiny::div(class = "diff", style = "background-color: yellow", sprintf("HOVER ME: %s", words))
                      )
                    )
                  
                  output$table <- reactable::renderReactable({
                    reactable::reactable(data = data, 
                                         columns = list(
                                           words = reactable::colDef(show = FALSE),
                                           same_content = reactable::colDef(html = TRUE, cell = htmlwidgets::JS(
                                             '
                                             $(function() {
                                                         $(".same").hover(
                                                           function() {
                                                             $(this).attr("style", "background-color: green");
                                                           },
                                                           function() {
                                                             $(this).attr("style", "background-color: yellow");
                                                           }
                                                         );
                                                       })
                                             '
                                           )
                                           ),
                                           diff_content = reactable::colDef(html = TRUE, cell = htmlwidgets::JS(
                                             '
                                             $(function() {
                                                         $(".diff").hover(
                                                           function() {
                                                             $(this).attr("style", "background-color: green");
                                                           },
                                                           function() {
                                                             $(this).attr("style", "background-color: yellow");
                                                           }
                                                         );
                                                       })
                                             '
                                           ))
                                         )
                    )
                  })
                }
)

On the first page of the table everything works as expected. When navigating to the second page only divs in the first column are changing their background color. The second column is stuck with yellow. When switching back to the first page the previously working second column does not change it's background color any more.

Is there a way to "re-apply" the function after switching to the second page of the table or are there any better ways to manipulate cell contents on hover?

Eike
  • 98
  • 5

1 Answers1

1

The question is do you really need JS to change the hover color? If not, some simple CSS can solve the problem:

shiny::shinyApp(
    ui = shiny::fluidPage(
        reactable::reactableOutput(outputId = "table"),
        shiny::tags$style('.same:hover {background-color: green !important; } .diff:hover {background-color: green !important;}')
    ),
    server = function(input, output, session){
        
        data <- tibble::tibble(words = do.call(paste0, replicate(8, sample(LETTERS, 20, TRUE), FALSE))) |>
            dplyr::rowwise() |>
            dplyr::mutate(
                same_content = as.character(
                    shiny::div(class = "same", style = "background-color: yellow", "HOVER ME")
                ),
                diff_content = as.character(
                    shiny::div(class = "diff", style = "background-color: yellow", sprintf("HOVER ME: %s", words))
                )
            )
        
        output$table <- reactable::renderReactable({
            reactable::reactable(data = data, 
                                 columns = list(
                                     words = reactable::colDef(show = FALSE),
                                     same_content = reactable::colDef(html = TRUE),
                                     diff_content = reactable::colDef(html = TRUE)
                                 )
            )
        })
    }
)
lz100
  • 6,990
  • 6
  • 29
  • Thanks for your reply! I chose the above example for the sake of simplicity. My real use case would be to have a `` tag inside my div and use something like `src.replace(".jpg", ".gif")` to play a gif instead of a static image on hover. Thats why I need the JS in there. – Eike Feb 20 '22 at 10:41