Shiny模块化后ConditionalPanel失效,如何修复?
修复Shiny模块化中ConditionalPanel失效的问题
问题原因
Shiny模块化后,所有输入输出控件的ID会自动添加模块命名空间前缀(比如你的模块ID是ww,那么plotly1控件的实际ID是ww-plotly1)。但你原来的conditionalPanel里直接用input.plotly1访问输入,JavaScript无法找到这个未带前缀的ID,导致面板无法根据勾选状态显示/隐藏。
修复方案
在conditionalPanel的条件表达式中,使用NS(id, "plotly1")生成带命名空间的正确ID,并用JavaScript的括号语法访问该输入项(因为ID包含横杠,不能用点语法)。
修正后的完整代码
library(shiny) library(plotly) dataset <- mtcars mod_ui <- function(id){ pageWithSidebar( headerPanel("Mtcars"), sidebarPanel(sliderInput(NS(id,'sampleSize'), 'Sample Size', min=10, max=nrow(dataset), value=min(10, nrow(dataset)), step=5, round=0), selectInput(NS(id, 'x'), 'X', names(dataset)), selectInput(NS(id, 'y'), 'Y', names(dataset), names(dataset)[[2]]), selectInput(NS(id, 'color'), 'Color', c('None', names(dataset))), checkboxInput(NS(id, 'smooth'), 'Smooth'), selectInput(NS(id, 'facet_row'), 'Facet Row', c(None='.', names(dataset))), selectInput(NS(id,'facet_col'), 'Facet Column', c(None='.', names(dataset))), hr(), checkboxInput(NS(id, "plotly1"), "Interactive plot!",value = FALSE, width=140), actionButton(NS(id, "plot"), "Plot!") ), mainPanel( plotOutput(NS(id,'plot')), hr(), hr(), # 修复ConditionalPanel的条件表达式 conditionalPanel( condition = paste0("input['", NS(id, "plotly1"), "'] === true"), plotlyOutput(NS(id,"plot2")) ) ) ) } mod_server <- function(id){ moduleServer(id, function(input, output, session){ dataset <- reactive( { mtcars[sample(nrow(mtcars), input$sampleSize),] } ) graph <- reactive({ p <- ggplot(dataset(), aes_string(x=input$x, y=input$y)) + geom_point() if (input$color != 'None') p <- p + aes_string(color=input$color) facets <- paste(input$facet_row, '~', input$facet_col) if (facets != '. ~ .') p <- p + facet_grid(facets) if (input$smooth) p <- p + geom_smooth() p }) |> bindEvent(input$plot) output$plot <- renderPlot({ graph() }) output$plot2 <- renderPlotly({ ggplotly(graph()) }) }) } simApp <- function(){ ui <- shinyUI( mod_ui("ww") ) server <- function(input, output, session){ mod_server("ww") } shinyApp(ui, server) } simApp()
额外说明
顺便修正了代码中gragh的拼写错误为graph,不影响功能但更规范。另外,由于graph响应式对象绑定了input$plot事件,只有点击「Plot!」按钮才会更新图表数据,所以勾选「Interactive plot!」后,需要点击「Plot!」才能加载交互式图表;如果希望勾选后自动更新,可移除bindEvent(input$plot),但这样会随输入控件变化实时更新。
内容的提问来源于stack exchange,提问作者EnriqueGG
相关产品推荐
相关产品推荐

