带有条件面板的闪亮仪表板中的动态菜单

Dynamic menu in shinydashboard with conditionalPanel

背景

我正在尝试开发一个应用程序,它有一个登录屏幕,并根据用户的权限显示不同的菜单。

用户权限是分层的,这意味着 Read + Write 用户应该拥有与 Read 用户相同的权限以及一些额外的权限。

我现在正在纠结如何创建这个动态菜单。我阅读了 this document on dynamic UIs,我希望我可以纯粹通过使用 conditionalPanel 调用来实现我的目标。

在下面的代码中,您会发现有很多重复项。最糟糕的是,我必须为 tabs 分配唯一的名称,即使它们位于不同的(互斥的)面板(a1a2)中,但它们的目的恰恰是一样。

到目前为止已经尝试过

我试图将 conditionalPanel 移动到 sidebarMenu(和 tabItems 分别),但随后出现错误,因为 return 类型 conditionalPanel 与预期类型不匹配。

预期结果

最后,我希望代码重复最少。也就是说,我想为 Do ADo B 定义 一次 ,但是 重新使用 Do A 两个用户。

我有哪些选择?我是否必须回退到动态渲染 (renderUI / renderMenu) 或有什么方法可以仅使用 conditionalPanel 实现所需的行为?

有重复的工作代码

library(shiny)
library(shinydashboard)

ui <- dashboardPage(
   dashboardHeader(),
   dashboardSidebar(
      selectInput("userrights", label = "User Rights:", 
                   choices = c("Read + Write", "Read")),
      conditionalPanel("input.userrights == 'Read'",
                       sidebarMenu(
                          menuItem("Do A", tabName = "a1")
                       )
      ),
      conditionalPanel("input.userrights == 'Read + Write'",
                       sidebarMenu(
                          ## unnecessary duplication + I need yet another tab 'a2'
                          menuItem("Do A", tabName = "a2"),
                          menuItem("Do B", tabName = "b2")
                       )
      )
   ),
   dashboardBody(
      conditionalPanel("input.userrights == 'Read'",
                       tabItems(
                          tabItem("a1", h1("A was done"))
                       )
      ),
      conditionalPanel("input.userrights == 'Read + Write'",
                       tabItems(
                          tabItem("a2", h1("A was done")),
                          tabItem("b2", h1("B was done"))
                       )
      )
   )
)

server <- function(input, output) {}

runApp(shinyApp(ui, server))

片段:不工作但至少 w/o 重复

sidebarMenu(
   menuItem("Do A", tabName = "a")
   conditionalPanel("input.userrights == 'Read + Write'",
      menuItem("Do B", tabName = "b")
   )
)

您可以根据用户输入或其他条件在服务器中呈现您的菜单,并将其输出到 UI。下面的工作示例:

library(shiny)
library(shinydashboard)

ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(
    selectInput("userrights", label = "User Rights:", 
                choices = c("Read + Write", "Read")),
    sidebarMenuOutput("menu")
  ),
  dashboardBody(
    tabItems(
      tabItem("a", h1("A was done")),
      tabItem("b", h1("B was done"))
    )
  )
)

server <- function(input, output) {


  output$menu <- renderMenu({

    my_list = list(menuItem("a", tabName="a"))

    if(input$userrights=="Read + Write")
       my_list[[2]] = menuItem("b", tabName="b")

    sidebarMenu(my_list)

  })

}

runApp(shinyApp(ui, server))

希望对您有所帮助!