Search code examples
rshinyreactable

Why is the reactable index of rows in my filtered table wrong?


I have used a reactable with the option for select rows. But after filtering the reactable the row-numbers (respective the values) get from getReactableState("table", "selected") are wrong. Where is my mistake? By clicking on a row with unfiltered data, the row-numbers are correct. After filtering I get wrong values. How can I get the correct indexes of a filtered table?

library(shiny)
library(reactable)

data <- MASS::Cars93[, 1:7]

ui <- fluidPage(
  actionButton("select_btn", "Select rows"),
  selectInput("filter_type", "Filter type", unique(data$Type), multiple = TRUE),
  textInput("row", label = "Selected"),
  reactableOutput("table")
)

server <- function(session, input, output) {
  selected <- reactive(getReactableState("table", "selected"))
  
  output$table <- renderReactable({
    reactable(
      data,
      filterable = TRUE,
      searchable = TRUE,
      selection = "single",
    )
  })
  
  observeEvent(input$select_btn, {
    # Select rows
    updateReactable("table", selected = c(1, 3, 5))
  })

  observe({
    # Filter data
    filtered <- if (length(input$filter_type) > 0) {
      data[data$Type %in% input$filter_type, ]
    } else {
      data
    }
    updateReactable("table", data = filtered)
  })
  
  observe({
    updateTextInput(session, "row",  value = data$Model[selected()])
  })
  
  
}

shinyApp(ui, server)


Solution

  • One possibility: Put your filtered data inside a reactive() and update the text input using data_filtered(). Similarly you can go on with the selected values.

    enter image description here

    library(shiny)
    library(reactable)
    
    data <- MASS::Cars93[, 1:7]
    
    ui <- fluidPage(
        actionButton("select_btn", "Select rows"),
        selectInput("filter_type", "Filter type", unique(data$Type), multiple = TRUE),
        textInput("row", label = "Selected"),
        reactableOutput("table")
    )
    
    server <- function(session, input, output) {
        rv <- reactiveValues(data = data)
        
        data_filtered <- reactive({
            if (length(input$filter_type) > 0) {
                rv$data[rv$data$Type %in% input$filter_type,]
            } else {
                rv$data
            }
        })
        
        selected <- reactiveValues(j = 0)
        
        currentSelected <-
            reactive(getReactableState("table", "selected"))
        
        observeEvent(currentSelected(), priority = 0, {
            selected$j <- currentSelected()
        })
        
        output$table <- renderReactable({
            reactable(
                data_filtered(),
                filterable = TRUE,
                searchable = TRUE,
                selection = "single",
            )
        })
        
        observeEvent(input$select_btn, {
            # Select rows
            updateReactable("table", selected = c(1, 3, 5))
        })
        
        observe({
            if (is.null(getReactableState("table", "selected"))) {
                updateTextInput(session, "row", value = "")
            } else {
                updateTextInput(session, "row", value = data_filtered()$Model[selected$j])
            }
        })
        
    }
    
    shinyApp(ui, server)