如何用DRY方式在Shiny中结合shinyjs与bslib实现卡片显隐
优化Shiny卡片显隐逻辑,遵循DRY原则
现有一款Shiny原型应用,可通过input$checkbox实现卡片的显隐切换,但代码存在大量重复逻辑,不符合DRY(Don't Repeat Yourself)原则,难以扩展和维护。需要抽象重复的if ("cardXX" %in% input$checkbox) show("cardXX") else hide("cardXX")调用,同时处理input$checkbox为空时的批量隐藏操作。
原型代码
library(shiny) library(tidyverse) library(bslib) library(shinyjs) cards <- list( card( id = "card1", card_header("Card 1"), plotOutput("card1_plot") ), card( id = "card2", card_header("Card 2"), plotOutput("card2_plot") ), card( id = "card3", card_header("Card 3"), plotOutput("card3_plot") ), card( id = "card4", card_header("Card 4"), plotOutput("card4_plot") ) ) ui <- page_sidebar( useShinyjs(), title = "My Dashboard", sidebar = sidebar( "Controls", checkboxGroupInput("checkbox", "Select Stuff", choices = c("card1", "card2", "card3", "card4"), selected = c("card1", "card2", "card3", "card4")) ), "Main Content Area", fillable = FALSE, cards ) server <- function(input, output) { observeEvent(input$checkbox, { if (is.null(input$checkbox)) hide("card1"); hide("card2"); hide("card3"); hide("card4"); if ("card1" %in% input$checkbox) show("card1") else hide("card1") if ("card2" %in% input$checkbox) show("card2") else hide("card2") if ("card3" %in% input$checkbox) show("card3") else hide("card3") if ("card4" %in% input$checkbox) show("card4") else hide("card4") }, ignoreNULL = FALSE) } shinyApp(ui = ui, server = server)
应用效果:
优化后的代码
library(shiny) library(tidyverse) library(bslib) library(shinyjs) # 统一管理所有卡片ID,后续新增/删除卡片只需修改此处 card_ids <- c("card1", "card2", "card3", "card4") # 批量生成卡片,避免重复编写card()代码 cards <- map(card_ids, function(id) { card( id = id, card_header(str_replace(id, "card", "Card ")), plotOutput(paste0(id, "_plot")) ) }) ui <- page_sidebar( useShinyjs(), title = "My Dashboard", sidebar = sidebar( "Controls", checkboxGroupInput("checkbox", "Select Stuff", choices = card_ids, selected = card_ids) ), "Main Content Area", fillable = FALSE, cards ) server <- function(input, output) { observeEvent(input$checkbox, { # 遍历所有卡片ID,统一处理显隐逻辑 walk(card_ids, function(id) { if (id %in% input$checkbox) { show(id) } else { hide(id) } }) }, ignoreNULL = FALSE) } shinyApp(ui = ui, server = server)
优化说明
- 集中管理卡片ID:将所有卡片ID存入
card_ids向量,避免多处硬编码,后续调整卡片数量只需修改这个向量。 - 批量生成UI组件:用
map()函数遍历卡片ID批量生成卡片,卡片标题、输出ID通过字符串处理动态生成,彻底消除重复的card()定义。 - 抽象显隐逻辑:用
walk()遍历所有卡片ID,统一执行显隐判断逻辑,替代原来重复的if-else语句。当input$checkbox为空时,所有卡片自动进入隐藏分支,无需单独编写空值处理代码。
内容的提问来源于stack exchange,提问作者JasonAizkalns
相关产品推荐
相关产品推荐

