基于外部数据在Shinydashboard的tabItem中动态生成对应数量的box组件
解决Shinydashboard动态生成Tab对应Box的问题
没问题,我帮你调整代码,实现每个Tab页面根据dat里的配置动态生成对应数量的Box,并且把box_name作为标题、box_desc作为内容。
核心思路
- 动态生成侧边栏菜单:避免硬编码,根据
dat中的唯一category自动生成menuItem,后续新增分类无需手动修改。 - 按分类生成对应Box:对每个分类筛选出对应的行,遍历生成每个
box()元素,再将它们组织到页面中。
修改后的完整代码
library(shiny) library(shinydashboard) library(dplyr) # 用来分组/筛选数据 dat <- tibble::tibble( category = c("blue", "blue", "green", "green", "green"), box_name = c("Box A", "Box B", "Box C", "Box D", "Box E"), box_desc = c("Foo", "Bar", "Bar", "Foo", "Foo") ) ui <- dashboardPage( dashboardHeader(), dashboardSidebar( uiOutput("dynamic_sidebar") # 动态生成侧边栏菜单 ), dashboardBody( uiOutput("render_reports") ) ) server <- function(input, output) { # 动态生成侧边栏菜单 output$dynamic_sidebar <- renderUI({ menu_items <- lapply(unique(dat$category), function(cat) { # 把分类名首字母大写作为菜单显示文本 menuItem( text = stringr::str_to_title(cat), tabName = cat, icon = icon("dashboard") ) }) do.call(sidebarMenu, menu_items) }) # 动态生成每个Tab的内容 output$render_reports <- renderUI({ # 遍历每个唯一分类 tabs <- lapply(unique(dat$category), function(cat) { # 筛选当前分类下的所有box数据 cat_boxes <- dat %>% filter(category == cat) # 生成当前分类的所有box元素 box_list <- lapply(1:nrow(cat_boxes), function(i) { box( title = cat_boxes$box_name[i], content = cat_boxes$box_desc[i], width = 4, # 一行放3个box,可根据需求调整width(1-12) solidHeader = TRUE, status = ifelse(cat == "blue", "primary", "success") # 不同分类用不同状态色 ) }) # 将box列表放到fluidRow里(自动换行) tabItem( tabName = cat, fluidRow(box_list) ) }) # 组合所有tabItem成tabItems do.call(tabItems, tabs) }) } shinyApp(ui, server)
关键说明
- 动态侧边栏:用
uiOutput和renderUI生成sidebarMenu,自动读取dat里的分类,不用硬编码每个menuItem。 - Box生成逻辑:对每个分类筛选数据后,用
lapply遍历每行生成对应的box(),指定了width=4让一行显示3个Box(Bootstrap的栅格系统,总宽度12),你可以根据需要调整这个值。 - 状态色区分:给不同分类的Box设置了不同的
status(blue用primary,green用success),让页面视觉区分更明显,也可以自定义其他状态色比如warning、danger。 - 文本格式化:用
stringr::str_to_title把分类名首字母大写,让菜单显示更美观(比如"blue"变成"Blue")。
这样运行后,Blue页面会显示2个Box,Green页面显示3个Box,每个Box的标题和内容都是从dat里读取的,完全符合你的需求!
内容的提问来源于stack exchange,提问作者Simon
相关产品推荐
相关产品推荐

