Shiny应用实时功能与取消按钮实现及切换清空问题求助
修复Shiny应用的模式切换与取消功能问题
核心问题梳理
- 切换手动/实时模式时,结果表格未自动清空
- 取消查询按钮无实际功能,无法终止手动查询或停止实时刷新
- 实时模式下定时器重复创建,导致刷新频率异常
- 实时模式取消后未同步关闭刷新开关
修复后的完整代码
library(shiny) library(shinyjs) library(shinyWidgets) library(lubridate) ui <- fluidPage( useShinyjs(), sidebarPanel( selectInput("fecha", "Fecha", choices = c("Manual", "Tiempo Real")), conditionalPanel("input.fecha == 'Manual'", airDatepickerInput("ini_manual", label = "Fecha Inicio", value = Sys.time() - 3 * (60 * 60), addon = 'none', timepicker = TRUE, firstDay = 1, width = "200px", autoClose = TRUE, timepickerOpts = timepickerOptions(timeFormat = "hh:ii")), airDatepickerInput("fin_manual", label = "Fecha Fin", value = Sys.time(), addon = 'none', timepicker = TRUE, firstDay = 1, width = "200px", autoClose = TRUE, maxDate = NULL, timepickerOpts = timepickerOptions(timeFormat = "hh:ii")) ), conditionalPanel("input.fecha == 'Tiempo Real'", materialSwitch(inputId = "refresh", label = "Tiempo Real", value = TRUE, status = "success") ), actionButton("btnConsulta", "Lanzar Consulta"), actionButton("btnCancelarConsulta", "Cancelar Consulta") ), mainPanel( tableOutput("tablaResultado") ) ) server <- function(input, output, session) { # 用reactiveVal存储查询结果,方便清空和更新 consulta_resultado <- reactiveVal(data.frame()) # 模式切换时清空结果、停止定时器 observeEvent(input$fecha, { consulta_resultado(data.frame()) shinyjs::runjs('if (typeof consultaInterval !== "undefined") clearInterval(consultaInterval);') if (input$fecha == "Tiempo Real") { updateMaterialSwitch(session, "refresh", value = FALSE) } }) # 手动模式查询逻辑 observeEvent(input$btnConsulta, { if (input$fecha == "Manual") { fecha_ini <- input$ini_manual fecha_fin <- input$fin_manual resultado <- data.frame( fecha = as.character(seq.POSIXt(from = fecha_ini, to = fecha_fin, by = "hour")), Valor = rnorm(length(seq.POSIXt(from = fecha_ini, to = fecha_fin, by = "hour"))) ) consulta_resultado(resultado) } }) # 实时模式定时器管理 observe({ if (input$fecha == "Tiempo Real" && input$refresh) { # 先清除已有定时器,避免重复创建 shinyjs::runjs('if (typeof consultaInterval !== "undefined") clearInterval(consultaInterval);') shinyjs::runjs( 'consultaInterval = setInterval(function() { Shiny.setInputValue("real_time_trigger", Math.random(), {priority: "event"}); }, 5000);' ) } else { shinyjs::runjs('if (typeof consultaInterval !== "undefined") clearInterval(consultaInterval);') } }) # 实时模式查询触发 observeEvent(input$real_time_trigger, { if (input$fecha == "Tiempo Real" && input$refresh) { consulta_tiempo_real <- data.frame( fecha = as.character(seq.POSIXt(from = Sys.time(), by = "hour", length.out = 5)), Valor = rnorm(5) ) consulta_resultado(consulta_tiempo_real) } }) # 点击Lanzar Consulta启动实时模式 observeEvent(input$btnConsulta, { if (input$fecha == "Tiempo Real") { updateMaterialSwitch(session, "refresh", value = TRUE) } }) # 取消查询按钮逻辑 observeEvent(input$btnCancelarConsulta, { consulta_resultado(data.frame()) shinyjs::runjs('if (typeof consultaInterval !== "undefined") clearInterval(consultaInterval);') if (input$fecha == "Tiempo Real") { updateMaterialSwitch(session, "refresh", value = FALSE) } }) # 渲染结果表格 output$tablaResultado <- renderTable({ consulta_resultado() }) } shinyApp(ui, server)
关键修改说明
- 模式切换处理:新增
observeEvent监听模式切换,立即清空表格、停止定时器,实时模式下自动关闭刷新开关 - 取消按钮功能:绑定取消按钮逻辑,清空结果、停止定时器,同步关闭实时开关
- 定时器优化:创建定时器前先清除已有实例,避免重复创建导致刷新频率异常
- 结果存储优化:用
reactiveVal存储查询结果,替代原eventReactive,更灵活控制清空和更新 - 实时触发分离:新增独立的
real_time_trigger输入触发实时查询,避免和手动查询的按钮事件冲突
内容的提问来源于stack exchange,提问作者Raq
相关产品推荐
相关产品推荐

