JS Plumb in React

Posted By : Akshay Singh | 30-Dec-2020

JS Plumb in React

Flowcharting & drawing lines on html using jsPlumb


Time for more & more AI & AR web apps has come, & with advance in technology, clients & customers require the web service or app to provide more information, by showing some animations, & dynamic drawings over the subject such as lines connecting the various parts of the AI subject, which add a lot more interactivity & comprehension of user with the service, also it boosts the AI appeal & quality of the service.


A similar scenario can be thought of a simple AI project, where a user uploads an invoice in format of image/pdf , it gets processed on backend, the response of the document contains the JSON for different characters recognized from the document uploaded, which then has to be shown on either side of the invoice document image on the screen in list format.

Also the recognized characters from the uploaded document have to be shown highlighted on the screen over the image of the document.


On clicking any of the listings, a connector line should appear connecting the list item to its corresponding highlighted characters. 




That appears to be a Rocket science. Isn’t it ? Let's check out.


How JsPlumb works ?


JSplumb is a flowcharting library which is used for showing real flowcharts on html page. It has draggable elements, moveable connectors, different types of connectors. More can be read on 



To show connection between 2 points, which can be 2 html elements like <div> or <rect>, both the pairing elements need to be same. viz - <div> to <div> or <rect> to <rect>

Secondly, both elements should have unique ids & have jsPlumb endpoints added right after the component gets loaded onto html


Such as,

Source element  - <rect id=”name_source”></rect>

Target element - <rect id=”name_target”></rect>


Now endpoints should be made by this jsPlumb method for all source & target elements




uuid: “<ELEMENT ID>”,



  1. For Source --

jsPlumbInstance.addEndpoint(“name_source”, sourceEndpoint, {

anchor: "RightMiddle",

uuid: “name_source”,



  1. For Target --

jsPlumbInstance.addEndpoint(“name_target”, targetEndpoint, {

anchor: "LeftMiddle",

uuid: “name_target”,



The ‘sourceEndpoint’ & ‘targetEndpoint’ used in the snippets above are also a set of key value pairs provided by jsPlumb, that will be discussed later.


We are 90% done here, we have elements to be connected, we have their ids, we have setup their endpoints, now we can connect these elements using this method






We need to pass the respective ids for the elements we want to connect



uuids: [‘name_source’, ‘name_target’]



We’ll get connected elements like this




JS Plumb is not a node library, hence it cannot be npm installed into the project.


  1. We need to acquire this using script tags.


Inside our React js project, go to /public/index.html

& use these script tags in the head section


<link rel="stylesheet" href="./css/jsplumbtoolkit-defaults.css" />

<link rel="stylesheet" href="./css/main.css" />

<link rel="stylesheet" href="./css/jsplumbtoolkit-demo.css" />

<link rel="stylesheet" href="./demo.css" />


Next, use these tags in body section


<script src="./js/jsplumb.js"></script>

<script src="./js/demo-list.js"></script>


Now we’re ready to use the JSplumb instance inside our project


  1. Now , on the component where we receive the response for the uploaded content, & need to show the connectors for the response, we can use the JS Plumb instance


Before that, we need to know what kind of response we need for the working of jsPlumb


For each node , whether starting or ending, we need some coordinates to show the elements on, so the response needs to have atleast this set of data for each node



  "source_key": "name_source",

  "target_key": "name_target",

  "value": " <OCR value obtained from response>",

  "boundingCoordinates": [


      "x1": 0.0856633,   

      "y1": 0.24884406,

      "x2": 0.21594289,

      "y2": 0.26523748,

      "x3": 0.21594289,

      "y3": 0.27742749,

      "x4": 0.0856633,

      "y4": 0.26229507





On the basis of which, multiple elements for source can be rendered on either side of document image with listing pairs such as



 sourceElementsSet.map(item => {

   return (

    <svg id='svgElement0'>                                                      

      <g id='boundingbox_group_0'>   

       <rect x= {item.boundingCoordinates[0].x1*100+'%'}

        y = {item.boundingCoordinates[0].y1*100+'%'}

        width={(item.boundingCoordinates[0].x2*100 -           item.boundingCoordinates[0].x1*100)+'%'}

        height={(item.boundingCoordinates[0].y4*100 -   item.boundingCoordinates[0].y1*100)+'%'}










Where sourceElementsSet is our array of objects with prescribed set of data as shown above this code. We can render target elements in similar manner using say targetElementsSet , which will contain target elements coordinates to be shown on the document image.


  1. Now the endpoints for all rendered elements need to be assigned using addEndPoint function discussed above. , lifecycle hooks such as componentDidMound would be better place to do this


First lets import following items


import $ from "jquery";

import '../../css/font.css';

import '../../css/jsplumbtoolkit-defaults.css';

import '../../css/main.css';

import '../../css/jsplumbtoolkit-demo.css';

import '../../css/demo.css';



Then , using this function inside componentDidMount such as , also we need to pass instance of the class to this function as ‘self’ so that it can access the class instance ‘this’ inside function to use class methods.


For example, this.setState({myVar}); will be used as self.setState({myVar});



componentDidMount() {

  this.setJsPlumbCanvas(this); // passing ‘this’ to access this keyword 



setJsPlumbCanvas = (self) =>

   window.jsPlumb.ready(function () {

     var offsetCalculators = {

       "RECT": function (el, parentOffset) {

         var x = el[0].getBoundingClientRect().x,

           y = el[0].getBoundingClientRect().y +                  (el[0].getBoundingClientRect().height / 2);

         return {

           left: x,

           top: y




     var sizeCalculators = {

       "RECT": function (el) {

         var w = 0,

           h = 0;

         return [w, h];



     var originalOffset = window.jsPlumbInstance.prototype.getOffset;

     var originalSize = window.jsPlumbInstance.prototype.getSize;


     window.jsPlumbInstance.prototype.getOffset = function (el) {

       var tn = el.tagName.toUpperCase();

       if (offsetCalculators[tn]) {

         return offsetCalculators[tn]($(el), $(el).parent().offset());

       } else

         return $(el).offset();



     window.jsPlumbInstance.prototype.getSize = function (el) {

       var tn = el.tagName.toUpperCase();

       if (sizeCalculators[tn]) {

         return sizeCalculators[tn]($(el));

       } else

         return [$(el).outerWidth(), $(el).outerHeight()];



     instance = (window.jsp = window.jsPlumb.getInstance({

       DragOptions: {

         cursor: "pointer",

         zIndex: 2000


       ConnectionOverlays: [




             location: 0.1,


             id: "label",

             cssClass: "aLabel",




       Container: "canvas",


     instance.registerConnectionType("basic", basicType);


     for (let i = 0; i < self.state.sourceKeys.length; i++) {

       for (let j = 0; j < self.state.sourceKeys[i].length; j++) {

         //For Left Node end points  self.addEndPoint(self.state.sourceKeys[i][j].key,sourceEndpoint,"RightMiddle") ;



     for (let k = 0; k < self.state.targetKeys.length; k++) {

       for (let l = 0; l < self.state.targetKeys[k].length; l++) {

         //For Right Node end points      self.addEndPoint(self.state.targetKeys[k][l].key,targetEndPoint,"LeftMiddle") ;






  1. Now, on click of each list item in the list we rendered above, we can bind a function on click event, where we can get uuids of the 2 nodes & establish a connection between them.


Making an onClick event on the items we rendered above,


     <rect x= {item.boundingCoordinates[0].x1*100+'%'}

      onClick = {() => this.handleConnectionSetup(item)}

      y = {item.boundingCoordinates[0].y1*100+'%'}


handleLeftClick = (item) => {


   let {source_key,target_key} = item;


   if (connection) {




   if (rightKey) {

       connection = instance.connect({

         uuids: [source_key, target_key],






Thats all about setting up flowcharting in react app using jsPlumb, Thanks for reading.


Request For Proposal

Sending message..

Ready to innovate ? Let's get in touch

Chat With Us