如何为shinyWidgets的airDatepicker不同选项配置对应日期高亮颜色
实现方案
核心逻辑
- 服务端用响应式变量存储「日期-选项」的映射关系
- 自定义CSS定义不同选项对应的日期单元格样式
- 前端JS监听日期点击事件,根据当前选中的选项为单元格添加对应样式类,同时同步映射关系到服务端
- 服务端同步全量映射到前端,避免日历翻页后样式丢失
完整可运行代码
library(shiny) library(shinyWidgets) ui <- fluidPage( tags$style(HTML(" /* 定义不同选项对应的日期样式 */ .airdatepicker--cell.option-A { background-color: #ff4444 !important; color: white !important; } .airdatepicker--cell.option-B { background-color: #00C851 !important; color: white !important; } ")), tags$script(HTML(" // 监听日期单元格点击事件 $(document).on('click', '.airdatepicker--cell.-day-', function() { const currentOption = $('#option').val(); // 移除旧的样式类,添加当前选项对应的样式类 $(this).removeClass('option-A option-B').addClass(`option-${currentOption}`); // 将点击的日期和对应选项同步到服务端 Shiny.setInputValue('date_click', { date: $(this).data('date'), option: currentOption }); }); // 接收服务端的全量映射,刷新所有日期的样式(解决翻页后样式丢失问题) Shiny.addCustomMessageHandler('refreshDateStyles', function(mapping) { $('.airdatepicker--cell.-day-').each(function() { const cellTimestamp = $(this).data('date'); const cellDate = new Date(cellTimestamp).toISOString().split('T')[0]; if (mapping[cellDate]) { $(this).removeClass('option-A option-B').addClass(`option-${mapping[cellDate]}`); } }); }); ")), fluidRow( selectInput("option", "Choice?", choices = c("A", "B")), airDatepickerInput( inputId = "input_dates", label = "Inline:", multiple = Inf, inline = TRUE ) ) ) server <- function(input, output, session) { # 存储日期与选项的映射关系 date_option_map <- reactiveVal(list()) # 监听前端的日期点击事件,更新映射 observeEvent(input$date_click, { current_map <- date_option_map() # 转换为标准日期字符串作为key date_str <- as.Date(input$date_click$date/1000, origin = "1970-01-01") |> as.character() current_map[[date_str]] <- input$date_click$option date_option_map(current_map) # 通知前端刷新样式 session$sendCustomMessage("refreshDateStyles", current_map) }) # 日历切换视图/选中日期变更时重新应用样式 observeEvent(input$input_dates, { session$sendCustomMessage("refreshDateStyles", date_option_map()) }) # 原示例的调试输出 observeEvent(input$input_dates, { print(sprintf("Selected Dates: %s", paste(input$input_dates, collapse = ", "))) }) observe({ print(sprintf("Option is now: '%s'", input$option)) }) } shinyApp(ui = ui, server = server)
使用说明
- 选中选项A后点击的日期会自动标记为红色
- 切换到选项B后点击的日期会自动标记为绿色
- 已标记的日期不会因为切换选项自动变色,重复点击已标记日期会更新为当前选中选项的颜色
- 日历翻页后已标记的日期样式会自动恢复
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

