如何在R Shiny中用conditionalPanel仅控输入显隐且不中断计算?
问题描述
用户在R Shiny应用中使用conditionalPanel()控制子X/Y表格的显示/隐藏,需求如下:
conditionalPanel()仅负责显示/隐藏侧边栏的子表格输入组件- 无论
checkboxInput()是否勾选,主面板的mainTbl都能正常渲染
当前问题:应用启动时未勾选复选框,mainTbl无法显示;只有勾选后才会出现。
解决方案
核心问题是初始状态下grpInputs$tbl为空,导致依赖它的plus/minus响应式表达式无法正常计算,同时mainTbl的req条件不满足。通过初始化grpInputs$tbl的默认值,并调整相关逻辑即可解决:
修改后的完整代码:
library(shiny) library(rhandsontable) extraFun <- function(input_df, time_win, col_name) { df <- setNames(data.frame(rep(NA, time_win)), col_name) df[,col_name] <- ifelse(seq_along(df[,1])%in%input_df[,1],input_df[match(seq_along(df[,1]),input_df[,1]),2],0) return(df) } ui <- fluidPage( sidebarPanel( h5(strong("Variable (Y) over window (W):")), rHandsontableOutput("parentTbl"), checkboxInput("showCurves", HTML("<b>Add curves</b>"), FALSE), conditionalPanel( condition = "input.showCurves == true", uiOutput("childTbl") ) ), mainPanel(tableOutput("mainTbl")) ) server <- function(input, output, session) { parentVars <- lapply(1:2, function(i) { reactiveValues(data = 2) }) # 初始化grpInputs$tbl,设置默认的A和B表格数据 grpInputs <- reactiveValues(tbl = list( A = data.frame(X = 1, Y = parentVars[[1]]$data), B = data.frame(X = 1, Y = parentVars[[2]]$data) )) plus <- reactive(extraFun(grpInputs$tbl[["A"]],10,"A")) minus <- reactive(extraFun(grpInputs$tbl[["B"]],10,"B")) output$parentTbl <- renderRHandsontable({ rhandsontable( data.frame(Inputs = sapply(parentVars, function(x) x$data)), rowHeaders = c("A","B") ) }) observeEvent(input$parentTbl, { newValues <- hot_to_r(input$parentTbl)$Inputs for (i in 1:2) {parentVars[[i]]$data <- newValues[i]} # 同步更新grpInputs$tbl的默认Y值(当父表格修改时) grpInputs$tbl$A$Y <- parentVars[[1]]$data grpInputs$tbl$B$Y <- parentVars[[2]]$data }) # 构建子X/Y表格 lapply(1:2, function(i) { varInputId <- c("A","B")[i] output[[varInputId]] <- renderRHandsontable({ df <- grpInputs$tbl[[varInputId]] rhandsontable(df, contextMenu = TRUE, rowHeaders = FALSE) }) }) output$childTbl <- renderUI({ lapply(1:2, function(i) { varInputId <- c("A","B")[i] list( h5(strong(paste("Adjust ", varInputId, " (Y) at time X:"))), rHandsontableOutput(varInputId) ) }) }) observe({ lapply(1:2, function(i) { varInputId <- c("A","B")[i] if (!is.null(input[[varInputId]])) { grpInputs$tbl[[varInputId]] <- hot_to_r(input[[varInputId]]) } }) }) amCrs <- reactive({ balances <- cumprod(c(1, 1+plus()[1:10,1]-minus()[1:10,1])) b <- head(balances, -1) result <- data.frame( Begin=b,Add=b*plus()[1:10,1],Subtract=b*minus()[1:10,1],End=balances[-1] ) }) output$mainTbl <- renderTable({ # 移除原有的req条件,因为grpInputs$tbl已初始化 amCrs() }) } shinyApp(ui, server)
关键修改点:
- 初始化
grpInputs$tbl:应用启动时就给A和B设置默认表格数据,确保plus/minus有初始计算依据 - 同步父表格与默认值:当父表格
parentTbl修改时,同步更新grpInputs$tbl中的Y值,保证初始计算和父表格输入一致 - 移除
mainTbl的req限制:因为grpInputs$tbl已初始化,无需再判断长度是否大于0 - 子表格渲染依赖
grpInputs$tbl:子表格直接使用grpInputs$tbl的数据,确保初始显示和父表格一致
内容的提问来源于stack exchange,提问作者Village.Idyot
相关产品推荐
相关产品推荐

