Flowchart with custom behaviours

Hi,

I want to allow the user to create a flowchart diagram. on some nodes I want to have an icon at the top left that can perform some action for me. Also, I want when I double click or left click on a node to have an option that opens a modal window that allows me to add details to the node. In addition, I want on the edge of a node to have the ability to drag to another node to make a connection, instead of having a connector in the paletttes list and drag it and connect manually.

Could you please provide a sample for that?

Thanks.

28 Replies

SG Shyam G Syncfusion Team October 17, 2017 09:32 AM UTC

Hi Hussain, 
 
Sorry for the delay. 
 
We have created a flowchart sample to achieve your requirement and it is available in the below link for download. 
 
 
  • In the above sample, we have rendered userhandles link tool icon at the middle left, so that you can draw the connector using that tool.
  • We have rendered the userhandles settings tool icon at the top left, so that you can add your custom action in it.
  • Also if you double click on the node, the doubleClick event gets triggered. In this event, we have opened the ejDialog box, so that you can enter the additional details to the node in a textbox. Once you entered the details and if you click on the save button, we add that details to the node’s addInfo property. please refer to the code example below.
Code example: 
   //doubleclick event 
        doubleclick(args){ 
            var diagram=$("#diagramCore").ejDiagram("instance"); 
            $("#basicDialog").ejDialog("open"); 
       
        } 
        saveaddinfo(){ 
            var diagram=$("#diagramCore").ejDiagram("instance"); 
            //get the selected Node 
            var node=diagram.model.selectedItems.children[0]; 
            if(node){ 
                //get the textbox value 
                var value=$("#txtFileName").val(); 
                //add the additional details to addInfo property 
                node.addInfo=value; 
            }      
            $("#basicDialog").ejDialog("close"); 
        } 
 
 
Regards, 
Shyam G 



SG Shyam G Syncfusion Team October 17, 2017 10:05 AM UTC

Hi Hussain, 
 
Please ignore our previous update. 
 
We have created a flowchart sample to achieve your requirement and it is available in the below link for download. 
 
 
  • In the above sample, we have rendered userhandles link tool icon at the middle left, so that you can draw the connector using that tool.
  • We have rendered the userhandles settings tool icon at the top left, so that you can add your custom action in it.
  • Also if you double click on the node, the doubleClick event gets triggered. In this event, we have opened the ejDialog box, so that you can enter the additional details to the node in a textbox. Once you entered the details and if you click on the save button, we add that details to the node’s addInfo property. please refer to the code example below.
Code example: 
   //doubleclick event 
        doubleclick(args){ 
            var diagram=$("#diagramCore").ejDiagram("instance"); 
            $("#basicDialog").ejDialog("open"); 
       
        } 
        saveaddinfo(){ 
            var diagram=$("#diagramCore").ejDiagram("instance"); 
            //get the selected Node 
            var node=diagram.model.selectedItems.children[0]; 
            if(node){ 
                //get the textbox value 
                var value=$("#txtFileName").val(); 
                //add the additional details to addInfo property 
                node.addInfo=value; 
            }      
            $("#basicDialog").ejDialog("close"); 
        } 
 
 
Regards, 
Shyam G 



HU Hussain October 19, 2017 09:22 AM UTC

Thanks for the reply, that helped a lot. 

I'm getting this error:

My systemjs config file is pretty much like this one:
Error: (SystemJS) ej is not defined

https://github.com/syncfusion/angular2-seeds/blob/systemjs/systemjs.config.js/#L27-L28

Also, I had to copy the folder node_modules/@types/userhandles to my project's folder, I'm gessing this is not available in npm.

Edit:

The solution was to add:

import 'syncfusion-javascript/Scripts/ej/datavisualization/ej.diagram.min';




SG Shyam G Syncfusion Team October 19, 2017 12:45 PM UTC

Hi Hussain, 
 
Query 
Response 
Thanks for the reply, that helped a lot.  
I'm getting this error: 
My systemjs config file is pretty much like this one:
Error: (SystemJS) ej is not defined
 
https://github.com/syncfusion/angular2-seeds/blob/systemjs/systemjs.config.js/#L27-L28 
The reported issue occurs due to ej-angular2 is not referred in the app.module.ts file. Could you please refer it to resolve your reported issue. Please refer to the code example below. 
 
Code example: 
 
App.module.ts 
import { EJAngular2Module } from 'ej-angular2'; 
 
However we have created a flowchart sample with system JS and provided the sample below. 
 
 
Also, I had to copy the folder node_modules/@types/userhandles to my project's folder, I'm gessing this is not available in npm. 
Yes, you need to copy the userhandles file to your project because toolbase class could not be implemented in the ej.web.all.d.ts. So only we have used that class in a separate file to render the userhandles tools. 
 
 
Regards, 
Shyam G 
 



HU Hussain October 24, 2017 09:29 AM UTC

Hi Shyam,

I've already imported ej-angular2 but that issue won't go without the fix I posted. Nevermind, as long as it works that way.

However,

I've some problems. 

1. When I add a new node from the palette, I log the nodes variable and I don't see the new node is being added there. Any idea?

2. I'm binding to itemClick event on the diagram, and from that event I'm trying to get the node that user clicked on as follows:
            var diagram : any = $("#diagramCore").ejDiagram("instance");
            var node = diagram.model.selectedItems.children[0];

The diagram.model.selectedItems.children property will be undefined first time you click and will be defined on the second click, so actually to get this working you need double click.

3. When I change a node name by double clicking on the shape and editing the text, that won't change the name property in the selected node.

What I'm trying to do is save the node variable to database after the user finished editing it to repopulate it on page reload.

I would appreciate your help in the nearest possible time for you. Thanks.


SG Shyam G Syncfusion Team October 25, 2017 10:15 AM UTC

Hi Hussain, 
 
Query 
Response 
When I add a new node from the palette, I log the nodes variable and I don't see the new node is being added there. Any idea? 
Could you please confirm us whether you are using drop event to get the dropped node and using diagram.model.selectedItems.children[0] to get the selected node? If yes, please use nodeCollectionChange event in which set the arguments state property as changed to achieve your requirement. please refer to the code example, sample and help documentation below. if we misunderstood your requirement, please provide us more details such as elaborate your requirement in detail with screenshot or video. 
 
Code example: 
 
<ej-diagram id="diagramCore" (nodeCollectionChange)="nodeCollectionChange($event)"> 
               </ej-diagram> 
 
  nodeCollectionChange(args){                
            if(args.state==="changed"){ 
                //get the selectedNode 
                var node=args.element; 
                console.log(node.name) 
            }      
        } 
 
 
 I'm binding to itemClick event on the diagram, and from that event I'm trying to get the node that user clicked on as follows: 
            var diagram : any = $("#diagramCore").ejDiagram("instance"); 
            var node = diagram.model.selectedItems.children[0]; 
In the itemClick event, please use arguments element property to get the selected node. please refer to the code example, sample and help documentation below. 
 
Code example: 
 
<ej-diagram id="diagramCore" (itemClick)="itemClick($event)"> 
               </ej-diagram> 
 
itemClick(args){ 
            //get the selectedNode 
            var node=args.element; 
            console.log(node.name) 
        } 
 
 
Also for doubleClick event , please use arguments element property to get the selected node. 
 
When I change a node name by double clicking on the shape and editing the text, that won't change the name property in the selected node. 
 
What I'm trying to do is save the node variable to database after the user finished editing it to repopulate it on page reload. 
We should not change the object’s name(node/connector/port) at runtime because it is a unique id for all the DOM elements. Also based on the object name, we have changed the object appearance or other functionality. Instead of using nodes name, you can use node’s addInfo property(custom property) and can save it to the database and repopulate it on page reload. Please refer to the code example to define node’s addInfo property. 
 
Code example: 
 
this.nodes = [ 
           { 
               name: "node1", width: 200, height: 230, offsetX: 200, offsetY: 200,addInfo:"node11" 
 
           }, 
]; 
 
 
 
 
Regards, 
Shyam G 



HU Hussain October 25, 2017 01:05 PM UTC

Thanks Shyam, I got this thing working as I want.




SG Shyam G Syncfusion Team October 26, 2017 04:06 AM UTC

Hi Hussain, 
Please let us know if you need further assistance on this. 
Regards, 
Shyam G 



HU Hussain October 26, 2017 05:14 AM UTC

Thanks Shyam for asking. Actually the next thing I'm trying is to show text or an icon in the upper right of a node (from withing the node, not outside like the user handle). This text is dynamic and would change. It's basically a counter for the number of times the user clicked on the userhandle Settings (the icon from the upper left).

See the sample image:

https://i.imgur.com/5tuKQCg.png

so, when hovering over the node, it will show 3 on the upper right. If I click on the userhandle on the left, the number will change to 4. If I hover over this number 4, it will show me some tooltip message.

In short, I want to add something like this in the upper right:

{{counter}}




HU Hussain October 30, 2017 08:47 AM UTC

Any update on this?



SG Shyam G Syncfusion Team October 30, 2017 09:50 AM UTC

Hi Hussain, 

Sorry for the inconvenience. 

We have created a sample to achieve your requirement and it is available in the below link for download. 


  • In the above sample, we have created a group node with rectangle and ellipse as children.
  • By default, we have hidden the ellipse node by setting node’s visible property as false.
  • When we hover on the user handles settings tool, the ellipse node is visible and when you click on the settings tool, the numeric value gets increased and updated the ellipse node label with that numeric value.
  • When you mouse out the user handles, the ellipse node is hidden. please refer to the video below for your reference.


Note: we have created a single group node(for order shape alone) in the sample. 

Regards, 
Shyam G 



HU Hussain October 30, 2017 11:14 AM UTC

Thanks Shyam, 

One more issue I have is with the node ports.

When dragging from node to another sometimes it will get stuck and won't allow the user to drag, it will show green box as shown:
https://i.imgur.com/RmFoC7p.png

The sample project is here:
https://www.dropbox.com/s/n89qsmcf58dzl1o/angular2-seeds-systemjs.zip?dl=0


SG Shyam G Syncfusion Team November 2, 2017 05:35 AM UTC

Hi Hussain, 
Sorry for the delay. 
We considered this “connectors not drawn properly with tool while mouse over on port and draw it” as an issue and a support incident has been created under your account to track the status of this requirement. Please log on to our support website to check for further updates. 
 

Regards, 
Shyam G 



HU Hussain November 20, 2017 08:49 AM UTC

Hello Shyam,

Are we getting the fix on Thursday as scheduled?

Also, are you planning on adding two-way data binding support for your Angular component?

<ej-diagram id="diagramCore" [nodes]="nodes" [connectors]="connectors"> </ej-diagram>

So we can use [(nodes)]="nodes" ?

Thanks.


HU Hussain November 23, 2017 07:16 AM UTC

Hello,
Am I in luck to get the fix as scheduled for today?

I've one more issue. I want to use the tooltip on nodes and I followed this tutorial:
https://help.syncfusion.com/js/diagram/tooltip

However, the tooltip shown is text: #nodetooltiptemplate


SG Shyam G Syncfusion Team November 24, 2017 06:17 AM UTC

Hi Hussain, 
 
Sorry for the delay 
 
Query 
Response 
Also, are you planning on adding two-way data binding support for your Angular component? 
 
<ej-diagram id="diagramCore" [nodes]="nodes" [connectors]="connectors"> </ej-diagram> 
 
So we can use [(nodes)]="nodes" ? 
Yes, we can do two way binding in our diagram control. we have created a sample in which we have done two way binding for nodes. Please refer to the code example and sample below. 
 
Code example: 
 
<button (click)="addNodes()">addNodes</button> 
    <!--node binding--> 
<ej-diagram width="1000px" [(nodes)]="nodes" > 
    </ej-diagram> 
 
addNodes(){ 
            var test=this.nodes.slice(); 
            test.push({name:"node3"+this.nodes.length,width:100,height:100,offsetX:400 +this.nodes.length,offsetY:400+this.nodes.length}); 
            this.nodes=test; 
        } 
 
Please refer to the video below in which we have demonstrated how two way binding works for node. 
 
 
I've one more issue. I want to use the tooltip on nodes and I followed this tutorial: 
https://help.syncfusion.com/js/diagram/tooltip 
 
However, the tooltip shown is text: #nodetooltiptemplate 
The reported issue occurs only if you refer the script template other than index.html file. You should refer script template only in index.html file. please refer to the link below.   
 
 
We have created a sample in which we have rendered tooltip for nodes. 
 
 
 
Regards, 
Shyam G 



HU Hussain November 29, 2017 07:40 AM UTC

Thanks Shyam for the reply. Highly appreciated. 

I'm using symbolpalette component and dragging nodes from the palette to the diagram. It should pickup the dragged nodes and update the nodes variable automatically.

Even if I bind to onDrop method and get the dropped node and add it to the nodes variable (which I wouldn't have to if the two way binding works properly) then the nodes variable won't pickup the changes I have did afterward on the node (like adding label or changing size).


SG Shyam G Syncfusion Team November 30, 2017 09:25 AM UTC

Hi Hussain, 

We can do two way binding for the nodes/connectors collection as we provided sample in our earlier update but the node property doesn’t support two way binding. However we can use model selectedItems offsetX,offsetY, width and height property in two way binding of node. please refer to the sample below in which we have changed the offsetX, offsetY property of selected Node and also refer to the video below for more details. 



Regards, 
Shyam G 



HU Hussain December 5, 2017 09:01 AM UTC

Thanks Shyam,

One more issue I'm facing. I've created a node that can be dragged into another node by allowing drop from constraints (ej.datavisualization.Diagram.NodeConstraints.AllowDrop) and drop event fires perfectly.

I want to detect if the user drops on empty space and prevent that.

I tried selectedItems:
selectedItems = {
            constraints: ej.datavisualization.Diagram.SelectorConstraints.All & ~(ej.datavisualization.Diagram.SelectorConstraints.Rotator | ej.datavisualization.Diagram.SelectorConstraints.Resizer | ej.datavisualization.Diagram.SelectorConstraints.Tooltip | ej.datavisualization.Diagram.SelectorConstraints.DragOnEmptySpace),
        };

however, that didn't work.

I tried also (dragLeave)="onDragLeave($event)" and that event isn't fired.

Any idea?



SG Shyam G Syncfusion Team December 6, 2017 09:49 AM UTC

 
Hi Hussain, 
 
Please use drop event to achieve your requirement. When you drag the node from palette and drop it onto the another node/connector in diagram, the args.target in drop event will be node/connector and when you drag the node from palette and drop it onto the empty space on diagram, the args.target in drop event will be diagram model. So when args.target is diagram model, you can cancel the drop event, so that node dragged from palette will not be added into the diagram. please refer to the  code example below. 
 
Code example: 
 
<ej-diagram id="diagramCore" (drop)= "drop($event)" > 
            </ej-diagram> 
 
   drop(args){ 
            if(args.objectType==="palette"){ 
                var diagram=$("#diagramCore").ejDiagram("instance"); 
                if(diagram.getObjectType(args.target)==="node" ||diagram.getObjectType(args.target)==="connector"){ 
                    //do your code here 
                } 
                else{ 
                    //when the target is diagram, you can cancel the event 
                    args.cancel=true; 
                } 
            } 
        } 
 
Note: diagramCore is an diagram id. 
 
Regards, 
Shyam G 



HU Hussain December 7, 2017 07:16 AM UTC

Hello Shyam,

As I mentioned, I'm not trying to drop from the palette, instead, I want to drop an existing node onto another node. If I drop on empty area drop event won't be triggered.


SG Shyam G Syncfusion Team December 8, 2017 11:16 AM UTC

Hi Hussain, 
 
Please use drag event to achieve your requirement. in this event, you can do your action when the arguments dragState is completed. Please refer to the code example below. 
 
Code example: 
 
<ej-diagram id="diagramCore" (drag)= "drag($event)" >  
            </ej-diagram>  
 
 drag(args) { 
            if (args.dragState === "completed") { 
                //do your action 
            } 
        } 
 
Regards, 
Shyam G 



HU Hussain replied to Shyam G December 10, 2017 01:04 PM UTC

Hi Hussain, 
 
Please use drag event to achieve your requirement. in this event, you can do your action when the arguments dragState is completed. Please refer to the code example below. 
 
Code example: 
 
<ej-diagram id="diagramCore" (drag)= "drag($event)" >  
            </ej-diagram>  
 
 drag(args) { 
            if (args.dragState === "completed") { 
                //do your action 
            } 
        } 
 
Regards, 
Shyam G 


If I used on drag event, how would I get the node I dropped on?

Basically I check the node's addInfo property to check if it is valid for dropping or not.


SG Shyam G Syncfusion Team December 11, 2017 09:04 AM UTC

Hi Hussain, 
 
  • In diagram, the drop event triggers when you drag a node and drop it onto the another node and it won’t be triggered when dragging an element. so only we have suggested the drag event. The drag event triggers when you drag an diagram element(node, connector). So you need to register both the events in your application as shown in the below code example.
  • In drag event, the arguments element property returns an dragged object.
  • In drop event, the arguments element property returns an dragged object and the arguments target property returns dropped target object. You can check condition based on it.
 
Code example: 
<ej-diagram (drag)= "drag($event)"  (drop)= "drop($event)"> 
</ej-diagram> 
 
 
 drag(args) {  
            if (args.dragState === "completed") {  
        //get an dragged element 
        var node = args.element; 
            }  
        }  
 
 
 drop(args){ 
      //get an dragged element 
   var node = args.element; 
      //get an dropped element 
   var target = args.target; 
} 
 
Regards, 
Shyam G 



HU Hussain December 11, 2017 10:03 AM UTC

Thanks, I already have that in my code.

Basically, I want to:

- Drag a node into another node & get the dragged node. (Using drop event and args.target will give me the dragged on node).
- Detect if a node is dragged into an empty area and reject the drag to restore the node's original position. (if I use drag event, how do I know if it is dragged on empty area not a node, and I can't use drop event as it won't be triggered)


SG Shyam G Syncfusion Team December 12, 2017 11:06 AM UTC

Hi Hussain, 
 
We have created a sample in which we have used drag and drop event to achieve your requirement. when you drag an element and drop it onto the empty area, we have restored it to original position. When you drag and element and drop it onto the another node, the node retains in the dropped position. Please refer to the code example and sample below. 
 
Code example: 
 
<ej-diagram (drag)= "drag($event)"  (drop)= "drop($event)">  
</ej-diagram>  
  
  
        drag(args) {   
            var diagram = $("#ejControl_0").ejDiagram("instance"); 
            if (args.dragState === "starting") { 
                this.newValues = args.newValue;                 
            } 
            if (args.dragState === "completed") {                
                if (this.isDropTriggered) { 
                    this.isDropTriggered = false; 
                } 
                else { 
                          diagram.updateNode(args.element.name, { offsetX: this.newValues.offsetX, offsetY: this.newValues.offsetY }); 
                } 
            } 
        }   
  
  
        drop(args){  
            if (!this.isDropTriggered) {             
                this.isDropTriggered = true; 
            } 
        } 
 
 
Regards, 
Shyam G 



SS Shalin Siriwaradhana May 4, 2018 11:42 AM UTC

These flowchart examples could be very helpful as there are many variations of it. You can edit and experiment with your data.



SG Shyam G Syncfusion Team May 7, 2018 11:55 AM UTC

Hi Shalin, 
 
  • We have diagram builder sample in which you can create flow shapes, BPMN shapes, swimlane, electrical shapes and so on but we don’t have built-in flowchart templates in our diagram and will consider it in future.
  • Also, We have demo samples in diagram in which we expose the Diagram functionalities.
  • Please let us know if you face any problem while creating flowchart in our diagram, so that we can assist you.
 
Here is the online sample link 
 
 
 
Regards, 
Shyam G 


Loader.
Up arrow icon