shinycssloaders在observeEvent按钮中失效问题求助
Shiny点击Run按钮时显示加载动画的解决方案
方法一:修正shinycssloaders::withSpinner的使用逻辑
你之前的问题出在:点击按钮时res$ults只是更新而非重置为NULL,导致renderTable不会重新进入等待状态,加载器自然不会触发。只需在执行循环前先清空结果,让输出重新触发加载状态。
修改后完整代码
library(shiny) library(ggplot2) library(bslib) library(DT) library(shinycssloaders) ui <- fluidPage( theme = bs_theme(version = 4, bootswatch = "sandstone"), titlePanel("TITLE"), sidebarLayout( sidebarPanel( numericInput("n", "n", value = 100), numericInput("m", "m", value = 50), numericInput("sigma", "sigma", value = 1), numericInput("S2", "S2", value = 2), numericInput("alpha", "alpha", value = 0.05), numericInput("lambda", "lambda", value = 1), numericInput("beta", "beta", value = 0.5), actionButton("runButton", "Run") ), mainPanel( tabsetPanel( tabPanel("Results and chart", # 用withSpinner包裹输出组件 shinycssloaders::withSpinner(tableOutput("results")), shinycssloaders::withSpinner(plotOutput("chart"))), tabPanel("Other") ) ) ) ) server <- function(input, output) { res <- reactiveValues(ults = NULL) observeEvent(input$runButton, { # 先重置结果为NULL,触发加载动画 res$ults <- NULL # 模拟耗时的循环(替换成你的实际生成向量代码) Sys.sleep(3) # 仅用于模拟延迟,实际代码删除此行 Vector <- data.frame( Group = rep(c("A", "B"), input$n/2), Value = rnorm(input$n, input$m, input$sigma) ) res$ults <- Vector }) output$results <- renderTable({ req(res$ults) }, rownames = FALSE, sanitize.text.function = function(x) x) output$chart <- renderPlot({ req(res$ults) ggplot(res$ults, aes(x = Group, y = Value)) + geom_boxplot() }) } shinyApp(ui, server)
关键逻辑说明
点击Run按钮时,先将res$ults设为NULL,此时renderTable和renderPlot会因req(res$ults)进入等待状态,withSpinner自动显示加载动画;循环完成后结果更新,加载器自动消失。
方法二:使用全局模态框作为加载提示
如果需要更醒目的全局加载提示,可以用Shiny自带的模态框实现,无需依赖额外包:
Server部分修改示例
server <- function(input, output) { res <- reactiveValues(ults = NULL) observeEvent(input$runButton, { # 弹出加载模态框 showModal(modalDialog( title = "处理中,请稍候", tags$div(class = "text-center", tags$i(class = "fa fa-spinner fa-spin fa-3x")), footer = NULL, easyClose = FALSE # 禁止用户手动关闭 )) # 模拟耗时循环(替换成你的实际代码) Sys.sleep(3) Vector <- data.frame( Group = rep(c("A", "B"), input$n/2), Value = rnorm(input$n, input$m, input$sigma) ) res$ults <- Vector # 循环结束后关闭模态框 removeModal() }) # 其余输出逻辑同方法一 output$results <- renderTable({ req(res$ults) }, rownames = FALSE, sanitize.text.function = function(x) x) output$chart <- renderPlot({ req(res$ults) ggplot(res$ults, aes(x = Group, y = Value)) + geom_boxplot() }) }
之前方法失败的原因
- 第一种方法:
withSpinner仅在输出组件首次等待数据时触发,你之前未重置res$ults,更新数据时输出组件不会重新进入等待状态,因此加载器不显示。 - 第二种方法:
showPageSpinner()并非shinycssloaders包的API,该包没有此函数,自然无法识别。
内容的提问来源于stack exchange,提问作者strikestack
相关产品推荐
相关产品推荐

