nimliug
nimliug

Reputation: 435

How to Disable a Button in a Shiny Nested Module?

I am trying to disable an action button inside a Shiny module when a specific radio button value is selected. Specifically, when "Log-normal" ("lnorm") is selected from the radioButtons, the "Go!" button should be disabled. Otherwise, the button should remain enabled.

The main constraint is that the disable / enable button must remain inside module 2, so I cannot move it to module 1

I am using shiny modules and shinyjs for enabling/disabling the button. However, my current implementation does not disable the button as expected. Here is my implementation:

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
    })
    
    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())  # Debugging output to check reactive value
      if (dist() == "lnorm") {
        shinyjs::disable(id = session$ns("btn_go"))  # Trying to disable the button
      } else {
        shinyjs::enable(id = session$ns("btn_go"))
      }
    })
    
    observeEvent(show(), {
      output$plot <- renderPlot({
        plot(runif(10, runif(10)))
      })
    })
    
  })
}

ui <- fluidPage(
  useShinyjs(),  # Required for shinyjs to work
  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)
}

How can I properly disable the "Go!" button when "Log-normal" is selected in this modularized Shiny app?

Upvotes: 2

Views: 29

Answers (1)

Jan
Jan

Reputation: 9468

You can use

shinyjs::disable(id = btn_go_id, asis = TRUE)

Explanation:

  • The button id btn_go_id is already passed into mod_2_server and can be used as it is.

  • asis = TRUE is needed because otherwise the shinyjs function honors the namespace. From ?shinyjs::disable:

    asis
    If TRUE, use the ID as-is even when inside a module (instead of adding the namespace prefix to the ID).

Upvotes: 3

Related Questions