You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Shiny动态UI结合模块化开发无法得到预期输出?

问题原因

你的推测方向正确,问题根源就是模块内动态UI的ID没有匹配模块命名空间:
在Shiny模块的服务端逻辑中,所有自行动态生成的*Output类元素的ID,都需要通过当前模块的session$ns()方法添加模块专属命名空间,才能和服务端output[[id]]的命名规则对应上。你之前的代码中动态生成DT::dataTableOutput(id)时直接使用了原始ID,没有加命名空间,导致前端找不到对应的服务端渲染结果,因此显示为空。

注意:模块服务端内的output[[id]]不需要额外添加命名空间,moduleServer已经自动给output对象封装了模块命名空间,直接使用原始ID即可。

修复后的可运行代码

仅需要修改tab_server函数内renderUI部分的代码即可,完整代码如下:

## library
library(shiny)
library(shinydashboard)
library(datasets)
library(dplyr)
library(DT)

## data
cars <- mtcars
irises <- iris
cars$team <- sample(c("Team1", "Team2"), nrow(cars), replace = TRUE)
irises$team <-
  sample(c("Team1", "Team2"), nrow(irises), replace = TRUE)

## module UI
tab_ui <- function(id) {
  uiOutput(NS(id, "content"))
}

## module Server
tab_server <- function(id, data, Team, var) {
  moduleServer(id, function(input, output, session) {
    table <- reactive({
      data %>% filter(team == Team)
    })

    output$content <- renderUI({
      lapply(sort(unique(table()[[var]])), function(i) {
        id <- paste0("content_", i)

        output[[id]] <-
          DT::renderDataTable(datatable(table()[table()[[var]] == i, ]))

        fluidRow(
          box(
            width = "100%",
            title = paste0(var, " ", i),
            status = "info",
            solidHeader = TRUE,
            collapsible = TRUE,
            # 仅修改了这一行:给output ID套上session$ns
            DT::dataTableOutput(session$ns(id))
          )
        )
      })
    })
  })
}

## UI
ui <- dashboardPage(
  dashboardHeader(title = "Teams"),
  dashboardSidebar(sidebarMenu(
    menuItem("Team 1",
      tabName = "tab_team1"
    ),
    menuItem("Team 2",
      tabName = "tab_team2"
    )
  )),
  dashboardBody(tabItems(
    tabItem(
      tabName = "tab_team1",
      fluidRow(
        tabBox(
          title = "",
          width = "100%",
          tabPanel(
            title = "A",
            tab_ui("team1_tabA")
          ), # module ui
          tabPanel(
            title = "B",
            tab_ui("team1_tabB")
          ) # module ui
        )
      )
    ),
    tabItem(
      tabName = "tab_team2",
      fluidRow(
        tabBox(
          title = "",
          width = "100%",
          tabPanel(
            title = "A",
            tab_ui("team2_tabA")
          ), # module ui
          tabPanel(
            title = "B",
            tab_ui("team2_tabB")
          ) # module ui
        )
      )
    )
  ))
)

## server
server <- function(input, output, session) {

  # module server
  tab_server("team1_tabA", data = cars, Team = "Team1", var = "gear")
  tab_server("team1_tabB", data = irises, Team = "Team1", var = "Species")
  tab_server("team2_tabA", data = cars, Team = "Team2", var = "gear")
  tab_server("team2_tabB", data = irises, Team = "Team2", var = "Species")
}

shinyApp(ui, server)

内容的提问来源于stack exchange,提问作者Xiang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 13:36:03