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

如何在Shiny嵌套模块中按单选框值禁用Go按钮(逻辑留子模块)

解决Shiny模块化应用中跨模块禁用按钮的问题

问题说明

需要实现:当单选框选中“Log-normal”(对应值lnorm)时,禁用模块1中的“Go!”按钮;选择其他选项时保持按钮启用。核心约束是禁用/启用逻辑必须保留在模块2中,不能移到模块1。当前使用Shiny模块+shinyjs的实现无法正常生效。

问题根源

模块2中错误地使用了自身的命名空间生成按钮ID(session$ns("btn_go")),但目标按钮属于模块1的命名空间。实际上你已经通过btn_go_id参数把正确的按钮ID传递给了模块2,只是没有在逻辑中使用这个参数。

修正后的完整代码

library(shiny)
library(shinyjs)

mod_1_ui <- function(id) {
  ns <- NS(id)
  
  fluidRow(
    column(
      width = 3,
      radioButtons(
        ns("dist"),
        "Distribution type:",
        c(
          "Normal" = "norm",
          "Uniform" = "unif",
          "Log-normal" = "lnorm",
          "Exponential" = "exp"
        )
      ),
      actionButton(
        inputId = ns("btn_go"),
        label = "Go !",
        icon = icon("play")
      )
    ),
    column(
      width = 9,
      mod_2_ui(ns("display_plot"))
    )
  )
}

mod_1_server <- function(id, r_global) {
  moduleServer(id, function(input, output, session) {
    show <- reactive({
      input$btn_go
    })
    
    # 传递正确的按钮命名空间ID给模块2
    mod_2_server("display_plot", show = show, btn_go_id = session$ns("btn_go"), dist = reactive({ input$dist }))
  })
}

mod_2_ui <- function(id) {
  ns <- NS(id)
  
  plotOutput(outputId = ns("plot"))
}

mod_2_server <- function(id, show, btn_go_id, dist) {
  moduleServer(id, function(input, output, session) {
    
    observeEvent(dist(), {
      print(dist())  # 调试用:查看当前选中的分布值
      if (dist() == "lnorm") {
        shinyjs::disable(id = btn_go_id)  # 使用传入的正确按钮ID
      } else {
        shinyjs::enable(id = btn_go_id)   # 使用传入的正确按钮ID
      }
    })
    
    observeEvent(show(), {
      output$plot <- renderPlot({
        plot(runif(10, runif(10)))
      })
    })
    
  })
}

ui <- fluidPage(
  useShinyjs(),  # 必须加载shinyjs
  mod_1_ui("mod")
)

server <- function(input, output, session) {
  r_global <- reactiveValues()
  
  mod_1_server("mod", r_global = r_global)
}

if (interactive()) {
  shinyApp(ui, server)
}

关键修改点

  • 在模块2的observeEvent(dist(), ...)逻辑中,不再使用模块自身的命名空间生成按钮ID,而是直接使用传入的btn_go_id参数,该参数已经是模块1命名空间下的正确按钮ID。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 02:37:41