Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to trigger a modalBox with observeEvent from a cell rendered button in a reactable?

Tags:

r

shiny

reactable

Following on from this post, I wonder why showModal() inside of observeEvent() does not get triggered when i click on the cell rendered button? I give the button the fixed ID 'character' on which the observeEvent() should listen and then open the modal box. But it doesnt.

Where is the difference if i place a button in the ShinyApp UI, where the observeEvent() would react to the inputid, or if I place it in a reactable?

library(shiny)
library(reactable)
library(tidyverse)

data = dplyr::starwars %>%
  select(name, height, mass, sex, species, homeworld)

ui = fluidPage(
  
  column(width = 6, style = "margin-top: 50px;",
  reactableOutput("table"))
  
)

server = function(input, output, session){

  
  output$table = renderReactable({
    reactable(data = data,
              height = 600,
              defaultPageSize = 20,
              columns = list(
                name = colDef(
                  cell = function(value){
                    div(htmltools::tags$button(value, class = "action-button", id = "character"))
                  })))})
  
  observeEvent(input$character, {
  showModal(modalDialog(title = "Test"))
  })
}

shinyApp(ui, server)
like image 496
werN Avatar asked Nov 20 '25 19:11

werN


1 Answers

The reactable package provides many examples how you can work with it including a custom action in each row. The sample has a column "details" and it shows elements looking like button. With the Javascript function there it identifies clicks on the details column and acts accordingly.

Add this as additional argument to the reactable call in renderReactable.

reactable(
  data = data,
  height = 600,
  defaultPageSize = 20,
  ...
  onClick = JS("function(rowInfo, colInfo) {
    // Only handle click events on the 'details' column
    if (colInfo.id !== 'details') {
      return
    }

    // Send the click event to Shiny
    if (window.Shiny) {
      Shiny.setInputValue('foo', 'bar')
    }
  }")
)

Shiny.setInputValue("foo", "bar") will cause the server’s input$foo to be set to "bar". That leads to a Shiny event which you can catch in the server e,g, with an observer. See this tutorial about Javascript in R for details.

Please note: The authors of reactable do not recommend using this because "custom click actions are currently not accessible to keyboard users" (quote from the manual 2021-10-16). If accessibility or other reasons for keyboard use are not relevant for you, you can use this solution.

Note about the "class"-solution: I would not advise to use class = "action-button" because I believe it to be a fragile construct. That is no proper way to create an input binding and I am surprised it works at all.

The only package that I know which officially supports buttons in table rows is DataTables with the Buttons extension.

like image 131
Jan Avatar answered Nov 23 '25 08:11

Jan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!