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

如何在Shiny模块catalog_server内触发observeEvent?

问题解决:将Shiny模块内DT按钮的observeEvent移至模块内部触发

问题原因

Shiny模块拥有独立的命名空间,原按钮的onclick代码直接使用'button'作为输入ID,未绑定模块的命名空间,导致模块内部的input$button无法接收到点击事件。

修改步骤

  1. 更新按钮生成函数:让make_button支持接收命名空间参数,生成包含模块命名空间的输入ID。
  2. 模块内传入命名空间:在catalog_server中调用make_button时,传入当前模块的命名空间。
  3. 迁移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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 14:52:17