【问题标题】:R shinydashboard - show/hide multiple menuItems based on user inputR shinydashboard - 根据用户输入显示/隐藏多个菜单项
【发布时间】:2019-01-27 12:03:55
【问题描述】:

这个想法是有一个用户输入(访问代码),基于它可以访问不同的菜单项。所以基本上我们有一个基于用户需求的自定义版本的应用程序。

3 个 menuItems 的工作示例如下:

library(shiny)
library(shinydashboard)
library(shinyjs)

ui <- dashboardPage(
                    dashboardHeader(title = "SHOW/HIDE MULTIPLE MENU ITEMS"),
                    dashboardSidebar(
                    useShinyjs(),
                    sidebarMenu(
                        id = "tabs",
                        hidden(
                        menuItem("MENU ITEM 1", tabName = "mi1"),
                        menuItem("MENU ITEM 2", tabName = "mi2"),
                        menuItem("MENU ITEM 3", tabName = "mi3")
                        ),
                        textInput(inputId = "accessToken", label = "Access Code", value = "Show/Hide Menu Items.")
                    )
                    ),
                    dashboardBody()

)

server <- function (input, output, session){
observeEvent(input$accessToken,{
    if(input$accessToken == "001"){
    hide(selector = "ul li:eq(0)")
    hide(selector = "ul li:eq(1)")
    show(selector = "ul li:eq(2)")
    } else if (input$accessToken == "010"){
        hide(selector = "ul li:eq(0)")
        show(selector = "ul li:eq(1)")
        hide(selector = "ul li:eq(2)")
    } else if (input$accessToken == "011"){
        hide(selector = "ul li:eq(0)")
        show(selector = "ul li:eq(1)")
        show(selector = "ul li:eq(2)")
    } else if (input$accessToken == "100"){
        show(selector = "ul li:eq(0)")
        hide(selector = "ul li:eq(1)")
        hide(selector = "ul li:eq(2)")
    } else if (input$accessToken == "101"){
        show(selector = "ul li:eq(0)")
        hide(selector = "ul li:eq(1)")
        show(selector = "ul li:eq(2)")
    } else if (input$accessToken == "110"){
        show(selector = "ul li:eq(0)")
        show(selector = "ul li:eq(1)")
        hide(selector = "ul li:eq(2)")
    } else if (input$accessToken == "111"){
        show(selector = "ul li:eq(0)")
        show(selector = "ul li:eq(1)")
        show(selector = "ul li:eq(2)")
    } else{
    hide(selector = "ul li") 
    }
})
}

shinyApp(ui, server)

这对于唯一访问代码可见的 3 个菜单项的所有组合都非常有效。

但是正如您所见,这是用于访问 3 个菜单项的大量重复代码。

实际上我有 10 个甚至更多的 menuItems,所以总体上 if else 语句的数量将呈指数级增长。

我已经尝试过:

我想过这个逻辑:对于 10 个菜单项,有一个 10 位的访问码,其中每个位的值可以是 0(隐藏)或 1(显示)。

observeEvent(input$accessToken, {
    tokenStr <- input$accessToken
    tokenStrShow <- which(strsplit(tokenStr, "")[[1]]=="1")
    tokenStrHide <- which(strsplit(tokenStr, "")[[1]]=="0")
    for (i in tokenStrShow){
        # some logic to show all menuItems with value 1
        # FOLLOWING DOESNOT WORK
        # paste0("show(selector='ul li:eq(",i,")'")
    }
})

我还遇到了我正在尝试实现的THIS javascript 逻辑。但我不知道如何在 Shiny 中做到这一点。

【问题讨论】:

    标签: javascript r shiny shinydashboard shinyjs


    【解决方案1】:

    这是一个使用renderUIuiOutput 动态增长sidebarMenu 的想法。如果选项卡数量增加,转换为 for 循环也相当简单。


    library(shiny)
    library(shinydashboard)
    library(shinyjs)
    
    ui <- dashboardPage(
      dashboardHeader(title = "SHOW/HIDE MULTIPLE MENU ITEMS"),
      dashboardSidebar(
        useShinyjs(),
        uiOutput('sidebar'),
        textInput(inputId = "accessToken", label = "Access Code", placeholder = "Show/Hide Menu Items.")
      ),
      dashboardBody()
      
    )
    
    server <- function (input, output, session){
      
      output$sidebar <- renderUI({
        
        menu_items = list()
        
        if(substr(input$accessToken,1,1)=='1')
          menu_items[[length(menu_items)+1]] = menuItem("MENU ITEM 1", tabName = "mi1")
        
        if(substr(input$accessToken,2,2)=='1')
          menu_items[[length(menu_items)+1]] = menuItem("MENU ITEM 2", tabName = "mi2")
        
        if(substr(input$accessToken,3,3)=='1')
          menu_items[[length(menu_items)+1]] = menuItem("MENU ITEM 3", tabName = "mi3")
        
        print(menu_items)
        
        sidebarMenu(id = "tabs",menu_items)
    
      })
    }
    
    shinyApp(ui, server)
    

    希望这会有所帮助!

    【讨论】:

    • 谢谢。虽然我希望我可以将 menuItem 保留在 dashboardSidebar 中。
    • 正如附加信息:这也可以使用 shinydashboard 的 ?renderMenu 函数来完成。 Here 是一个类似的问题。
    【解决方案2】:

    这是为未来的读者准备的。

    弗洛里安的回答很有帮助,但因为我想将我的 menuItems 保留在 dashboardSidebar 中。 我花了一些时间才意识到我错误地使用了paste0

    我最终使用了以下内容:

    observeEvent(input$accessToken, {
     tokenStr <- strsplit(input$accessToken, "")[[1]]
     tokenLen <- length(tokenStr)
    
     if(tokenLen == 3){
      tokenStrShow <- which(tokenStr=="1")
      tokenStrHide <- which(tokenStr=="0")
      for (i in tokenStrShow){
        show(selector= paste0("ul li:eq(",i - 1,")"))
      } 
      for (i in tokenStrHide){
        hide(selector= paste0("ul li:eq(",i - 1,")"))
      }
    }
    

    })

    这种方法的优点是:

    • 我能够保持仪表板边栏不变。 (这是我的项目所需要的)
    • 可轻松扩展以适应越来越多的菜单项。 (只需要编辑tokenLen

    【讨论】:

    • 这也是一个不错的解决方案!
    • @Urvah Shabbir 您是如何找到必须解析为hide()show() 的文本(“ul li:eq(x)”)的?因为在 shinydashboardPlus() 它隐藏了其他元素。
    猜你喜欢
    • 2021-12-23
    • 1970-01-01
    • 2017-02-20
    • 2012-08-11
    • 1970-01-01
    • 2013-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多