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

如何点击一次按钮同步加载并处理Shiny已保存的指定输入?

问题解决:单次点击上传恢复Shiny输入值

问题描述

当前代码中,用户上传保存的场景时,需要点击两次Upload按钮才能完全恢复time_window滑块和var_1_input矩阵输入:第一次点击仅恢复滑块值,第二次才能恢复矩阵值。

原因分析

output$Vectors通过renderUI依赖input$time_window动态生成矩阵输入。当调用updateSliderInput修改滑块值后,renderUI会立即触发,用新的滑块值初始化矩阵,直接覆盖了随后调用的updateMatrixInput设置的上传矩阵值。因此第一次点击时矩阵被重新初始化,第二次点击时滑块已为目标值,renderUI不再触发,矩阵才能被正确更新。

解决方案

通过添加状态标记和延迟更新逻辑,确保滑块值更新完成后,再用上传的矩阵值更新输入组件,避免renderUI的初始化覆盖。

修改后的完整代码

library(shiny)
library(shinyMatrix)

matInput <- function(name, x) {
  matrixInput(
    name,
    value = matrix(c(x, 0), 1, 2, dimnames = list(NULL, c("X", "Y"))),
    rows = list(extend = TRUE, names = FALSE),
    cols = list(extend = TRUE, delta = 0, names = TRUE, editableNames = FALSE),
    class = "numeric"
  )
}

matStretch <- function(mat, time_window, col_name) {
  mat[, 1] <- pmin(mat[, 1], time_window)
  df <- data.frame(matrix(0, nrow = time_window, ncol = 1, dimnames = list(NULL, col_name)))
  df[, col_name] <- ifelse(seq_along(df[, 1]) %in% mat[, 1], mat[match(seq_along(df[, 1]), mat[, 1]), 2], 0)
  return(df)
}

ui <- fluidPage(
  actionButton('modal_upload', 'Upload'),
  downloadButton("save_btn", "Save"),
  sliderInput("time_window","Time window (W):", min = 1, max = 10, value = 10),
  uiOutput("Vectors"),
  tableOutput("table2")
)

server <- function(input, output, session) {
  # 新增状态变量:标记上传状态、存储临时矩阵值
  is_uploading <- reactiveVal(FALSE)
  uploaded_matrix <- reactiveVal(NULL)
  
  time_window <- reactive(input$time_window)
  
  output$Vectors <- renderUI({
    matInput("var_1_input", input$time_window)
  })
  
  output$save_btn <- downloadHandler(
    filename = function() paste0("scenario", ".rds"),
    content = function(file) saveRDS(list(var_1_input = input$var_1_input, time_window = input$time_window), file)
  )
  
  observeEvent(input$modal_upload, {
    showModal(modalDialog(fileInput("upload_file_input", "Upload:", accept = c('.rds'))))
  })
  
  # 处理上传:记录矩阵、标记状态、更新滑块
  observe({
    if (!is.null(input$upload_file_input)) {
      uploaded_values <- readRDS(input$upload_file_input$datapath)
      uploaded_matrix(uploaded_values$var_1_input)
      is_uploading(TRUE)
      updateSliderInput(session, "time_window", value = uploaded_values$time_window)
      removeModal()
      # 清空文件输入避免重复触发
      updateFileInput(session, "upload_file_input", NULL)
    }
  })
  
  # 滑块更新完成后再更新矩阵,规避renderUI覆盖
  observeEvent(time_window(), {
    if (is_uploading() && !is.null(uploaded_matrix())) {
      updateMatrixInput(session, "var_1_input", value = uploaded_matrix())
      is_uploading(FALSE)
      uploaded_matrix(NULL)
    }
  })
  
  var_1 <- reactive(input$var_1_input)
  output$table2 <- renderTable(matStretch(var_1(), time_window(), "Var_1"))
}

shinyApp(ui, server)

关键修改点

  • 状态变量:is_uploading标记是否处于上传加载状态,uploaded_matrix临时存储上传的矩阵值
  • 上传逻辑优化:读取文件后先记录矩阵、标记状态,再更新滑块,同时清空文件输入防止重复触发
  • 延迟矩阵更新:监听滑块值变化,确认处于上传状态时再更新矩阵,此时renderUI已完成新矩阵初始化,不会覆盖上传值

效果验证

现在点击一次Upload按钮并选择保存的.rds文件后,滑块值会先更新,随后矩阵输入自动恢复为保存的数值,无需二次点击。

内容的提问来源于stack exchange,提问作者Village.Idyot

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 18:18:38