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

Shiny应用中基于组件输入控制操作按钮禁用状态的问题

Shiny应用按钮初始状态修复问题

我开发了一个Shiny应用,期望实现以下功能:

  • 应用首次加载时,所有组件无选中项,操作按钮处于禁用状态;
  • 选择学区(district)后,更新学校(school)选项列表;
  • 至少选中一所学校时,启用「Preview」操作按钮;
  • 仅在点击「Preview」后,启用「Download」操作按钮;
  • 清除所有选中项后,两个操作按钮重新禁用。

目前除「Preview」按钮初始状态为激活(不符合需求1)外,其余功能均已正常实现。

解决方案

问题根源在于observeEvent(input$schools)的初始判断逻辑:应用启动时input$schools的初始值是长度为1的空字符串"",此前仅通过length(input$schools) > 0判断会误判为有效选中,导致「Preview」按钮被错误启用。

只需在判断条件中增加空字符串检查,即可修复该问题。修改后的完整代码如下:

library(renv)
# library(AzureRMR)
# library(AzureStor)
#source(here::here("code/functions/momentmn_functions.R"))
library(dplyr)
library(shiny)
library(shinyWidgets)
library(DT)
library(tidyr)

early <- structure(list(district_name = c("Nonpublic School", "Nonpublic School", 
                                          "Nonpublic School", "Nonpublic School", "Nonpublic School", "Nonpublic School", 
                                          "Nonpublic School", "Nonpublic School", "Nonpublic School", "Nonpublic School", 
                                          "Nonpublic School", "Nonpublic School", "Nonpublic School", "Nonpublic School", 
                                          "Nonpublic School", "Nonpublic School", "Nonpublic School", "Nonpublic School", 
                                          "Nonpublic School", "Nonpublic School", "Nonpublic School", "Nonpublic School", 
                                          "Nonpublic School", "Nonpublic School", "Nonpublic School", "Nonpublic School", 
                                          "Nonpublic School", "Aitkin Public School District", "Minneapolis Public School Dist.", 
                                          "Minneapolis Public School Dist."), school_name_unique = c("Ascension Catholic School 0001-33-012", 
                                                                                                     "Risen Christ 0001-33-015", "St. Helena Catholic School 0001-33-036", 
                                                                                                     "Al-Amal School 0014-31-006", "St. Mary's Mission 0038-31-001", 
                                                                                                     "St. Joseph 0110-31-001", "Immanuel Lutheran School 0113-31-100", 
                                                                                                     "St. Joseph's Catholic 0196-31-007", "St. John The Baptist 0200-31-002", 
                                                                                                     "Our Lady Of Grace 0273-31-007", "St. Henry 0549-31-001", "St. Paul's Lutheran 0549-31-002", 
                                                                                                     "Talmud Torah 0625-31-879", "St. Dominic School 0659-31-012", 
                                                                                                     "Hills Christian 0671-31-001", "St. Paul's Lutheran 0719-31-003", 
                                                                                                     "St. Elizabeth Ann Seton School 0742-31-020", "Prince Of Peace Lutheran School 0742-31-022", 
                                                                                                     "St. Francis Xavier 0748-31-001", "Community Christian 0912-31-001", 
                                                                                                     "Fond Du Lac Ojibwe School 1094-34-030", "Bug-O-Nay-Ge-Shig 1115-34-010", 
                                                                                                     "Circle Of Life 1435-34-010", "Nay-Ah-Shing 1480-34-010", "Sacred Heart Area School 2170-31-001", 
                                                                                                     "St. Anne's 2397-31-001", "St. Mary Of Mt. Carmel 2753-31-002", 
                                                                                                     "Rippleside Elementary 0001-01-002", "Armatage Elementary 0001-03-103", 
                                                                                                     "Lake Harriet Lower Elementary 0001-03-104")), row.names = c(NA, 
                                                                                                                                                                  -30L), spec = structure(list(cols = list(temp_record_id = structure(list(), class = c("collector_character", 
                                                                                                                                                                                                                                                        "collector")), district_number = structure(list(), class = c("collector_character", 
                                                                                                                                                                                                                                                                                                                     "collector")), district_type = structure(list(), class = c("collector_character", 
                                                                                                                                                                                                                                                                                                                                                                                "collector")), school_number = structure(list(), class = c("collector_character", 
                                                                                                                                                                                                                                                                                                                                                                                                                                           "collector")), grade = structure(list(), class = c("collector_character", 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              "collector")), subject = structure(list(), class = c("collector_character", 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "collector")), group_category = structure(list(), class = c("collector_character", 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               "collector")), student_group = structure(list(), class = c("collector_character", 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          "collector")), school_year = structure(list(), class = c("collector_double", 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "collector")), denominator = structure(list(), class = c("collector_double", 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            "collector")), numerator = structure(list(), class = c("collector_double", 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "collector"))), default = structure(list(), class = c("collector_guess", 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         "collector")), delim = ","), class = "col_spec"), class = c("spec_tbl_df", 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     "tbl_df", "tbl", "data.frame"))

all_districts <- unique(sort(early$district_name))
all_schools <- unique(sort(early$school_name_unique))

# Define UI for application that draws a histogram
ui <- fluidPage(
  
  # Application title
  titlePanel("EPC Civic Infrastructure Assessment File Prep"),
  
  # Sidebar with a slider input for number of bins 
  sidebarLayout(
    sidebarPanel(
      h2("Select Schools to Include"),
      shinyWidgets::pickerInput(inputId = "districts",
                                label = "Districts:",
                                choices = all_districts,
                                options = list(`actions-box` = TRUE),
                                multiple = TRUE),
      shinyWidgets::pickerInput(inputId = "schools",
                                label = "Schools:",
                                choices = "",
                                options = list(`actions-box` = TRUE),
                                selected = "",
                                multiple = TRUE),
      shiny::actionButton(inputId = "runButton", label = "Preview", disabled = TRUE),
      shiny::actionButton(inputId = "downButton", label = "Download", disabled = TRUE)),
    
    # Show a plot of the generated distribution
    mainPanel(
      dataTableOutput("early_reading")#,
      
    )
  )
)

# Define server logic required to draw a histogram
server <- function(input, output, session) {
  shiny::observeEvent(input$districts, {
    if(!is.null(input$districts) && length(input$districts) > 0){
      shinyWidgets::updatePickerInput(session = session, inputId = "schools",
                                      choices = early %>% dplyr::arrange(district_name, school_name_unique) %>% dplyr::filter(district_name %in% input$districts) %>% dplyr::select(school_name_unique) %>% unique() %>% pull())
    } else {
      shinyWidgets::updatePickerInput(session = session, inputId = "schools",
                                      choices = "",
                                      options = list(`actions-box` = TRUE),
                                      selected = "")
      shiny::updateActionButton(session, "runButton", disabled = TRUE)
      shiny::updateActionButton(session, "downButton", disabled = TRUE)
    }
  }, ignoreNULL = FALSE)
  
  shiny::observeEvent(input$schools, {
    # 新增空字符串检查,避免初始状态误判
    if(!is.null(input$schools) && length(input$schools) > 0 && input$schools != ""){
      shiny::updateActionButton(inputId = "runButton",
                                disabled = FALSE)
    } else {
      shiny::updateActionButton(inputId = "runButton",
                                disabled = TRUE)
      shiny::updateActionButton(inputId = "downButton",
                                disabled = TRUE)
    }
  }, ignoreNULL = FALSE)  
  
  shiny::observeEvent(input$runButton, {
    if(input$runButton > 0){
      shiny::updateActionButton(inputId = "downButton",
                                disabled = FALSE)
    }
  })
  
  output$early_reading <- renderDataTable({
    
    if(input$runButton == 0){return()}
    else{
      
      early <- early %>%
        dplyr::filter(district_name %in% input$districts, school_name_unique %in% input$schools)
      
      datatable(early)
      
    }
  })
}

# Run the application 
shinyApp(ui = ui, server = server)

修改说明

在observeEvent(input$schools)的启用条件中新增input$schools != ""判断:

  • 应用初始加载时,input$schools的值为长度1的空字符串,新增判断后会识别为无效选中,「Preview」按钮保持禁用状态;
  • 当用户选中有效学校选项时,条件满足,按钮正常启用,不影响原有功能逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 13:15:55