[英]Dynamically create sortable menuSubItems in shinydashboard
I have a Shiny app using the shinydashboard
package in which I'm dynamically creating menuSubItem
s in the sidebarMenu
of a dashboardSidebar
.我有一个 Shiny 应用程序,它使用shinydashboard
package 在其中我在dashboardSidebar
的sidebarMenu
中动态创建menuSubItem
。 The creation of the subItems is triggered by an actionButton. subItems 的创建由 actionButton 触发。 I can create the menuSubItem
s on the server side just fine, but I would like to also make them sortable using the sortable
package and sortable_js
function.我可以在服务器端创建menuSubItem
就好了,但我也想使用可排序的 package 和sortable
function 使它们可sortable_js
。 I just can't seem to figure out where to place the sortable_js
function to make this actually work, though.不过,我似乎无法弄清楚将sortable_js
function 放在哪里才能使其真正起作用。
Here's my MRE:这是我的 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)
Any help is much appreciated任何帮助深表感谢
The sortable_js()
function generates HTML, so it'll need to be included in the UI. sortable_js()
function 生成 HTML,所以它需要包含在 UI 中。 However, you also have to make sure it is included after the element that it applies to already exists;但是,您还必须确保它包含在它适用的元素已经存在之后; it won't work otherwise.否则它将无法正常工作。 Here, we can accomplish that by adding it to the output of the renderMenu()
call as an additional child of the menu item created with menuItem()
:在这里,我们可以通过将其添加到renderMenu()
调用的 output 作为使用menuItem()
创建的菜单项的附加子项来实现:
output$test <- renderMenu({
menu <- menuItem("test_tabs", do.call(tagList, tabs_list))
tagAppendChildren(menu, sortable_js("test_tabs"))
})
Now, the id that you give to sortable_js()
has to be the CSS id of the element whose children you want to make sortable.现在,您提供给sortable_js()
的 id 必须是要使其子元素可排序的元素的 CSS id。 In this case, that would be the ul
element inside the menuItem()
, which contains all of the sub-items.在这种情况下,这将是menuItem()
中的ul
元素,其中包含所有子项。 Unfortunately there is no way to directly set this id when creating the menu item, so we have to inject it after the fact.不幸的是,在创建菜单项时没有办法直接设置这个id,所以我们必须在事后注入它。 A quick inspection of the menuItem()
source code reveals that the ul
tag is the second child of the menu item tag:快速查看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"))
})
With these modifications, your example will be up and running:通过这些修改,您的示例将启动并运行:
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)
Created on 2019-10-16 by the reprex package (v0.3.0)由reprex package (v0.3.0) 于 2019 年 10 月 16 日创建
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.