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

如何在Shiny中将shinytree数据转为层级下拉输入组件?

实现自定义层级下拉框替代shinytree并传递选中值

我明白你的需求:想把shinytree展示的层级列表改成自定义下拉框的形式,同时保留选中值的传递功能。下面我给你一个完整的解决方案,用shinyWidgets的pickerInput来实现(它自带层级支持,而且容易自定义样式),同时适配你现有的数据源逻辑。

完整可运行代码

library(shiny)
library(shinyTree)
library(shinyWidgets)

# Define UI for application:
ui <- fluidPage(
  # 自定义下拉框样式,强化层级缩进效果
  tags$style(HTML("
    .bs-select .dropdown-menu li ul {
      padding-left: 18px;
    }
    .bs-select .dropdown-menu li a {
      white-space: nowrap;
      padding: 6px 12px;
    }
    .bs-select .dropdown-toggle {
      width: 100%;
    }
  ")),
  sidebarLayout(
    sidebarPanel(width = 3,
                 # 自定义层级下拉框,替换原shinytree组件
                 pickerInput(
                   inputId = "customDropdown",
                   label = "层级选择",
                   choices = NULL,
                   multiple = TRUE, # 对应原shinytree的checkbox=True
                   options = list(
                     `actions-box` = TRUE,
                     `selected-text-format` = "count > 3",
                     `live-search` = TRUE,
                     `treeview` = TRUE, # 开启层级树视图模式
                     `show-tick` = TRUE
                   )
                 ),
                 verbatimTextOutput("selected")
    ),
    mainPanel(width = 9)
  )
)

# Define server logic:
server <- function(input, output, session){
  observe({
    df <- data.frame(
      child= c('a','b','c','d','e','f','g','h'),
      parent = c('f','f','f','g','h','i','i','i'))
    
    # 用shinytree函数生成原始树结构
    tree <- FromDataFrameNetwork(df)
    filtered_value <- as.list(tree)
    filtered_value <- filtered_value[-1] # 移除根节点'i'的外层包裹
    
    # 递归转换树结构为pickerInput兼容的层级选项格式
    convertTreeToChoices <- function(tree_list, parent_label = "") {
      choices_list <- list()
      for (node_name in names(tree_list)) {
        current_label <- if(parent_label == "") node_name else paste(parent_label, node_name, sep = " > ")
        if(is.list(tree_list[[node_name]])) {
          # 处理子节点,递归生成层级选项
          sub_choices <- convertTreeToChoices(tree_list[[node_name]], current_label)
          choices_list[[current_label]] <- sub_choices
        } else {
          # 处理叶子节点,直接添加为选项
          choices_list[[current_label]] <- node_name
        }
      }
      return(choices_list)
    }
    
    dropdown_choices <- convertTreeToChoices(filtered_value)
    
    # 更新下拉框的选项内容
    updatePickerInput(
      session = session,
      inputId = "customDropdown",
      choices = dropdown_choices
    )
  })
  
  # 输出选中的值,和原shinytree的输出逻辑一致
  output$selected <- renderPrint({
    input$customDropdown
  })
}

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

关键部分说明

1. 下拉框组件选择

用shinyWidgets::pickerInput替代shinyTree,它原生支持层级树视图(通过treeview = TRUE开启),同时提供多选、搜索、选中计数等功能,完美匹配原shinytree的复选框模式需求。

2. 树结构转下拉选项

我写了一个convertTreeToChoices递归函数,把FromDataFrameNetwork生成的树结构转换成pickerInput需要的层级格式:

  • 父节点作为分组标签,子节点自动缩进显示
  • 叶子节点直接作为可选择的选项

3. 样式自定义

添加了CSS样式优化下拉框的视觉效果,你可以根据需求调整缩进距离、按钮宽度、选项内边距等样式,打造完全自定义的下拉框外观。

4. 值传递逻辑

input$customDropdown会返回所有选中的选项值,和原input$Tree的返回逻辑一致,你可以直接在后续的业务逻辑中使用这个值,完全兼容原代码的输出需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 17:49:10