使用visNetwork的visEvents控制Shiny Box折叠展开失败问题排查
问题解决:通过visNetwork节点事件控制Shiny Box折叠/展开
问题根源
你的代码存在两个核心问题:
visEvents()的selectNode/deselectNode参数需要传入前端事件触发时执行的JavaScript代码字符串,但你传入了R端的shinyjs::runjs()调用,这会导致代码在网络渲染时就执行一次,而非节点选择/取消事件触发时执行。- 后续测试中你调用了
openBox('groupedbars'),但目标Box的实际ID是collapse,参数与目标元素不匹配。
修正后的完整代码
1. UI部分(确认脚本引入路径正确)
library(shiny) library(visNetwork) library(shinyjs) library(shinydashboard) ui <- dashboardPage( dashboardHeader(title = "Test visEvents Javascript"), dashboardSidebar(width = 220), dashboardBody( useShinyjs(), tags$head(tags$script(src = "custom.js")), fluidRow( box(id = "network", title = "Network", status = "primary", solidHeader = TRUE, collapsible = TRUE, visNetworkOutput('network')) ), # 节点选择/取消时触发折叠/展开的目标Box fluidRow( box(id = "collapse", title = "Collapse", status = "primary", solidHeader = TRUE, collapsible = TRUE, collapsed = TRUE) ) ) )
2. Server部分(核心修正visEvents参数)
server <- function(input, output, session) { getDiagramPlot <- function(nodes, edges){ v <- visNetwork(nodes, edges) %>% visPhysics(stabilization = TRUE, enabled = TRUE) %>% visOptions(highlightNearest = list(enabled = T, degree = 1, hover = F), autoResize = TRUE, collapse = FALSE) %>% visEdges(color = list(highlight = "red")) %>% visLayout(improvedLayout = TRUE) %>% visEdges(arrows = edges$arrows) %>% visInteraction(multiselect = F) %>% # 直接传入JS函数调用字符串,让前端事件触发时执行 visEvents(selectNode = "openBox('collapse')", deselectNode = "closeBox('collapse')") return(v) } nodes <- data.frame(id = 1:3, label = 1:3) edges <- data.frame(from = c(1,2), to = c(1,3)) output$network <- renderVisNetwork( getDiagramPlot(nodes, edges) ) } shinyApp(ui, server)
3. custom.js文件(保持逻辑不变)
closeBox = function(boxid) { var box = $('#' + boxid).closest('.box'); if (!box.hasClass('collapsed-box')) { box.find('[data-widget=collapse]').click(); } }; openBox = function(boxid) { var box = $('#' + boxid).closest('.box'); if (box.hasClass('collapsed-box')) { box.find('[data-widget=collapse]').click(); } };
关键修正说明
- visEvents参数调整:将R端的
shinyjs::runjs()调用替换为纯JavaScript函数调用字符串,确保节点事件触发时才会执行对应操作。 - ID匹配校验:确保JS函数传入的ID与目标Box的
id属性完全一致,避免因元素查找失败导致无响应。
内容的提问来源于stack exchange,提问作者Corentin Wicht
相关产品推荐
相关产品推荐

