Shiny模块开发中动态selectInput()命名空间使用问题咨询
Shiny模块动态UI命名空间配置方案
你的模块化代码无法运行,是三个命名空间相关的错误导致的:
- 模块UI函数内,所有绑定输入输出的元素ID没有全部用
ns()包裹:原代码里numericInput的输入IDn、uiOutput的输出IDres都漏了ns()包装,模块服务端根本无法识别这两个元素 - 服务端
renderUI动态生成的输入组件没有加模块命名空间:静态UI的命名空间是UI渲染时自动加的,但动态生成的UI必须手动用session$ns()包装ID,否则生成的selectInput会被注册到全局命名空间,模块内的input对象读不到这个值 - 输入ID写错:动态生成的
selectInputID是sample-size(中间横杠),后面读取时用的是input$sample_size(中间下划线),ID不匹配自然读不到值
修正后的可运行代码如下:
library(shiny) sampleUI <- function(id){ ns <- NS(id) fluidPage( # 所有模块内静态UI的ID全部用ns()包裹 numericInput(ns("n"), "n", 10), uiOutput(ns("select")), uiOutput(ns("res")) ) } sampleServer <- function(id) { moduleServer(id, function(input, output, session) { output$select <- renderUI({ # 动态生成的UI元素必须用session$ns()包裹ID selectInput( inputId = session$ns("sample_size"), label = "Sample size", choices = 1:input$n ) }) output$res <- renderUI({ renderPrint(rnorm(input$sample_size)) }) }) } ui <- fluidPage( sampleUI("mod1") ) server <- function(input, output, session) { sampleServer("mod1") } shinyApp(ui, server)
核心规则记住两点就不会出错
- 写在模块UI函数里的静态元素(输入、输出绑定),ID一律用
NS(id)生成的ns()函数包裹 - 服务端通过
renderUI、insertUI动态生成的元素,ID一律用当前模块环境下的session$ns()包裹
注:示例用了Shiny 1.5.0版本后推荐的
moduleServer写法代替旧的callModule,这种写法命名空间处理更稳定,不需要手动传递session参数,也避免了很多旧写法的隐式bug。
内容的提问来源于stack exchange,提问作者johannes
相关产品推荐
相关产品推荐

