userHandles
collection of the selectedItems
property.User handles can be aligned relative to the node boundaries. It has margin
, offset
, side
, horizontalAlignment
, and verticalAlignment
settings. It is quite tricky when all four alignments are used together but gives more control over alignment.
The offset
property of userHandles
is used to align the user handle based on fractions. 0 represents top/left corner, 1 represents bottom/right corner, and 0.5 represents half of width/height.
The side
property of userHandles
is used to align the user handle by using the Top
, Bottom
, Left
, and Right
options.
The horizontalAlignment
property of userHandles
is used to set how the user handle is horizontally aligned at the position based on the offset
. The verticalAlignment
property is used to set how user handle is vertically aligned at the position.
Margin is an absolute value used to add some blank space in any one of its four sides. The userHandles
can be displaced with the margin
property.
The appearance of the user handle can be customized by using the size
, borderColor
, backgroundColor
, visible
, pathData
, and pathColor
properties of the userHandles
.
import { Diagram, NodeModel, BasicShapeModel, MoveTool, MouseEventArgs, IElement, UserHandleModel, ToolBase, SelectorConstraints, Actions, randomId, cloneObject } from '@syncfusion/ej2-diagrams';
let shape: BasicShapeModel = { type: 'Basic', shape: 'Rectangle' };
let node1: NodeModel = { id: 'node', offsetX: 100, offsetY: 100, shape: shape };
let handles: UserHandleModel[] = [{
name: 'clone', pathData: 'M60.3,18H27.5c-3,0-5.5,2.4-5.5,5.5v38.2h5.5V23.5h32.7V18z M68.5,28.9h-30c-3, 0-5.5,2.4-5.5,5.5v38.2c0,3,2.4,5.5,5.5,5.5h30c3,0,5.5-2.4,5.5-5.5V34.4C73.9,31.4,71.5,28.9,68.5,28.9z M68.5,72.5h-30V34.4h30V72.5z', visible: true, offset: 0, side: 'Bottom',
margin: { top: 0, bottom: 0, left: 0, right: 0 }
}];
let diagram: Diagram = new Diagram({
width: '100%', height: '600px', nodes: [node1],
selectedItems: { constraints: SelectorConstraints.All, userHandles: handles },
getNodeDefaults: (node: NodeModel): NodeModel => {
node.height = 100;
node.width = 100;
node.style.fill = '#6BA5D7';
node.style.strokeColor = '#6BA5D7';
return node;
},
getCustomTool: getTool
});
diagram.appendTo('#element');
function getTool(action: string): ToolBase {
let tool: ToolBase;
if (action === 'clone') {
tool = new CloneTool(diagram.commandHandler);
}
return tool;
}
//Defines the clone tool used to copy Node/Connector
class CloneTool extends MoveTool {
public mouseDown(args: MouseEventArgs): void {
let newObject: any;
if (diagram.selectedItems.nodes.length > 0) {
newObject = cloneObject(diagram.selectedItems.nodes[0]) as NodeModel;
} else {
newObject = cloneObject(diagram.selectedItems.connectors[0]) as ConnectorModel;
}
newObject.id += randomId();
diagram.paste([newObject]);
args.source = diagram.nodes[diagram.nodes.length - 1] as IElement;
args.sourceWrapper = args.source.wrapper;
super.mouseDown(args);
this.inAction = true;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>EJ2 Diagram</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Typescript UI Controls" />
<meta name="author" content="Syncfusion" />
<link href="index.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-base/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-buttons/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-popups/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-splitbuttons/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-diagrams/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-navigations/styles/fabric.css" rel="stylesheet" />
<script src="systemjs.config.js"></script>
</head>
<body>
<div id='loader'>Loading....</div>
<div id='container'>
<div id='element'></div>
</div>
</body>
</html>
The fixed user handles are used to add some frequently used commands around the node and connector even without selecting it.
To create the fixed user handles, define and add them to the collection of nodes and connectors property. The following code example used to create an fixed user handles for the nodes and connectors.
import { Diagram, NodeModel } from '@syncfusion/ej2-diagrams';
let node: NodeModel = {
offsetX: 250,
offsetY: 250,
width: 100,
height: 100,
style: {
fill: '#6BA5D7',
strokeColor: 'white'
},
// A fixed user handle is created and stored in fixed user handle collection of Node.
fixedUserHandles: [{margin: { right: 20 },
pathData: 'M60.3,18H27.5c-3,0-5.5,2.4-5.5,5.5v38.2h5.5V23.5h32.7V18z M68.5,28.9h-30c-3,0-5.5,2.4-5.5,5.5v38.2c0,3,2.4,5.5,5.5,5.5h30c3,0,5.5-2.4,5.5-5.5V34.4C73.9,31.4,71.5,28.9,68.5,28.9z M68.5,72.5h-30V34.4h30V72.5z' }]
};
let diagram: Diagram = new Diagram({
width: '100%',
height: '600px',
nodes: [node]
});
diagram.appendTo('#element');
<!DOCTYPE html>
<html lang="en">
<head>
<title>EJ2 Diagram</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Typescript UI Controls" />
<meta name="author" content="Syncfusion" />
<link href="index.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-base/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-buttons/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-popups/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-splitbuttons/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-diagrams/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-navigations/styles/fabric.css" rel="stylesheet" />
<script src="systemjs.config.js"></script>
</head>
<body>
<div id='loader'>Loading....</div>
<div id='container'>
<div id='element'></div>
</div>
</body>
</html>
Padding
is used to leave the space that is inside the fixed user handle between the icon and border.cornerRadius
property.Note: The PathData needs to be provided to render fixed user handle.
Diagram allows you set size for the fixed user handles by using the width
and height
property. The default value of the width and height property is 10.
iconStrokeColor
and iconStrokeWidth
property used to change the stroke color and stroke width of the given pathData
.handleStrokeColor
and fill
properties are used to define the background color and border color of the userhandle and the handleStrokeWidth
property is used to define the border width of the fixed user handle.visible
property of the fixed user handle enables or disables the visibility of fixed user handle.The following code explains how to customize the appearance of the fixed user handles.
import { Diagram, NodeModel, ConnectorModel } from '@syncfusion/ej2-diagrams';
let node: NodeModel = {
offsetX: 150,
offsetY: 150,
width: 100,
height: 100,
style: {
fill: '#6BA5D7',
strokeColor: 'white'
},
fixedUserHandles: [{offset: { x: 0, y: 0 },margin: { right: 20 }, width: 20, height: 20,
padding:{left:3,right:3,top:3,bottom:3},iconStrokeColor:'white',fill:'black', id: 'user1', pathData: 'M60.3,18H27.5c-3,0-5.5,2.4-5.5,5.5v38.2h5.5V23.5h32.7V18z M68.5,28.9h-30c-3,0-5.5,2.4-5.5,5.5v38.2c0,3,2.4,5.5,5.5,5.5h30c3,0,5.5-2.4,5.5-5.5V34.4C73.9,31.4,71.5,28.9,68.5,28.9z M68.5,72.5h-30V34.4h30V72.5z' }]
};
let connector: ConnectorModel = {
id: 'connector1',
type: 'Orthogonal',
sourcePoint: { x: 300, y: 100 },
targetPoint: { x: 400, y: 200 },
fixedUserHandles: [{ offset: 0.5, width: 20, alignment: 'Before', padding:{left:3,right:3,top:3,bottom:3},iconStrokeColor:'white',fill:'black', height: 20, id: 'usercon1', displacement:{x:10,y:10}, pathData: 'M60.3,18H27.5c-3,0-5.5,2.4-5.5,5.5v38.2h5.5V23.5h32.7V18z M68.5,28.9h-30c-3,0-5.5,2.4-5.5,5.5v38.2c0,3,2.4,5.5,5.5,5.5h30c3,0,5.5-2.4,5.5-5.5V34.4C73.9,31.4,71.5,28.9,68.5,28.9z M68.5,72.5h-30V34.4h30V72.5z' }]
};
let diagram: Diagram = new Diagram({
width: '100%',
height: '600px',
nodes: [node],
connectors: [connector]
});
diagram.appendTo('#element');
<!DOCTYPE html>
<html lang="en">
<head>
<title>EJ2 Diagram</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Typescript UI Controls" />
<meta name="author" content="Syncfusion" />
<link href="index.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-base/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-buttons/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-popups/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-splitbuttons/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-diagrams/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-navigations/styles/fabric.css" rel="stylesheet" />
<script src="systemjs.config.js"></script>
</head>
<body>
<div id='loader'>Loading....</div>
<div id='container'>
<div id='element'></div>
</div>
</body>
</html>
Note: The fixed user handle id need to be unique.
margin
and offset
settings. It is quite useful to position the node fixed userhandle and used together and gives you more control over the node fixed user handle positioning.Margin is an absolute value used to add some blank space in any one of its four sides. The fixed user handle can be displaced with the margin
property.
The offset
property of fixed user handle is used to align the user handle based on the x
and y
points. (0,0) represents the top or left corner and (1,1) represents the bottom or right corner.
The following table shows all the possible alignments visually shows the fixed user handle positions.
Offset | Margin | Output |
---|---|---|
(0,0) | Right = 20 |
![]() |
(0.5,0) | Bottom = 20 |
![]() |
(1,0) | Left = 20 |
![]() |
(0,0.5) | Right = 20 |
![]() |
(0,1) | Left = 20 |
![]() |
(0,1) | Right = 20 |
![]() |
(0.5,1) | Top = 20 |
![]() |
(1,1) | Left = 20 |
![]() |
The following code explains how to customize the node fixed user handle.
import { Diagram, NodeModel } from '@syncfusion/ej2-diagrams';
let node: NodeModel = {
offsetX: 200,
offsetY: 200,
width: 100,
height: 100,
style: {
fill: '#6BA5D7',
strokeColor: 'white'
},// A fixed user handle is created and stored in fixed user handle collection of Node.
fixedUserHandles: [{ offset: { x: 0, y: 0 }, margin: { right: 20 }, width: 20,height: 20, pathData: 'M60.3,18H27.5c-3,0-5.5,2.4-5.5,5.5v38.2h5.5V23.5h32.7V18z M68.5,28.9h-30c-3,0-5.5,2.4-5.5,5.5v38.2c0,3,2.4,5.5,5.5,5.5h30c3,0,5.5-2.4,5.5-5.5V34.4C73.9,31.4,71.5,28.9,68.5,28.9z M68.5,72.5h-30V34.4h30V72.5z' }]
};
let diagram: Diagram = new Diagram({
width: '100%',
height: '600px',
nodes: [node]
});
diagram.appendTo('#element');
<!DOCTYPE html>
<html lang="en">
<head>
<title>EJ2 Diagram</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Typescript UI Controls" />
<meta name="author" content="Syncfusion" />
<link href="index.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-base/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-buttons/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-popups/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-splitbuttons/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-diagrams/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-navigations/styles/fabric.css" rel="stylesheet" />
<script src="systemjs.config.js"></script>
</head>
<body>
<div id='loader'>Loading....</div>
<div id='container'>
<div id='element'></div>
</div>
</body>
</html>
offset
and alignment
properties of fixed user handle allows you to align the connector fixed user handles to the segments.The offset
property of connector fixed user handle is used to align the user handle based on fractions. 0 represents the connector source point, 1 represents the connector target point, and 0.5 represents the center point of the connector segment.
The connector’s fixed user handle can be aligned over its segment path using the alignment
property of fixed user handle.
The following table shows all the possible alignments visually shows the fixed user handle positions.
Offset | Alignment | Output |
---|---|---|
0 | Before |
![]() |
0.5 | Center |
![]() |
1 | After |
![]() |
displacement
property allows you to specify the space to be left from the connector segment based on the x and y value provided.The following table shows all the possible alignments visually shows the fixed user handle positions.
Displacment | Alignment | Output |
---|---|---|
x=10 | Before |
![]() |
x=10 | After |
![]() |
y=10 | Before |
![]() |
y=10 | After |
![]() |
Note: Displacement will not be done if the alignment is set to be center.
The following code explains how to customize the connector fixed user handle.
import { Diagram, ConnectorModel } from '@syncfusion/ej2-diagrams';
let connector: ConnectorModel = {
id: 'connector1',
type: 'Orthogonal',
sourcePoint: { x: 300, y: 100 },
targetPoint: { x: 400, y: 200 },
// A fixed user handle is created and stored in fixed user handle collection of Connector.
fixedUserHandles: [{ offset: 0.5, width: 20, alignment: 'Before', height: 20, id: 'usercon1', displacement:{x:10,y:10}, pathData: 'M60.3,18H27.5c-3,0-5.5,2.4-5.5,5.5v38.2h5.5V23.5h32.7V18z M68.5,28.9h-30c-3,0-5.5,2.4-5.5,5.5v38.2c0,3,2.4,5.5,5.5,5.5h30c3,0,5.5-2.4,5.5-5.5V34.4C73.9,31.4,71.5,28.9,68.5,28.9z M68.5,72.5h-30V34.4h30V72.5z' }]
};
let diagram: Diagram = new Diagram({
width: '100%',
height: '600px',
connectors: [connector]
});
diagram.appendTo('#element');
<!DOCTYPE html>
<html lang="en">
<head>
<title>EJ2 Diagram</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Typescript UI Controls" />
<meta name="author" content="Syncfusion" />
<link href="index.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-base/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-buttons/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-popups/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-splitbuttons/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-diagrams/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-navigations/styles/fabric.css" rel="stylesheet" />
<script src="systemjs.config.js"></script>
</head>
<body>
<div id='loader'>Loading....</div>
<div id='container'>
<div id='element'></div>
</div>
</body>
</html>
The diagram provides support to show tooltip when the mouse hovers over any user handle.
To show the tooltip on mouse over, the tooltip
property of diagram model needs to be set with the tooltip content
and position
as shown in the following example.
import {
Diagram,
NodeModel,
DiagramConstraints,
UserHandleModel,
SelectorConstraints,
NodeConstraints
} from '@syncfusion/ej2-diagrams';
import {
NodeAnimationSettings
} from '@syncfusion/ej2-navigations';
let node: NodeModel = {
// Position of the node
offsetX: 250,
offsetY: 250,
// Size of the node
width: 100,
height: 100,
style: {
fill: '#6BA5D7',
strokeColor: 'white'
},
tooltip: { content: 'node1', position: 'BottomRight', relativeMode: 'Object' },
constraints:NodeConstraints.Default | NodeConstraints.Tooltip
};
let handle: UserHandleModel[] = [{
name: 'handle1',
pathData: 'M60.3,18H27.5c-3,0-5.5,2.4-5.5,5.5v38.2h5.5V23.5h32.7V18z M68.5,28.9h-30c-3,0-5.5,2.4-5.5,5.5v38.2c0,3,2.4,5.5,5.5,5.5h30c3,0,5.5-2.4,5.5-5.5V34.4C73.9,31.4,71.5,28.9,68.5,28.9z M68.5,72.5h-30V34.4h30V72.5z',
visible: true, backgroundColor: 'black', offset: 0, side: 'Right',
pathColor: 'white',
tooltip: { content: 'handle1', position: 'BottomRight', relativeMode: 'Object' },
}]
// initialize Diagram component
let diagram: Diagram = new Diagram({
width: '100%',
height: '600px',
// Add node
nodes: [node],
constraints: DiagramConstraints.Default | DiagramConstraints.Tooltip,
userHandleTemplate: '#userHandletemplate',
selectedItems: { constraints: SelectorConstraints.All,userHandles: handle },
});
diagram.appendTo('#element');
<!DOCTYPE html>
<html lang="en">
<head>
<title>EJ2 Diagram</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Typescript UI Controls" />
<meta name="author" content="Syncfusion" />
<link href="index.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-base/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-buttons/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-popups/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-splitbuttons/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-diagrams/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.2.3/ej2-navigations/styles/fabric.css" rel="stylesheet" />
<script src="systemjs.config.js"></script>
</head>
<body>
<div id='loader'>Loading....</div>
<div id='container'>
<div id='element'></div>
</div>
</body>
</html>