如何为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
相关产品推荐
相关产品推荐

