Search code examples
javascriptrshinynodes

Js technicue to capture clicks in a shiny app does not capture node id


I have the shiny app below in which I use a js technique to capture clicks in the app without having to use shiny input elements. It works great but not on nodes as I want to be able to capture nodes and get the node ID.

The logic is the following: I click on "Click me" text or on the nodes then in Rstudio console I type input$js.node_clicked. The result should be "one_1" which I can accept ase "one" corresponds to node and "_1" on clicking sequence. But when I click on nodes I get only "_1" and not the node id "one_1". The logic is from here.

library(shiny)
library(shinyWidgets)
library(DiagrammeR)
library(magrittr)

js <- '
$(document).on("click", ".node", function(e) {
if(typeof BUTTON_CLICK_COUNT == "undefined") {
BUTTON_CLICK_COUNT = 1;
} else {
BUTTON_CLICK_COUNT ++;
}
Shiny.onInputChange("js.node_clicked",
e.target.id + "_" + BUTTON_CLICK_COUNT);
});
'

ui <- fluidPage(
  tags$script(HTML(js))
  ,
  div(id="one","click me",class="node")
  ,
  uiOutput("main")
)

server <- function(input, output) {
  
  output$main <- renderUI({
    tagList(
      div(
        grVizOutput("grr", width = "100%", height = "90vh")
      ))
    
  })
  
  output$grr <- renderGrViz(grViz( "digraph test{
A[tooltip='A word'];
B[tooltip='Another word'];
A -> B;}" )
  )
  
  observeEvent(input$js.node_clicked , {
    browser()
  }) #
  
}

shinyApp(ui, server)

Solution

  • This works like this. You have to use currentTarget instead of target. Avoid to include a dot in the input name of Shiny.setInputValue (or Shiny.onInputChange, which is the same), because the dot has a special meaning.

    library(shiny)
    library(shinyWidgets)
    library(DiagrammeR)
    library(magrittr)
    
    js <- '
    $(document).on("click", ".node", function(e) {
      if(typeof BUTTON_CLICK_COUNT === "undefined") {
        BUTTON_CLICK_COUNT = 1;
      } else {
        BUTTON_CLICK_COUNT++;
      }
      Shiny.setInputValue("js_node_clicked",
        e.currentTarget.id + "_" + BUTTON_CLICK_COUNT);
    });
    '
    
    ui <- fluidPage(
      tags$script(HTML(js)),
      
      div(id="one", "click me", class="node"),
      
      uiOutput("main")
    )
    
    server <- function(input, output) {
      
      output$main <- renderUI({
        tagList(
          div(
            grVizOutput("grr", width = "100%", height = "90vh")
          )
        )
      })
      
      output$grr <- renderGrViz(grViz( "digraph test{
    A[tooltip='A word'];
    B[tooltip='Another word'];
    A -> B;}" )
      )
      
      observeEvent(input$js_node_clicked , {
        print(input$js_node_clicked)
      }) 
      
    }
    
    shinyApp(ui, server)