如何在Shiny子模块中点击动态按钮显示隐藏的Tab2?
问题解决方法
你的代码存在两个核心问题:
- 动态按钮的JS代码硬编码了Input ID,未适配模块命名空间,导致模块内的监听事件无法正确触发
- 模块内直接调用
showTab时使用的是模块子Session,无法操作主UI中的navbar_page元素
以下是修改后的完整代码:
library(data.table) library(dplyr) library(shiny) library(DT) # 修改按钮生成函数,接受命名空间ID参数 make_button <- function(ns_id){ function(i){ sprintf( '<button id="btn_tab2_%d" type="button" class="btn btn-light" onclick="%s"><span class="glyphicon glyphicon-search"></span> </button>', i, sprintf("Shiny.setInputValue('%s', this.id);", ns_id)) } } # Catalog server module catalog_server <- function(input, output, session) { ns <- session$ns # 创建项目列表,使用模块命名空间生成按钮的Input ID df_list_projects <- shiny::reactiveVal({ df <- iris cbind(df, button = sapply(1:nrow(df), make_button(ns("button"))), stringsAsFactors = FALSE) }) # 渲染数据表 output[["tbl1"]] = DT::renderDT( DT::datatable(df_list_projects(), escape = F) ) # 创建响应式信号,用于向主Server传递按钮点击事件 button_clicked <- reactive({ input$button }) # 显示弹窗 observeEvent(input$button, { showModal(modalDialog( title = "Showing tab2", size = "s", easyClose = TRUE, footer = NULL )) }) # 返回响应式信号给主Server return(button_clicked) } # Catalog UI module catalog_ui <- function(id) { ns <- NS(id) div(style = "height: 100%", class = "jumbotron", id = ns("project_panel"), shinyWidgets::useSweetAlert(), fluidRow( column(12, column(12, DT::DTOutput(outputId = ns("tbl1"))) ) )) } # Shiny app UI ui <- shiny::tagList( navbarPage(id = "navbar_page", title = "test", collapsible = TRUE, tabPanel("Tab1", catalog_ui(id = "tab1_page")), tabPanel("Tab2", catalog_ui(id = "tab2_page")) )) # Shiny app server server <- function(input, output, session) { # 调用模块并接收按钮点击信号 tab1_button_signal <- shiny::moduleServer(id = "tab1_page", module = catalog_server, session) # 初始隐藏Tab2 shiny::hideTab(inputId = "navbar_page", target = "Tab2", session = session) # 监听模块传来的信号,显示Tab2 observeEvent(tab1_button_signal(), { shiny::showTab(inputId = "navbar_page", target = "Tab2", session = session) }) } # Run the app shinyApp(ui, server)
关键修改点说明
- 适配模块命名空间:修改
make_button函数,让它接收模块的命名空间ID,生成符合Shiny模块规范的Input ID,确保模块内的input$button能正确监听到点击事件 - 分离UI操作逻辑:模块只负责处理弹窗显示和传递点击信号,将
showTab操作移到主Server中执行,因为主Server拥有操作主UI元素的权限 - 响应式信号传递:模块返回一个响应式值,主Server监听该值来触发Tab显示操作,符合Shiny模块的解耦设计原则
内容的提问来源于stack exchange,提问作者Quizicall
相关产品推荐
相关产品推荐

