glin / reactable

Interactive data tables for R
https://glin.github.io/reactable
Other
612 stars 79 forks source link

crosstalk: selection interaction is wrong, it filters rows instead of selecting/highlighting #320

Open daattali opened 1 year ago

daattali commented 1 year ago

The {crosstalk} package provides functionality to link shiny widgets in two ways: selection and filtering. reactable implements filtering correctly, and when rows in a reactable table are selected then it correctly sends the selection signal. However, when rows are selected externally, reactable does not correctly show the selection - it filters for these rows instead of highlighting them.

In the example below, if you use the filters, then both the plot and the table will show filtered data. This is correct. If you select rows in the table, then the corresponding data points will highlight in the plot. This is also correct. But if you highlight points in the plot, then the table will filter out the other data instead of highlighting the selected data.

library(shiny)

df <- crosstalk::SharedData$new(cars)

ui <- fluidPage(
  crosstalk::filter_slider("speed", NULL, df, "speed"),
  d3scatter::d3scatterOutput("plot"),
  reactable::reactableOutput("table")
)

server <- function(input, output, session) {
  output$plot <- d3scatter::renderD3scatter({
    d3scatter::d3scatter(df, ~speed, ~dist)
  })
  output$table <- reactable::renderReactable({
    reactable::reactable(df, selection = "multiple")
  })
}

shinyApp(ui, server)
glin commented 1 year ago

So this is intentional, and also a weird thing I encountered in DT while adding Crosstalk support originally. Crosstalk selections aren't congruent - selecting from the table selects in other widgets, but selecting from other widgets filter the table. It's weird, but made so much sense after thinking about what users would expect when using a paginated table as a Crosstalk output.

If you select points in a plot, they'd typically want to see the corresponding selected rows highlighted in the table. But if you just highlight those rows like a selection, there's a good chance those rows will be lost on some other page and hard to find. It wouldn't be great UX in many cases, so I settled on filtering too for lack of a better highlighting mechanism.

Not ideal and also causes other confusing behavior (https://github.com/glin/reactable/issues/267), so I guess it should at least be documented.

If you want selections from another widget to select in reactable, the JavaScript API could make that possible if there was a selection method, and if that other widget could run custom JS code on selections. I could add this as a feature request if that'd work.

daattali commented 1 year ago

Thanks for the explanation. I haven't thought of that reason, I can see now that both behaviours (current behaviour and my expected behaviour) aren't ideal.