shinyshinydashboardshinyjsvisnetwork

VisNetwork visEvents javascript to uncollapse box


I am trying to use visEvents() selectNode and deselectNode arguments from the visNetwork R package to run a javascript code that would collapse/uncollapse a Shiny box (within fluidRow) based on selected/deselected nodes. The approach is inspired from the following post.

Currently the code runs without errors but the box is not (un)collapsing.

Here is a reproducible code:

library(shiny)
library(visNetwork)
library(shinyjs)

ui <- dashboardPage(
  dashboardHeader(title = "Test visEvents Javascript"),
  dashboardSidebar(width = 220),
  dashboardBody(useShinyjs(),
                tags$head(
                  tags$script(src = "custom.js")), # loading custom javascript functions
  fluidRow(box(id = "network",
               title = "Network",
               status = "primary",
               solidHeader = TRUE, 
               collapsible = TRUE,
               visNetworkOutput('network'))),
  
  # This box should collapse/uncollapse when node is selected/deselected
   fluidRow(box(id = "collapse",
                title = "Collapse",
                status = "primary", 
                solidHeader = TRUE, 
                collapsible = TRUE,
                collapsed = TRUE)),
))

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")) %>% # The colour of the edge linking nodes
      visLayout(improvedLayout = TRUE) %>%
      visEdges(arrows = edges$arrows) %>%
      visInteraction(multiselect = F) %>%
      visEvents(selectNode = shinyjs::runjs("openBox('collapse')"),
                deselectNode = shinyjs::runjs("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)

content of the external custom.js file:

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();
  }
};

I tried replacing

 visEvents(selectNode = shinyjs::runjs("openBox('collapse')"),
                deselectNode = shinyjs::runjs("closeBox('collapse')"))

by

visEvents(selectNode = "openBox('groupedbars')",
          deselectNode = "closeBox('groupedbars')")

but it still doesn't work.


Solution

  • Here is the solution, in case someone may be interested:

    You don’t need shinyjs::runjs() in your visEvent() call. Just define a js function as a text string:

    visEvents(selectNode = "function(){openBox('collapse')}", 
              deselectNode = "function(){closeBox('collapse')}")
    

    If you do not create a function, it will instead only call openBox() and closeBox() at the start when the JS interpreter pass through your file (so it gets triggered when you are trying to define it).