R shinydashboard - показать / скрыть несколько пунктов меню на основе ввода пользователя

1

Идея состоит в том, чтобы ввести пользовательский код (код доступа), на основе которого можно получить доступ к различным элементам меню. Таким образом, в основном у нас есть пользовательская версия приложения, доступная по требованию пользователя.

Рабочим примером для 3-х элементов меню является следующее:

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 или даже большее количество элементов меню, поэтому в целом число операторов 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,")'")
    }
})

Я также наткнулся НАСТОЯЩИМ яваскрипт логики, я пытаюсь реализовать. Но я не знаю, как это сделать в Блестящем.

Теги:
shiny
shinydashboard
shinyjs

2 ответа

1
Лучший ответ

Вот идея для динамического роста вашего sidebarMenu с помощью renderUI и uiOutput. Также довольно легко преобразовать в цикл for, если количество вкладок растет.


Изображение 174551

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", value = "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)

Надеюсь это поможет!

  • 0
    Спасибо за это. Хотя я бы хотел оставить пункт меню в панели инструментов на боковой панели.
  • 0
    Так же, как дополнительная информация: это также можно сделать с помощью функции ? RenderMenu shinydashboard . Вот похожий вопрос.
1

Это для будущих читателей.

Флорианский ответ был полезен, но так как я хотел сохранить свой пункт menuItem в 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
  • 0
    Это тоже хорошее решение!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню