如何在Shiny模块catalog_server内触发observeEvent?
问题解决:将Shiny模块内DT按钮的observeEvent移至模块内部触发
问题原因
Shiny模块拥有独立的命名空间,原按钮的onclick代码直接使用'button'作为输入ID,未绑定模块的命名空间,导致模块内部的input$button无法接收到点击事件。
修改步骤
- 更新按钮生成函数:让
make_button支持接收命名空间参数,生成包含模块命名空间的输入ID。 - 模块内传入命名空间:在
catalog_server中调用make_button时,传入当前模块的命名空间。 - 迁移observeEvent到模块内:将原主server中的
observeEvent移动到catalog_server内部,使用模块的input对象监听事件。
修改后的完整代码
library(data.table) library(dplyr) library(shiny) library(DT) library(htmlwidgets) # 获取数据 get_list_projects <- function(ns) { df <- iris cbind(df, button = sapply(1:nrow(df), make_button("tbl1", ns)), stringsAsFactors = FALSE) } # 按钮HTML生成器:新增ns参数支持命名空间 make_button <- function(tbl, ns){ function(i){ # 用ns()包装inputId,绑定模块命名空间 input_id <- ns("button") sprintf( '<button id="btn_%s_%d" type="button" class="btn btn-light" onclick="%s"><span class="glyphicon glyphicon-search"></span> </button>', tbl, i, sprintf("Shiny.setInputValue('%s', this.id); ", input_id) ) } } catalog_server <- function(input, output, session) { # 获取当前模块的命名空间函数 ns <- session$ns df_list_projects <- shiny::reactiveVal({ # 传入命名空间给数据生成函数 get_list_projects(ns) }) output[["tbl1"]] = DT::renderDT( DT::datatable(df_list_projects(), escape = F) ) # 迁移observeEvent到模块内部 observeEvent(input$button, { row <- strsplit(input$button, "_")[[1]] row <- row[3] showModal(modalDialog( title = paste0("Row ", row, " clicked"), size = "s", easyClose = TRUE, footer = NULL )) }) } 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::tagList( navbarPage(id = "navbar_header", shinyjs::useShinyjs(), waiter::use_waiter(), collapsible = TRUE, tabPanel("Tab1", catalog_ui(id = "catalog_page")))) -> ui server <- function(input, output, session) { shiny::moduleServer(id = "catalog_page", module = catalog_server, session) } shinyApp(ui, server)
关键修改说明
make_button函数新增ns参数,通过sprintf将带命名空间的input_id注入到onclick代码中,确保点击事件发送到模块的input$button。get_list_projects新增ns参数,传递给make_button,保证生成的按钮绑定当前模块的命名空间。- 将
observeEvent直接放在catalog_server内部,使用模块自身的input对象监听事件,无需依赖主server的输入。
内容的提问来源于stack exchange,提问作者Quizicall
相关产品推荐
相关产品推荐

