reactable icon indicating copy to clipboard operation
reactable copied to clipboard

Control when to sort the table

Open daattali opened this issue 2 years ago • 3 comments

If a reactable table is sortable, then clicking anywhere in the column header will result in sorting that column. However, I'd like to have more control over when to sort a column. Specifically, I'd like to be able to only sort when a certain button is clicked.

Here's an example (expanded from https://github.com/glin/reactable/issues/262), where I only want to sort when the sort button is clicked, but not when the rest of the header is clicked.

library(shiny)
library(reactable)

ui <- fluidPage(
    reactableOutput("table")
)

server <- function(input, output, session) {
    output$table <- renderReactable({
        reactable(
            mtcars,
            defaultColDef = colDef(
                header = function(name) {
                    tags$div(
                        name,
                        icon("sort", title = "Sort"),
                        icon("trash-alt", title="Remove", onclick = "event.stopPropagation(); alert('drop');")
                    )
                }
            )
        )
    })
}

shinyApp(ui, server)

daattali avatar Mar 14 '23 07:03 daattali

This would be totally possible with a sorting method in the JavaScript API. I thought it already existed, but realized it didn't when I was writing up the example. Tagging as a feature request for now, but when it gets added later, you should be able to set sortable = FALSE to disable UI sorting and add your own custom sort buttons that call a Reactable.toggleSortBy() method. It'd look something like this:

library(shiny)
library(reactable)

ui <- fluidPage(
  reactableOutput("table")
)

server <- function(input, output, session) {
  output$table <- renderReactable({
    reactable(
      mtcars,
      sortable = FALSE,
      defaultColDef = colDef(
        header = function(value, name) {
          tags$div(
            value,
            tags$button(icon("sort", title = "Sort"), onclick = "Reactable.toggleSortBy('table', '%s')", name),
            icon("trash-alt", title="Remove", onclick = "event.stopPropagation(); alert('drop');")
          )
        }
      )
    )
  })
}

shinyApp(ui, server)

glin avatar Mar 19 '23 03:03 glin

There would be no need for the event.stopPropagation() in the other button :) Do you know if this is something you're likely to work on in the near future (few weeks) or is it more of a "put it on the shelf for some point in the future"?

No problem either way, just to know if I should make my own workaround or not.

daattali avatar Mar 19 '23 05:03 daattali

Probably near future since it should be a fairly small change, but it would be a while before that release makes it to CRAN anyway. A workaround could still make sense.

There's also a completely undocumented/unsupported way to achieve this if it's easier than the workaround. In the cars-table table on the JavaScript API page, you can try it using:

// Toggle sort on the Type column (asc -> desc -> unsorted)
Reactable.getInstance('cars-table').toggleSortBy('Type')

// Change sort on the Type column to descending
Reactable.getInstance('cars-table').toggleSortBy('Type', true)

// Change sort on the Type column to ascending
Reactable.getInstance('cars-table').toggleSortBy('Type', false)

The final method would look similar, except toggleSortBy(column) would only switch between ascending and descending unless you added another argument to enable the "shift key held" behavior.

glin avatar Mar 27 '23 05:03 glin