You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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()
  })
}

之前方法失败的原因

  1. 第一种方法:withSpinner仅在输出组件首次等待数据时触发,你之前未重置res$ults,更新数据时输出组件不会重新进入等待状态,因此加载器不显示。
  2. 第二种方法:showPageSpinner()并非shinycssloaders包的API,该包没有此函数,自然无法识别。

内容的提问来源于stack exchange,提问作者strikestack

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 12:13:12