Action button not disabling after being enabled with conditional numericInputs

I'm having an issue with the enabling/disabling of my action button. I have several numeric inputs and radio buttons. I have a conditional panel based on a radio button consisting of more numeric inputs and radio buttons. I would like the action button disabled unless all inputs are filled and within range. This works as long as the conditional panel is not activated. If the action button has been enabled, none of the requirements for the conditional panel affect the enabling/disabling of the action button. I am new to R Shiny and am having trouble remedying this issue. Any ideas would be greatly appreciated.

Select UI code:

ui <- fluidPage(
  
  # require shinyjs
  useShinyjs(),
  
  # Sidebar layout with input and output definitions ----
  sidebarLayout(
    
    # Sidebar panel for inputs ----
    sidebarPanel(
      
      # Input: Radio button for sex ----
      radioButtons("sex", ("Sex"),
                   choices = list("Male" = 1, "Female" = 2), selected=character(0)),
      
      # Input: numeric input for age ----
      numericInput("age", ("Age (years)"), value=NULL, min=18, max=80),
      
      # Input: numeric input for SBP ----
      numericInput("sbp", ("Systolic Blood Pressure (mm Hg)"), value=NULL, min=90, max=220),
      
      # Input: numeric input for age ----
      numericInput("dbp", ("Diastolic Blood Pressure (mm Hg)"), value=NULL, min=45, max=100),
      
      # Input: Radio button for bpmeds ----
      radioButtons("bpmeds", ("Taking anti-Hypertension medication"),
                   choices = list("Yes" = 1, "No" = 0), selected=character(0)),
      
      # conditionally display more inputs based on selection of bpmeds
      conditionalPanel(
        condition = "input.bpmeds == 1",
        helpText(helpText("More information is needed to calculate underlying blood pressure")),
        radioButtons("race", "Race", choices=list("White"="white", "Black"="black", "Other"="other"), selected=character(0)),
        radioButtons("hispanic", "Ethnicity", choices=list("Hispanic"=1, "Non-Hispanic"=0), selected=character(0)),
        # numericInput("height", ("Height (cm)"), value=NULL, min=55, max=270),
        splitLayout(numericInput("height_ft", "Height (ft)", value=NULL, min=3, max=7),
                    numericInput("height_in", "(in)", value=NULL, min=0, max=11)),
        numericInput("bmi", ("Body Mass Index"), value=NULL, min=0, max=80),
        numericInput("chol", ("Total Cholesterol (mg/dL)"), value=NULL, min=100, max=1000)
      ),

      actionButton("goButton", "Submit", disabled=TRUE) #,
    ),

Select server code:

server <- function(input, output, session) {

  iv <- InputValidator$new()

  # rules for inputs
  iv$add_rule("age", sv_between(18,80))
  iv$add_rule("sbp", sv_between(90,220))
  iv$add_rule("dbp", sv_between(45,100))
  iv$add_rule("bmi", sv_between(0, 80))
  iv$add_rule("chol", sv_between(100,1000))
  iv$add_rule("height_ft", sv_between(3,7))
  iv$add_rule("height_in", sv_between(0,11))

  iv$enable()

  observe({
    req(iv$is_valid)
    req(input$age, input$sbp, input$dbp, input$bpmeds)
    
    if (input$bpmeds == 1) {
      req(input$race, input$hispanic, input$height_ft, input$bmi, input$chol)
    }
    
    if (!any(is.na(c(input$age, input$sbp, input$dbp, input$bpmeds))) & input$age!="" & input$sbp!="" & input$dbp!="") {
      valid_input_range <- (
        (input$age >= 18 && input$age <= 80 && !input$age=="") &&
          (input$sbp >= 90 && input$sbp <= 220 && !input$sbp=="") &&
          (input$dbp >= 45 && input$dbp <= 100 && !input$dbp=="") &&
          (input$bpmeds == 0 || (
            !any(is.na(c(input$race, input$hispanic, input$height_ft, input$bmi, input$chol))) &&
              (input$height_ft >= 3 && input$height_ft <= 7 && !input$height_ft=="") &&
              (is.na(input$height_in) || (input$height_in >= 0 && input$height_in <= 11)) &&
              (input$bmi >= 0 && input$bmi <= 80 && !input$bmi=="") &&
              (input$chol >= 100 && input$chol <= 1000 && !input$chol=="")
          ))
      )
      
      if (valid_input_range) {
        shinyjs::enable("goButton")
      } else {
        shinyjs::disable("goButton")
      }
    } else {
      shinyjs::disable("goButton")
    }
    
  })
  
  # manually go through each one since the above code only works sometimes
  # SBP
  observe({
    if (is.na(input$sbp) || input$sbp=="") {
      shinyjs::disable("goButton")
    }
  })
  # DBP
  observe({
    if (is.na(input$dbp) || input$dbp=="") {
      shinyjs::disable("goButton")
    }
  })
  # AGE
  observe({
    if (is.na(input$age) || input$age=="") {
      shinyjs::disable("goButton")
    }
  })
  # attempt with BMI (conditional) -- this is not working!
  observe({
    req(iv$is_valid)
    req(input$age, input$sbp, input$dbp, input$bpmeds)
    
    if (input$bpmeds == 1) {
      req(input$race, input$hispanic, input$height_ft, input$bmi, input$chol)
    }
    
    if (input$bpmeds==1 && (is.na(input$bmi) || input$bmi=="")) {
      shinyjs::disable("goButton")
    }
  })

This seems to work as I intuit you intended.

library(shiny)
library(shinyjs)
library(shinyvalidate)
ui <- fluidPage(
  
  # require shinyjs
  useShinyjs(),
  
  # Sidebar layout with input and output definitions ----
  sidebarLayout(mainPanel = div(),
    
    # Sidebar panel for inputs ----
    sidebarPanel(
      
      # Input: Radio button for sex ----
      radioButtons("sex", ("Sex"),
                   choices = list("Male" = 1, "Female" = 2), selected=character(0)),
      
      # Input: numeric input for age ----
      numericInput("age", ("Age (years)"), value=NULL, min=18, max=80),
      
      # Input: numeric input for SBP ----
      numericInput("sbp", ("Systolic Blood Pressure (mm Hg)"), value=NULL, min=90, max=220),
      
      # Input: numeric input for age ----
      numericInput("dbp", ("Diastolic Blood Pressure (mm Hg)"), value=NULL, min=45, max=100),
      
      # Input: Radio button for bpmeds ----
      radioButtons("bpmeds", ("Taking anti-Hypertension medication"),
                   choices = list("Yes" = 1, "No" = 0), selected=character(0)),
      
      # conditionally display more inputs based on selection of bpmeds
      conditionalPanel(
        condition = "input.bpmeds == 1",
        helpText(helpText("More information is needed to calculate underlying blood pressure")),
        radioButtons("race", "Race", choices=list("White"="white", "Black"="black", "Other"="other"), selected=character(0)),
        radioButtons("hispanic", "Ethnicity", choices=list("Hispanic"=1, "Non-Hispanic"=0), selected=character(0)),
        # numericInput("height", ("Height (cm)"), value=NULL, min=55, max=270),
        splitLayout(numericInput("height_ft", "Height (ft)", value=NULL, min=3, max=7),
                    numericInput("height_in", "(in)", value=NULL, min=0, max=11)),
        numericInput("bmi", ("Body Mass Index"), value=NULL, min=0, max=80),
        numericInput("chol", ("Total Cholesterol (mg/dL)"), value=NULL, min=100, max=1000)
      ),
      
      actionButton("goButton", "Submit", disabled=TRUE) #,
    )))

server <- function(input, output, session) {
  
  iv <- InputValidator$new()
  
  # rules for inputs
  iv$add_rule("age", sv_between(18,80))
  iv$add_rule("sbp", sv_between(90,220))
  iv$add_rule("dbp", sv_between(45,100))

  
  iv$enable()
  
  observe({
    req(iv$is_valid)
    valid_input_range <- FALSE
    if (!any(is.na(c(input$age, input$sbp, input$dbp, input$bpmeds))) & input$age!="" & input$sbp!="" & input$dbp!="") {
      t0 <- isTruthy(input$bpmeds == 0)
      t1 <- !any(is.na(c(input$race, input$hispanic, input$height_ft, input$bmi, input$chol)))
      t2 <- isTruthy(input$height_ft >= 3 && input$height_ft <= 7 && !input$height_ft=="")
      t3 <- is.na(input$height_in) || (input$height_in >= 0 && input$height_in <= 11)
      t4 <- isTruthy(input$bmi >= 0 && input$bmi <= 80 && !input$bmi=="")
      t5 <- isTruthy(input$chol >= 100 && input$chol <= 1000 && !input$chol=="")
      valid_input_range <- (
          (t0 || (
            t1 &&
              t2 &&
              t3 &&
              t4 &&
              t5
          ))
      )

      if (valid_input_range) {
        shinyjs::enable("goButton")
      } else {
        shinyjs::disable("goButton")
      }
    } else {
      shinyjs::disable("goButton")
    }
    
  })
}

shinyApp(ui, server)

Amazing, thank you so much for your help! This works as intended.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.