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

如何在Shiny中动态生成argonTabItem并实现标签页正常切换

问题背景

我正在开发基于argonDash的Shiny应用,预期效果如下(静态实现代码):

library(argonDash)
library(argonR)
library(shiny)

ui <- argonDashPage(
  header = argonDashHeader(
    color = "header_custom",
    gradient = TRUE,
    top_padding = 3,
    bottom_padding = 3
  ),
  sidebar = argonDashSidebar(
    id = "app_sidebar",
    vertical = TRUE,
    side = "left",
    size = "md",
    background = "sidebar_custom",
    wellPanel(id = "well_panel", argonDash::argonSidebarMenu(
      shiny::br(),
      argonDash::argonSidebarItem(tabName = "home", "Home", icon = htmltools::tags$i(class = paste0("fa fa-home"))),
      shiny::br(),
      argonDash::argonSidebarItem(tabName = "study_metrics", "Study Metrics",icon = argonR::argonIcon(name = "sound-wave")),
      shiny::br(),
      argonDash::argonSidebarItem(tabName = "demo_app", "Demo App"),
      shiny::br()
    )
    )
  ),
  body = argonDashBody(
    id = "app_body",
    argonTabItems(
      argonTabItem(tabName = "home", p("Test")),
      argonTabItem(tabName = "study_metrics",
        br(),textInput('id_study_metrics', 'text', placeholder = 'study_metrics')
      ),
      argonTabItem(tabName = "demo_app",
        br(),textInput('id_demo_app', 'text', placeholder = 'demo_app')
      )
    )
  ),
  footer = NULL
)

server <- function(input, output, session) {
  
}
shinyApp(ui, server)

(对应效果:正常标签页切换效果)

需求与问题

我需要动态生成以下部分的argonTabItem(因后续该列表会扩展):

argonTabItem(tabName = "study_metrics",
        br(),textInput('id_study_metrics', 'text', placeholder = 'study_metrics')
      ),
      argonTabItem(tabName = "demo_app",
        br(),textInput('id_demo_app', 'text', placeholder = 'demo_app')
      )

我尝试通过以下代码实现动态生成:

library(argonDash)
library(argonR)
library(shiny)

ui <- argonDashPage(
  header = argonDashHeader(
    color = "header_custom",
    gradient = TRUE,
    top_padding = 3,
    bottom_padding = 3
  ),
  sidebar = argonDashSidebar(
    id = "app_sidebar",
    vertical = TRUE,
    side = "left",
    size = "md",
    background = "sidebar_custom",
    wellPanel(id = "well_panel", argonDash::argonSidebarMenu(
      shiny::br(),
      argonDash::argonSidebarItem(tabName = "home", "Home", icon = htmltools::tags$i(class = paste0("fa fa-home"))),
      shiny::br(),
      argonDash::argonSidebarItem(tabName = "study_metrics", "Study Metrics",icon = argonR::argonIcon(name = "sound-wave")),
      shiny::br(),
      argonDash::argonSidebarItem(tabName = "demo_app", "Demo App"),
      shiny::br()
    )
    )
  ),
  body = argonDashBody(
    id = "app_body",
    argonTabItems(
      argonTabItem(tabName = "home", p("Test")),
      uiOutput("apps_ui")
    )
  ),
  footer = NULL
)


server <- function(input, output, session) {
  apps_fns <- c("id_study_metrics", "id_demo_app")
  prefix_removed <- sub("id_", "", apps_fns)
  
  output$apps_ui <- renderUI({
    lapply(seq_along(apps_fns), function(i) {
      argonTabItem(
        tabName = prefix_removed[i],
        br(),
        textInput(apps_fns[i], "text", placeholder = prefix_removed[i])
      )
    })
  })
}

shinyApp(ui, server)

但实现后,所有输入控件都集中显示在同一页面,无法实现标签页的正常切换(效果:异常显示效果)。我尝试过使用tagList等方法,均未解决问题,恳请提供有效的解决方案。

解决方案

问题核心是argonTabItems要求直接将argonTabItem作为子元素,而你把动态生成的标签页放在了uiOutput容器中,导致这些argonTabItem不是argonTabItems的直接子节点,标签切换逻辑无法识别它们。

正确的做法是将整个argonTabItems的内容都动态生成,包括固定的Home标签页,确保所有argonTabItem都是argonTabItems的直接子元素。修改后的代码如下:

library(argonDash)
library(argonR)
library(shiny)

ui <- argonDashPage(
  header = argonDashHeader(
    color = "header_custom",
    gradient = TRUE,
    top_padding = 3,
    bottom_padding = 3
  ),
  sidebar = argonDashSidebar(
    id = "app_sidebar",
    vertical = TRUE,
    side = "left",
    size = "md",
    background = "sidebar_custom",
    wellPanel(id = "well_panel", argonDash::argonSidebarMenu(
      shiny::br(),
      argonDash::argonSidebarItem(tabName = "home", "Home", icon = htmltools::tags$i(class = paste0("fa fa-home"))),
      shiny::br(),
      argonDash::argonSidebarItem(tabName = "study_metrics", "Study Metrics",icon = argonR::argonIcon(name = "sound-wave")),
      shiny::br(),
      argonDash::argonSidebarItem(tabName = "demo_app", "Demo App"),
      shiny::br()
    )
    )
  ),
  body = argonDashBody(
    id = "app_body",
    # 用uiOutput动态生成整个argonTabItems内容
    uiOutput("all_tab_items")
  ),
  footer = NULL
)


server <- function(input, output, session) {
  apps_fns <- c("id_study_metrics", "id_demo_app")
  prefix_removed <- sub("id_", "", apps_fns)
  
  output$all_tab_items <- renderUI({
    # 先创建固定的Home标签页
    tab_items <- list(
      argonTabItem(tabName = "home", p("Test"))
    )
    # 动态添加其他标签页
    dynamic_tabs <- lapply(seq_along(apps_fns), function(i) {
      argonTabItem(
        tabName = prefix_removed[i],
        br(),
        textInput(apps_fns[i], "text", placeholder = prefix_removed[i])
      )
    })
    # 合并所有标签页,传入argonTabItems
    do.call(argonTabItems, c(tab_items, dynamic_tabs))
  })
}

shinyApp(ui, server)

如果希望保留Home标签页在UI中静态定义,也可以通过do.call让动态生成的标签页直接成为argonTabItems的子元素,但全动态生成的方案扩展性更强,更适合后续列表扩展的需求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 15:07:01