不确定它是否仍然相关,但我最近在寻找类似的东西并找到了这个解决方案
library(shiny)
library(shinyjs)
library(purrr)
library(tibble)
library(stringr)
library(lubridate)
library(reactable)
dates = seq.Date(from = as_date("2022-01-01"), to = as_date("2023-02-01"), by = "month")
labels = paste(month(c(as_date(dates)), label = T), year(c(as_date(dates))))
df = tibble(date = dates, letters = letters[1:14])
ui = fluidPage(
tags$head(tags$style(HTML(".selected {background: rgba(125, 181, 171, .25);}")), shinyjs::useShinyjs()),
div(style = "margin-top: 50px; display: flex; flex-direction: column; gap: 20px; align-items: center;",
div(style = "display: flex; gap: 1rem;",
pmap(
.l = list(
dates = dates,
labels = labels,
classes = c(rep("", 3), rep("selected", 4), rep("", 7))), .f = ~actionButton(inputId = paste0("btn_", ..1), label = ..2) %>%tagAppendAttributes(class = ..3))),
reactableOutput(outputId = "table"))
)
server = function(input, output, session){
range = reactiveValues(from = "2022-04-01", to = "2022-07-01")
map(paste0("btn_", dates), .f = function(x) {
observeEvent(input[[x]], {
freezeReactiveValue(input, "from")
freezeReactiveValue(input, "to")
val = str_remove(x, pattern = "btn_")
if(!is_null(range$to)){
range$from = val
range$to = NULL
}else if(is_null(range$to)){
if(val > range$from){
range$to = val
}else if(val < range$from){
range$to = range$from
range$from = val
}else if(val == range$from){
range$to = NULL
}
}
dateseq = if(is_null(range$to)){as_date(range$from)}else{seq.Date(as_date(range$from), as_date(range$to), by = "month")}
map(.x = paste0("btn_", dates)[!paste0("btn_", dates)%in%paste0("btn_", dateseq)], .f = ~shinyjs::removeClass(id = .x, class = "selected"))
map(.x = paste0("btn_", dateseq), .f = ~shinyjs::addClass(id = .x, class = "selected"))
})
})
output$table = renderReactable({
datevalues = if(is_null(range$to)){c(range$from, range$from)}else{c(range$from, range$to)}
reactable(df[df$date>=as_date(datevalues[1])&df$date<=as_date(datevalues[2]),], defaultPageSize = 14)
})
}
shinyApp(ui, server)