rshinyjstreeshinytree

shinyTree - run function once tree is expanded


Let's assume I have a minimum working example like

library(shiny)
library(shinyTree)

ui <- fluidPage(
  shinyTree("tree", contextmenu = TRUE, search = TRUE, unique = TRUE, sort = TRUE)
)

server <- function(input, output, session) {
  
  output$tree <- renderTree({
    list(
      root1 = "",
      root2 = list(
        SubListA = list(leaf1 = "", leaf2 = "", leaf3=""),
        SubListB = list(leafA = "", leafB = "")
      ),
      root3 = list(
        SubListA = list(leaf1 = "", leaf2 = "", leaf3=""),
        SubListB = list(leafA = "", leafB = "")
      )
    )
  })
}

shinyApp(ui, server)

which generates a shinyTree (jstree) like

enter image description here

Is it possible to run a function if I click on one of the small triangles on the left when I expand the tree (not necessarily selecting anything). I was thinking about using shinyjs package with onclick event, but did not really manage all that much


Solution

  • You can use the jstree events to trigger a shiny observer to execute a function. In the example below, the JS code will update the value of input$expanded_node with the name of the expanded node, then the associated observer will be triggered.

    library(shiny)
    library(shinyTree)
    
    ui <- fluidPage(
      shinyTree("tree", contextmenu = TRUE, search = TRUE, unique = TRUE, sort = TRUE),
      tags$script(HTML('
        // "triggered when a node is opened and the animation is complete"
        $("#tree").on("after_open.jstree", function (e, data) {
          Shiny.onInputChange("expanded_node", data.node.text, {priority: "event"});
        });
      ')),
      verbatimTextOutput("function_result")
    )
    
    server <- function(input, output, session) {
      
      output$tree <- renderTree({
        list(
          root1 = "",
          root2 = list(
            SubListA = list(leaf1 = "", leaf2 = "", leaf3=""),
            SubListB = list(leafA = "", leafB = "")
          ),
          root3 = list(
            SubListA = list(leaf1 = "", leaf2 = "", leaf3=""),
            SubListB = list(leafA = "", leafB = "")
          )
        )
      })
      
      result <- reactiveValues()
      
      observeEvent(input$expanded_node, {
        # execute a function ...
        result$data <- runif(1, 1, 1e6)
        result$node <- input$expanded_node
      })
      
      output$function_result <- renderPrint({ 
        paste("Node:", result$node, ", Result:", result$data)
      })
    }
    
    shinyApp(ui, server)