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

在Shiny模块中点击reactable行触发模态框失效问题

Shiny模块中reactable行点击触发模态框失效的解决方案

问题根源

Shiny模块会自动给内部所有输入、输出和UI元素加上命名空间前缀,非模块环境下写的JS代码直接用原始ID调用,到了模块里就找不到对应的元素或输入,自然触发不了模态框。

关键修复点

  • 模块里所有UI元素的ID必须用NS()/session$ns()包裹,包括模态框的ID
  • reactable的点击事件JS代码里,要把命名空间前缀注入到输入ID和模态框选择器中
  • 关闭模态框的逻辑也要对应加上命名空间前缀

代码示例

非模块正常版本(参考)

library(shiny)
library(reactable)

ui <- fluidPage(
  reactableOutput("table"),
  modalDialog(
    textOutput("row_data"),
    id = "modal",
    footer = actionButton("close_modal", "关闭")
  )
)

server <- function(input, output, session) {
  output$table <- renderReactable({
    reactable(
      mtcars,
      onClick = JS("function(rowInfo) {
        Shiny.setInputValue('row_click', rowInfo.index);
        $('#modal').modal('show');
      }")
    )
  })
  
  output$row_data <- renderText({
    req(input$row_click)
    paste("你点击了第", input$row_click + 1, "行,数据:", toString(mtcars[input$row_click + 1, ]))
  })
  
  observeEvent(input$close_modal, {
    $('#modal').modal('hide')
  })
}

shinyApp(ui, server)

修复后的模块版本

library(shiny)
library(reactable)

# 模块UI
tableModalUI <- function(id) {
  ns <- NS(id)
  tagList(
    reactableOutput(ns("table")),
    modalDialog(
      textOutput(ns("row_data")),
      id = ns("modal"),  # 给模态框ID加命名空间
      footer = actionButton(ns("close_modal"), "关闭")
    )
  )
}

# 模块Server
tableModalServer <- function(id) {
  moduleServer(id, function(input, output, session) {
    ns <- session$ns
    
    output$table <- renderReactable({
      reactable(
        mtcars,
        # 用sprintf把命名空间注入到JS代码里
        onClick = JS(sprintf("function(rowInfo) {
          Shiny.setInputValue('%s', rowInfo.index);
          $('#%s').modal('show');
        }", ns("row_click"), ns("modal")))
      )
    })
    
    output$row_data <- renderText({
      req(input$row_click)
      paste("你点击了第", input$row_click + 1, "行,数据:", toString(mtcars[input$row_click + 1, ]))
    })
    
    observeEvent(input$close_modal, {
      # 关闭模态框也要用带命名空间的选择器
      $(paste0("#", ns("modal"))).modal('hide')
    })
  })
}

# 主应用
ui <- fluidPage(
  tableModalUI("test_module")
)

server <- function(input, output, session) {
  tableModalServer("test_module")
}

shinyApp(ui, server)

说明

核心就是让JS代码里的ID和模块内实际生成的ID完全匹配——模块会把你定义的ID加上类似test_module-的前缀,所以必须通过ns()方法把前缀注入到JS里,不然JS找不到对应的模态框和输入项。

内容的提问来源于stack exchange,提问作者Antônio

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 20:58:15