Динамически создавать сортируемые меню SubItems в Shinydashboard - PullRequest
4 голосов
/ 03 октября 2019

У меня есть приложение Shiny, использующее пакет shinydashboard, в котором я динамически создаю menuSubItem s в sidebarMenu из dashboardSidebar. Создание подэлементов инициируется кнопкой действия. Я могу просто создать menuSubItem на стороне сервера, но я бы также хотел сделать их сортируемыми, используя пакет sortable и функцию sortable_js. Я просто не могу понять, где разместить функцию sortable_js, чтобы это на самом деле работало.

Вот мой MRE:

library(shiny)
library(shinydashboard)
library(sortable)

# Define UI for shinydashboard
ui <- dashboardPage(
    dashboardHeader(),
    dashboardSidebar(
      sidebarMenu(
        menuItem("tab_one", tabName = "test_body"),
        menuItemOutput("test"),
        id = "sidebar"
      )
    ),
    dashboardBody(
      tabItem("test_body",
              actionButton("click_me", "Click Me"))
    )
  )


# Define server logic to dynamically create menuSubItems
server <- function(input, output) {

  observeEvent(input$click_me, {
    tabs_list <-
      lapply(1:5, function(x) {
        menuSubItem(text = paste("tab", x))
      })

    output$test <- renderMenu({
      menuItem("test_tabs", do.call(tagList, tabs_list))
    })
    sortable_js("test_tabs")
  })
}

# Run the application
shinyApp(ui = ui, server = server)

Любая помощь очень ценится

1 Ответ

4 голосов
/ 16 октября 2019

Функция sortable_js() генерирует HTML, поэтому ее необходимо включить в пользовательский интерфейс. Однако вы также должны убедиться, что он включен после того, как элемент, к которому он применяется, уже существует;иначе это не сработает. Здесь мы можем сделать это, добавив его к выводу вызова renderMenu() в качестве дополнительного дочернего элемента пункта меню, созданного с помощью menuItem():

output$test <- renderMenu({
  menu <- menuItem("test_tabs", do.call(tagList, tabs_list))
  tagAppendChildren(menu, sortable_js("test_tabs"))
})

Теперь идентификатор, который вы даете sortable_js() должен быть CSS-идентификатором элемента, чьи потомки вы хотите сделать сортируемыми. В этом случае это будет элемент ul внутри menuItem(), который содержит все подпункты. К сожалению, нет возможности напрямую установить этот идентификатор при создании пункта меню, поэтому мы должны добавить его по факту. Быстрая проверка исходного кода menuItem() показывает, что тег ul является вторым дочерним элементом тега элемента меню:

output$test <- renderMenu({
  menu <- menuItem("test_tabs", do.call(tagList, tabs_list))
  menu$children[[2]] <- tagAppendAttributes(menu$children[[2]], id = "test_tabs")
  tagAppendChildren(menu, sortable_js("test_tabs"))
})

С этими модификациями ваш пример будет запущен:

library(shiny)
library(shinydashboard)
library(sortable)

# Define UI for shinydashboard
ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(
    sidebarMenu(
      menuItem("tab_one", tabName = "test_body"),
      menuItemOutput("test")
    )
  ),
  dashboardBody(
    tabItem("test_body", actionButton("click_me", "Click Me"))
  )
)

# Define server logic to dynamically create menuSubItems
server <- function(input, output) {
  observeEvent(input$click_me, {
    tabs_list <- lapply(1:5, function(x) {
      menuSubItem(text = paste("tab", x))
    })

    output$test <- renderMenu({
      menu <- menuItem("test_tabs", do.call(tagList, tabs_list))
      menu$children[[2]] <- tagAppendAttributes(menu$children[[2]], id = "test_tabs")
      tagAppendChildren(menu, sortable_js("test_tabs"))
    })
  })
}

# Run the application
shinyApp(ui = ui, server = server)

Создан в 2019-10-16 пакетом Представить (v0.3.0)

...