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

如何为Shiny modalDialog中渲染的对象运行observe监听函数?

解决方案

observe()属于Shiny的服务端响应逻辑,不能嵌入到modalDialog()这类UI定义代码中,直接调整你原来注释的observe()逻辑即可实现需求,修复后可以同时覆盖「修改matrix2内容」和「修改periods数值」两个场景的上限校验,不会出现限制失效的问题。

核心改动

将你注释的observe()代码取消注释,补充req(input$matrix2)避免初始化报错即可,修改后的逻辑会自动监听两个触发源:

  • input$periods变化:自动截断matrix2左列所有超出当前上限的数值
  • input$matrix2变化:自动校验新输入的左列数值不超过当前input$periods的取值

完整可运行代码

library(dplyr)
library(ggplot2)
library(shiny)
library(shinyMatrix)

interpol <- function(a, b) { # a = periods, b = matrix inputs
  c <- rep(NA, a)
  c[1] <- b[1]
  c[a] <- b[2]
  c <- approx(seq_along(c)[!is.na(c)], c[!is.na(c)], seq_along(c))$y # << interpolates
  return(c)
}

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      sliderInput('periods', 'Modeled periods (X variable):', min=1, max=10, value=10),
      matrixInput("matrix1", 
                  label = "Matrix 1",
                  value = matrix(c(5), ncol = 1, dimnames = list("Base rate",NULL)),
                  cols =  list(names = FALSE),
                  class = "numeric"),
      
      actionButton("matrix2show","Add scenarios (via Matrix 2)",width = "100%")
    ),
    mainPanel(
      plotOutput("plot")
    )  
  )    
)

server <- function(input, output, session){
  
  observe({ 
    req(input$matrix2)
    tmpMat2 <- input$matrix2
    tmpMat2[,c(TRUE, FALSE)] <- apply(tmpMat2[,c(TRUE, FALSE),drop=FALSE], 2,
                                      function(x) pmin(x, input$periods))
    updateMatrixInput(session,
                      inputId="matrix2",
                      value=tmpMat2
    )
  })
  
  observeEvent(input$matrix1, {
    tmpMat2 <- c(input$matrix2[,1],input$matrix2[,2]) # convert to vector
    tmpMat2[length(input$matrix2)/2+1] <- input$matrix1[,1] # drop matrix 1 value into row 1/col 2 of matrix 2
    updateMatrixInput(session,
                      inputId="matrix2",
                      value=matrix(tmpMat2,ncol=2,dimnames=list(NULL,c("X","Y")))
    )
  })
  
  observeEvent(input$matrix2show,{
    showModal(
      modalDialog(
        matrixInput("matrix2",
                    label = "Matrix 2 (will link to Matrix 1)",
                    value = if(is.null(input$matrix2)){
                      matrix(c(10,5), ncol = 2, dimnames = list(NULL,c("X","Y")))} 
                    else {input$matrix2},
                    rows = list(extend = TRUE, delete = TRUE),
                    class = "numeric"),
        footer = modalButton("Close")
      ))
  })
  
  plotData <- reactive({
    tryCatch(
      tibble(
        X = seq_len(input$periods),
        Y = if(isTruthy(input$matrix2)){interpol(input$periods,input$matrix2)} 
        else {input$matrix1}
      ),
      error = function(e) NULL
    )
  })
  
  output$plot <- renderPlot({
    req(plotData())
    plotData() %>% ggplot() + 
      geom_line(aes(x = X, y = Y)) +
      theme(legend.title=element_blank())
  })
}

shinyApp(ui, server)

内容的提问来源于stack exchange,提问作者Curious Jorge - user9788072

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 07:27:02