简体   繁体   中英

Persistent column filters with Shiny DT

I'm trying to adapt this method for capturing DT's column search term responses and re-applying them when table refreshes due to an update of its reactive data object. I can't figure out the right formulation to achieve this. Reproducible example:

require(shiny)
require(dplyr)
require(stringr)
require(DT)

d = tibble(sentence = sentences, chars = nchar(sentence), grp = sample(LETTERS, length(sentences), replace = TRUE))
default_search = ''

ui <- fluidPage(
  selectInput("grp", 'group', choices = LETTERS, selected = NULL),
  DTOutput("data_tbl")
)

server <- function(input, output, session) {
  
  r = reactiveValues(group = NULL, lines = NULL, search_columns = NULL)
  
  proxy <- dataTableProxy('data_tbl')
  
  observeEvent(input$grp, {
    r$data = d %>% filter(grp == input$grp)
  })
  
  output$data_tbl <- renderDT(filter = "top", {
    r$data %>% select(-grp)
  }, options = list(stateSave = TRUE))
  
  # catch column search terms
  observeEvent(input$data_tbl_search_columns, {
    if(is.null(input$data_tbl_search_columns)) return()
    if(input$data_tbl_search_columns[1] != '') {
      proxy %>% updateSearch(keywords = list(global = default_search, columns = c('', isolate(input$data_tbl_search_columns))))
    }
  })
  
}

shinyApp(ui, server)

The intended outcome would be:

  1. User adds a search filter in "sentence" field eg "the". The table filters to matching records.
  2. User changes the grp selection to change the data. The table refreshes, but (i) the search term is preserved in the filter window, and (ii) the table is filtered accordingly.

I'm getting some persistence but the results are wrong. And the filter term is omitted from the search window. Any assistance appreciated.

The trick is that your observeEvent depends on the changing data, not the column search terms. I've also added the ability that your global search term is stored.

require(shiny)
require(dplyr)
require(stringr)
require(DT)

d = tibble(sentence = sentences, chars = nchar(sentence), grp = sample(LETTERS, length(sentences), replace = TRUE))
default_search = ''

ui <- fluidPage(
  selectInput("grp", 'group', choices = LETTERS, selected = NULL),
  DTOutput("data_tbl")
)

server <- function(input, output, session) {
  
  r = reactiveValues(group = NULL, lines = NULL, search_columns = NULL)
  
  proxy <- dataTableProxy('data_tbl')
  
  observeEvent(input$grp, {
    r$data = d %>% filter(grp == input$grp)
  })
  
  output$data_tbl <- renderDT(filter = "top", {
    r$data %>% select(-grp)
  })
  
  # catch column search terms
  observeEvent(r$data, {

    if(is.null(input$data_tbl_search_columns)) return()
    if(input$data_tbl_search_columns[1] != '') {
      proxy %>% updateSearch(keywords = list(global = isolate(input$data_tbl_search),
                                             columns = c("", isolate(input$data_tbl_search_columns))))
    }
  })
  
}

shinyApp(ui, server)

I'm not sure if it is desired behaviour, with your if condition the second filter doesn't get stored. And at least in this reprex you actually don't need the reactiveValues but could store the data directly in a reactive , then you can save one observer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM