Shiny嵌套模块中conditionalPanel命名空间异常问题求助
修复嵌套模块中模态框内conditionalPanel的命名空间问题
问题场景
当子模块直接挂载到根UI时,模态框内的conditionalPanel可以正常工作:输入大于5的数字,"Show Me"文本会正常显示。但将子模块嵌套到父模块后,conditionalPanel的命名空间前缀错误,导致条件判断失效。
正常运行的一级模块代码
library(shiny) library(bslib) # Child module server function childModule <- function(id, run) { moduleServer(id, function(input, output, session) { ns <- session$ns rv <- reactiveValues( show = FALSE ) output$show <- reactive(input$number > 5) outputOptions(output, "show", suspendWhenHidden = FALSE) observeEvent(run(), { showModal(modalDialog( numericInput(ns("number"), "For Numbers >5 the conditionalPanel should show.", value = 5, min = 0, max = 100), conditionalPanel( condition = "output.show == true", ns = NS(id), "Show Me" ), )) }) }) } # UI ui <- page( actionButton("run", "click me") ) # Server server <- function(input, output, session) { childModule("child1", reactive(input$run)) } # Run the app shinyApp(ui, server)
嵌套父模块后出现问题的代码
library(shiny) library(bslib) # Child module server function childModule <- function(id, run) { moduleServer(id, function(input, output, session) { ns <- session$ns rv <- reactiveValues( show = FALSE ) output$show <- reactive(input$number > 5) outputOptions(output, "show", suspendWhenHidden = FALSE) observeEvent(run(), { showModal(modalDialog( numericInput(ns("number"), "For Numbers >5 the conditionalPanel should show.", value = 5, min = 0, max = 100), conditionalPanel( condition = "output.show == true", ns = NS(id), "Show Me" ), )) }) }) } # Parent module UI function parentModuleUI <- function(id) { ns <- NS(id) actionButton(ns("run"), "click me") } # Parent module server function parentModule <- function(id) { moduleServer(id, function(input, output, session) { childModule("child1", reactive(input$run)) }) } # UI ui <- page( parentModuleUI("parent1") ) # Server server <- function(input, output, session) { parentModule("parent1") } # Run the app shinyApp(ui, server)
错误表现
查看HTML代码可见,conditionalPanel的命名空间前缀缺失父模块部分:
<div class="shiny-panel-conditional" data-display-if="output.show == true" data-ns-prefix="child1-" style="display: none;">Show Me</div>
正确的前缀应为parent1-child1-。
问题原因
子模块服务器中,NS(id)仅生成当前子模块的命名空间前缀,没有继承父模块的命名空间。而模块服务器中的session$ns是已经包含完整父-子层级的命名空间函数,应该用它来替代NS(id)。
修复方案
修改子模块中conditionalPanel的ns参数,将NS(id)替换为session$ns:
修复后的完整代码
library(shiny) library(bslib) # Child module server function childModule <- function(id, run) { moduleServer(id, function(input, output, session) { ns <- session$ns rv <- reactiveValues( show = FALSE ) output$show <- reactive(input$number > 5) outputOptions(output, "show", suspendWhenHidden = FALSE) observeEvent(run(), { showModal(modalDialog( numericInput(ns("number"), "For Numbers >5 the conditionalPanel should show.", value = 5, min = 0, max = 100), conditionalPanel( condition = "output.show == true", ns = session$ns, # 替换为session$ns "Show Me" ), )) }) }) } # Parent module UI function parentModuleUI <- function(id) { ns <- NS(id) actionButton(ns("run"), "click me") } # Parent module server function parentModule <- function(id) { moduleServer(id, function(input, output, session) { childModule("child1", reactive(input$run)) }) } # UI ui <- page( parentModuleUI("parent1") ) # Server server <- function(input, output, session) { parentModule("parent1") } # Run the app shinyApp(ui, server)
修复后,conditionalPanel的HTML会生成正确的命名空间前缀parent1-child1-,条件判断即可正常工作。
内容的提问来源于stack exchange,提问作者eastclintw00d
相关产品推荐
相关产品推荐

