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

如何基于Shiny单选框响应禁用bslib::navset_tab指定导航面板

问题

能否让“Favorite food”和“Favorite color”这两个nav_panel始终显示在标签栏中,但仅当“Main questions”标签内对应的radioButton选择“Yes”时才可点击?理想效果为:若用户对“是否要回答关于喜爱食物的问题?”选择“No”,则“Favorite food”标签可见但置灰不可点击,“Favorite color”标签同理。已知可根据响应动态增删标签,但更希望标签始终可见,仅根据用户输入启用,类似其他UI框架的标签禁用功能。请问Shiny(搭配bslib)是否支持该功能?若不支持,有无JavaScript或其他替代方案?

解决方案

原生Shiny+bslib的支持情况

目前Shiny和bslib没有直接提供标签禁用的原生API,无法仅通过R代码实现标签可见但不可点击的效果,必须借助JavaScript来实现。

JavaScript实现方案

核心思路:

  • 监听两个单选按钮的变化事件
  • 根据选择结果,给对应的标签添加/移除禁用属性和置灰样式
  • 阻止禁用标签的点击事件,防止切换到该标签

以下是完整实现代码:

library(shiny)
library(bslib)

questionnaire_panel <- function() {
  bslib::card(
    title = "Questionnaire",
    bslib::navset_tab(
      id = "questionnaire_tabs",
      
      # Tab 1: Main questions
      bslib::nav_panel(
        title = "Main questions",
        shiny::radioButtons(
          inputId = "wants_food_question",
          label = tags$b("Do you want to answer a question about your favorite food?"),
          choices = c("No" = "no", "Yes" = "yes"),
          selected = character(0),
          width = "100%"
        ),
        shiny::radioButtons(
          inputId = "wants_color_question",
          label = tags$b("Do you want to answer a question about your favorite color?"),
          choices = c("No" = "no", "Yes" = "yes"),
          selected = character(0),
          width = "100%"
        )
      ),
      
      # Tab 2: Favorite Food(给标签标题加自定义ID方便JS定位)
      bslib::nav_panel(
        title = tags$span(id = "food_tab_title", "Favorite food"),
        shiny::radioButtons(
          inputId = "favorite_food",
          label = tags$b("What is your favorite food?"),
          choices = c(
            "Pizza" = "pizza",
            "Pasta" = "pasta",
            "Sushi" = "sushi",
            "Salad" = "salad",
            "Other" = "other"
          ),
          selected = character(0),
          width = "100%"
        )
      ),
      
      # Tab 3: Favorite Color(给标签标题加自定义ID方便JS定位)
      bslib::nav_panel(
        title = tags$span(id = "color_tab_title", "Favorite color"),
        shiny::radioButtons(
          inputId = "favorite_color",
          label = tags$b("What is your favorite color?"),
          choices = c(
            "Red" = "red",
            "Blue" = "blue",
            "Green" = "green",
            "Yellow" = "yellow",
            "Other" = "other"
          ),
          selected = character(0),
          width = "100%"
        )
      )
    ),
    # 自定义JS脚本
    tags$script(HTML("
      // 更新标签状态的核心函数
      function updateTabStatus() {
        const foodChoice = $('#wants_food_question input:checked').val();
        const colorChoice = $('#wants_color_question input:checked').val();
        
        // 通过标题ID找到对应的标签元素
        const foodTab = $('#food_tab_title').closest('a.nav-link');
        const colorTab = $('#color_tab_title').closest('a.nav-link');
        
        // 处理食物标签的禁用/启用
        if (foodChoice === 'no') {
          foodTab.addClass('disabled').css({'pointer-events': 'none', 'opacity': 0.6});
        } else if (foodChoice === 'yes') {
          foodTab.removeClass('disabled').css({'pointer-events': 'auto', 'opacity': 1});
        }
        
        // 处理颜色标签的禁用/启用
        if (colorChoice === 'no') {
          colorTab.addClass('disabled').css({'pointer-events': 'none', 'opacity': 0.6});
        } else if (colorChoice === 'yes') {
          colorTab.removeClass('disabled').css({'pointer-events': 'auto', 'opacity': 1});
        }
      }
      
      // 监听单选按钮变化,实时更新标签状态
      $('#wants_food_question').on('change', updateTabStatus);
      $('#wants_color_question').on('change', updateTabStatus);
      
      // 页面加载时初始化标签状态
      $(document).ready(updateTabStatus);
    "))
  )
}

# 示例应用
ui <- fluidPage(
  theme = bs_theme(bootswatch = "flatly"),
  questionnaire_panel()
)

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

shinyApp(ui, server)

代码说明

  1. 给两个子标签的标题添加自定义ID,让JavaScript可以精准定位到对应的标签元素
  2. 编写updateTabStatus函数,根据单选按钮的选择结果,给标签添加/移除禁用样式:
    • 利用Bootstrap的disabled类实现基础禁用样式
    • 设置pointer-events: none阻止标签的点击事件
    • 调整opacity实现置灰效果
  3. 监听单选按钮的change事件,实时同步标签状态
  4. 页面加载时执行初始化,确保初始状态符合预期

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 21:18:16