Grapheditor
Component Attributes
- svg-template
A css selector for the html template containing the full svg template to use in the grapheditor.
Note
Loading the svg from a html template into the shadow dom fully isolates the css from the main page. This makes it easier to have multiple grapheditors at the same time with different styles. Because of that loading the svg from a html template is the preferred method.
<template id="graph-template"> <svg> <style></style> </svg> </template> <network-graph svg-template="#graph-template"></network-graph>
Warning
The html template must be in the dom before the grapheditor node. Otherwise the grapheditor may not be able to select and use the template. The template can also be manually loaded later with
GraphEditor.reloadSvgTemplate().
- nodes
A json list of
Node()objects. The attribute will not be updated to reflect the current node list!If JSON parsing fails, all
'characters will be replaced with"before parsing again. This behaviour is deprecated and will be removed in the next major version.
- edges
A json list of
Edge()objects. The attribute will not be updated to reflect the current edge list!If JSON parsing fails, all
'characters will be replaced with"before parsing again. This behaviour is deprecated and will be removed in the next major version.
- classes
List of possible css classnames to set for edges or nodes. Same syntax as
classattribute. (Can also be a json list.)If JSON parsing fails, all
'characters will be replaced with"before parsing again. This behaviour is deprecated and will be removed in the next major version.
- mode (deprecated)
See also
Replaced by the attributes
zoom,select,node-click,node-drag,edge-dragandbackground-drag.The interaction mode of the graph.
displayallow no user interaction with the graph except selecting nodes.layoutallow free layout manipulation by user.linkallow creating and destroying links by user.selectallow only selecting and deselecting nodes.
Deprecated since version 7.0.
- zoom
Controls zoom behaviour of graph. To control graph panning see
background-drag. Some zoom gestures may also pan the graph!Manual zoom refers to zoom gestures using the mouse wheel, double click or pinch-to-zoom gestures.
nonegraph will not zoom at all.manualallow free zoom by user.automaticgraph will zoom to the bounding box of the graph after (re-)render to show all nodes.bothDEFAULT; both manual and automatic.
Changed in version 7.0: Zoom mode now only controls zoom gestures. Use
background-dragattribute to control panning!
- select
Controls the default node selection behaviour. This setting affects all interactive behaviours (node click, brush select) and the grapheditor API (e.g.
changeSelected(),selectNode()anddeselectNode()).Changes to this setting only apply to new selections. An already existing node selection will not be changed automatically!
noneprevents all node selectionssingleonly a single node can be selected at the same timemultipleDEFAULT; multiple nodes can be selected at the same time
New in version 7.0.
- node-click
Controls the default behaviour when clicking on a node. Events for node clicks will always fire.
noneno default action will be performed. Use this when a node click should trigger a custom actionselectDEFAULT; the selected status of the node will be toggled. If the selection mode is single all selected nodes will be deselected.linkclicking on a node selects the node as the temporary edge source. Clicking on a second node creates (or removes) an edge from the selected edge source to the clicked node.
New in version 7.0.
- node-drag
Controls the drag behaviour of nodes.
nonenodes cannot be dragged around.moveDEFAULT; dragging a node moves the node.linkthe entire node acts like a link drag handle. Dragging the node creates a new dragged edge.
New in version 7.0.
- edge-drag
Controls the drag behaviour of edges (when dragged from their drag handles).
noneedges cannot be dragged around.linkDEFAULT; dragging edges can change to which nodes they are linked to. Dropping an edge over the background removes the edge.
New in version 7.0.
- background-drag
Controls the drag behaviour when the whole graph is dragged around (i.e., when the background is dragged).
All modes (except
noneandmove) draw a visible brush on the screen. When a brush is drawn, the action indicated by the current setting is performed when the brush is released.The brush can be styled using css. It uses the css class
brushand is a direct decendent of theg.zoom-groupnode in the dom.nonedisables this behaviour completely. Only zoom gestures are allowed (seezoom).moveDEFAULT; dragging the graph moves it around (panning the graph).zoomzoom to fit the brush area to the available screen space.selectselect all nodes with coordinates that are inside of the brush box. This works best if the node coordinates correspond to the visual centers of the nodes. In single select mode the node closest to the brush center will be chosen. The brush will not select any node if the current selection mode isnone.customdraws the brush and fires the brush events without an active default behaviour. Use this to implement custom brush behaviours.
New in version 7.0.
Example Usage
<network-graph
nodes='[{"id": 1, "title": "hello world", "type": "simple-node", "x": 0, "y": 0}, {"id": 2, "title": "HI2", "type": "simple-node", "x": 150, "y": 100}]'
edges='[{"source": 1, "target": 2}]'
classes="bg-red bg-blue"
mode="layout"
zoom="both"
svg-template="#graph-template">
</network-graph>
Component Styling
It is possible to inject styles, Node() and Marker() templates into the component.
This is achieved by using the slots mechanic.
Warning
The old styling method meant that every style was added to the global css scope.
This makes the style slot essentially useless, thus it is deprecated.
Styling is still supported with a <style> tag from inside the svg.
Styles can also be placed in a <style> tag inside the <svg> used to render the graph.
Placing all graph related styles in the svg is recommended as it allows to simply save the current graph as a self contained svg.
When the svg is loaded from a html template all styles are fully isolated from the global css styles.
There is also very limited support for completely dynamic styles with dynamic content.
Warning
The current preferred method to load an svg is to load it from an html template. See Component Attributes above for more information.
See also
It is possible to set the svg content of Nodes and Markers using templates.
See the documentation for static templates and dynamic templates.
<!-- new method (strongly recommended) -->
<template id="graph-template">
<svg>
<style>/* graph styles go here (styles here are isolated!) */</style>
</svg>
</template>
<network-graph svg-template="#graph-template"></network-graph>
<!-- old method (discouraged) -->
<network-graph>
<svg slot="graphs">
<style>/* graph styles go here (styles here are global!) */</style>
</svg>
</network-graph>
It is also possible to change the default layering (nodes rendering above edges) in the provided svg:
<template id="graph-template">
<svg>
<g class="zoom-group"> <!-- the zoom-groop is used for the pan and zoom transormations -->
<g class="nodes"></g> <!-- the first group will be rendered below the following groups-->
<g class="edges"></g>
<!-- A brush will appear like this:
<rect class="brush"></rect>
-->
</g>
</svg>
</template>
Styling Nodes
The structure of the svg around a single node looks like this:
<!-- container for all nodes -->
<g class="nodes">
<!-- container for single node -->
<g class="node hovered" id="1" data-template="default" transform="translate(0,0)">
<!-- template content -->
<!-- link handles -->
<g class="link-handle" transform="translate(0,-30)" data-template="default-marker">
<circle fill="black" cx="0" cy="0" r="3"></circle>
</g>
<g class="link-handle" transform="translate(50,0)" data-template="default-marker">
<circle fill="black" cx="0" cy="0" r="3"></circle>
</g>
<g class="link-handle" transform="translate(0,30)" data-template="default-marker">
<circle fill="black" cx="0" cy="0" r="3"></circle>
</g>
<g class="link-handle" transform="translate(-50,0)" data-template="default-marker">
<circle fill="black" cx="0" cy="0" r="3"></circle>
</g>
</g>
</g>
All classes are set on the top level group (<g class="node"></g>) tag.
The top level group always has the node class.
To change the classlist of a node dynamically set the GraphEditor.setNodeClass (details).
List of special node classes
nodesSpecial class for node container group.
nodeAll nodes have the
nodeclass.hoveredThis class is set if the node is hovered by the mouse or a pointer device.
selectedThis class is set if the node is currently selected.
link-handleSpecial class for link handles inside of node.
outlineSpecial class for an svg element used to define the outline of the node for calculating link-handle positions.
textSpecial class to select all text elements that need to be updated with text from the node.
See also
Setting custom css classes is also supported: Styling nodes and edges with custom css classes.
Styling Edges
The structure of the svg around a single edge looks like this:
<!-- container for all edges -->
<g class="edges">
<!-- container for single edge with markers -->
<g class="edge-group " id="s1,t2" >
<path class="edge" fill="none" stroke="black" d="M50,0L51,0C53,0,56,0,63,16,33,80,66,86,83C93,100,96,100,98,100L100,100"></path>
<!-- edge markers -->
<g class="marker" data-template="arrow" transform="translate(100,100)scale(0.5)rotate(0)">
<!-- marker template content -->
</g>
<!-- text components -->
<text x="54" y="-32" class="text" width="30" data-click="TextClick" data-wrapped="true">Hello…</text>
<!-- link handle to drag edge -->
<g class="link-handle" transform="translate(92,94)" data-template="default-marker">
<circle fill="black" r="3" cx="0" cy="0"></circle>
</g>
</g>
</g>
All classes are set on the top level group (<g class="edge-group"></g>) tag.
The top level group always has the edge class.
To change the classlist of a edge dynamically set the GraphEditor.setEdgeClass (details).
Hint
The edge path can be changed with Edge Path Templates.
List of special edge classes
edgesSpecial class for edge-group container group.
edge-groupSpecial class for edge container group.
draggedSpecial class for user dragged edge-groups.
edgeClass for edge path.
markerClass for all edge markers.
marker-specialSpecial class for marker at the start or end of the edge.
marker-startSpecial class for marker at the start of the edge.
marker-endSpecial class for marker at the end of the edge.
link-handleClass for edge drag handle.
highlight-outgoingClass to highlight outgoing edges of a selected or hovered node.
highlight-incomingClass to highlight incoming edges of a selected or hovered node.
Edge Drag Handles
Edges can have a list of EdgeDragHandles that use marker templates for display.
They behave like Markers (see next section).
If they are dragged the edge detaches from it’s target node and follows the drag.
To create bidirectional edges set the isBidirectional attribute to true.
Alternatively directly use a EdgeDragHandle() with isReverseHandle to true to
simulate an edge that can be dragged from its source.
If such a EdgeDragHandle() is dragged the resulting dragged edge is a flipped version of the original edge with source and target switched.
Hint
To determine if an edge was dragged from a EdgeDragHandle() with isReverseHandle set true
compare the dragged edge source with the original edge source.
Edge Markers
Edges can have a list of Markers that use marker templates for display.
For an arrowhead at the start or end of the edge use the special edge-end-markers markerEnd and markerStart.
The attachement point of the edge line to the marker can be adjusted by setting the data-line-attachement-point attribute in the marker template (example).
If the attribute is a single number it describes how far from the center of the template the edge attaches.
If the attribute is two numbers (seperated by a single space) the it describes a specific point in the template where the edge attaches to.
To update markers of dragged edges it is possible to set the function onCreateDraggedEdge, onDraggedEdgeTargetChange and onDropDraggedEdge.
Hint
The position of the marker can be controlled with the attributes defined in PathPositionRotationAndScale() and RotationData().
Text-Components
Edges can have a list of Text-Components.
To set the displayed text either use value to set a specific text or attributePath to set the text based on an attribute of the edge.
The position of the Text can be controlled via the positionOnLine Attribute similar to the Markers.
A Text-Component must have a width > 0 which is used to wrap the text.
For multiline text wrapping also set the height attribute.
The text element will always have the text class.
Normally the text origin is the left of the baseline.
This means that a single line text is to the right and above the calculated anchor point on the edge path.
This can be changed by the text-anchor css attribute.
The Text-Component will always try not to clip into nodes.
This is achieved by checking whether the text is nearer to the start or end of the edge and then checking for overlaps with the node at that endpoint.
If the text overlaps it gets pushed in the direction towards the center of the edge.
The padding is used as a buffer zone around the text.
Text components can be marked as user draggable by setting draggable.
Hint
The position of the text component can be controlled with the attributes defined in PathPositionRotationAndScale() and RotationData().
Customising where edges attach to nodes
Edges will snap to the nearest LinkHandle().
Link handles are calculated per node template.
To customize the position where the edge attaches to nodes set the calculateLinkHandlesForEdge callback.
See also
Documentation for dynamic node templates.
Styling The Brush
The structure of the svg around the brush looks like this:
<!-- outer svg -->
<svg>
<g class="zoom-group">
<g class="nodes"></g>
<g class="edges"></g>
<!-- The brush will always be inserted at the end -->
<rect class="brush"></rect>
</g>
</svg>
The brush can be selected with the CSS selector .zoom-group > .brush.
Example Styling Usage
<template id="graph-template">
<svg>
<style>
svg {width:100%; height: 100%}
.zoom-group > .brush {fill: dodgerblue; opacity: 0.3;}
.node {fill: aqua;}
.link-handle {display: none; fill: black; opacity: 0.1;}
.edge-group .link-handle {display: initial}
.link-handle:hover {opacity: 0.7;}
// the css transform overwrites the svg transform completely
// and link handles are placed with a translate transformation
// but the content of the link handle group can be scaled
.link-handle>* {transition:transform 0.25s ease-out;}
.link-handle:hover>* {transform: scale(1.5);}
.text {fill: black;}
.node.hovered {fill: red;}
.node.selected {fill: green; content:attr(class)}
.highlight-outgoing .edge {stroke: red;}
.highlight-incoming .edge {stroke: green;}
.highlight-outgoing .marker {fill: red;}
.highlight-incoming .marker {fill: green;}
</style>
<defs>
<g id="simple-node" data-template-type="node">
<rect width="100" height="60" x="-50" y="-30"></rect>
<text class="title text" data-content="title" data-click="title" x="-40" y="-10"></text>
<text class="text" data-content="type" x="-40" y="10" width="80"></text>
</g>
<g id="arrow" data-template-type="marker" data-line-attachement-point="-9 0">
<path d="M -9 -4 L 0 0 L -9 4 z" />
</g>
</defs>
</svg>
</template>
<network-graph svg-template="#graph-template"></network-graph>
Styling nodes and edges with custom css classes
It is possible to style nodes and edges with custom css classes.
The network-graph component needs to know about all possible classes.
The list of possible classes can be set in the classes attribute.
To controll which class is set for a node or an edge set the functions setNodeClass or setEdgeClass.
<network-graph classes="type-a type-b"></network-graph>
var graph = document.querySelector('network-graph');
graph.setNodeClass = (className, node) => {
return className === node.type;
}
graph.setEdgeClass = (className, edge, sourceNode, targetNode) => {
if (targetNode == null) {
return false;
}
return className === targetNode.type;
}
Component Events
The graph component uses custom events. Custom event data can be accessed via the detail attribute.
Warning
Custom events get dispatched synchronously!
Hint
All events have an attribute eventSource in the event detail that can have the following values:
INTERNALfor events triggered by internal/unknown sourceAPIfor events triggered using the public API.USER_INTERACTIONfor events triggered by the user interacting with the graph.
The eventSource can be used in event listeners to ignore all events triggered by using the API.
Events Overview
General Events
svginitialized A new SVG was initialized and is ready to render graph data
modechange (removed)
zoommodechange The
zoomattribute of graph editor has changedzoomchange Position and/or scale of the graph were updated
render Graph data was rendered to the SVG
backgroundclick User clicked on graph background
brushdrag User dragged a brush selection over the graph background
brush User released/comitted the brush
selection Current selected nodes have changed
- svginitialized
Fired after the zoom has changed.
Example
detail{ "newSVG": this.svg, "oldSVG": oldSVG, }
- modechange (removed)
Warning
This event was removed with the deprecation of the mode attribute.
Deprecated since version 7.0.
- zoommodechange
Fired after the zoom mode changed.
Example
detail{ "oldMode": "none", "newMode": "both" }
- zoomchange
Fired after the zoom has changed.
Example
detail{ "oldZoom": d3-zoom.ZoomTransform, "newZoom": d3-zoom.ZoomTransform, "currentViewWindow": graphEditor.currentViewWindow, }
- render
Fired after the graph was completely or partially updated.
The attribute
renderedcan be one of the following:completeThe method
GraphEditor.completeRender()was used to update the graph.textThe method
GraphEditor.updateTextElements()was used to update the graph.classesThe method
GraphEditor.updateNodeClasses()was used to update the graph.positionsThe method
GraphEditor.updateGraphPositions()was used to update the graph.Example
detail{ "rendered": "complete", }
- backgroundclick
Fired when the graph background was clicked.
The event contains the point where the click happened in graph coordinates.
Example
detail{ sourceEvent: {}, point: { x: 0, y: 0, }, }
- brushdrag
Fired when the brush area changes.
The event contains the current brush area and the current brush interaction settings (the value of the
background-dragattribute; see Component Attributes).Example
detail{ sourceEvent: {}, brushArea: { x: 0, y: 0, width: 100, height: 100, }, brushMode: "select", }
- brush
Fired before the current active brush action is performed.
The event contains the current brush area and the current brush interaction settings (the value of the
background-dragattribute; see Component Attributes).Example
detail{ sourceEvent: {}, brushArea: { x: 0, y: 0, width: 100, height: 100, }, brushMode: "select", }
- selection
Fired when a user (de-)selects a
Node().Hint
Use
GraphEditor.selectNode(),GraphEditor.deselectNode()andGraphEditor.changeSelected()to change the selection programmatically. UseGraphEditor.selectedto get the current selection outside of events.Example
detail{ "selection": new Set<number|string>([1, 2, 5]) }
Node Events
Events marked with * have default behaviour that can be prevented with event.preventDefault().
nodeclick* User clicked on a node
nodeenter Mouse cursor was moved over a node
nodeleave Mouse cursor was moved outside of a node
nodepositionchange Node has changed its position
nodedragstart User starts dragging a node
nodedragend User stops dragging a node
nodeadd* New node is added to the graph
noderemove* Node is removed from the graph
- nodeclick
Fired when a user clicks on a
Node(). Thekeycan be used to create custom buttons.Use
event.preventDefault()to prevent standard graph behaviour.Example
detail{ "sourceEvent": {}, "node": { "id": 1, "x": 0, "y": 0 }, "key": "close" }
- nodeenter
Fired when a user enters a
Node()with a mouse or pointer device.Example
detail{ "sourceEvent": {}, "node": { "id": 1, "x": 0, "y": 0 } }
- nodeleave
Fired when a user leaves a
Node()with a mouse or pointer device.Example
detail{ "sourceEvent": {}, "node": { "id": 1, "x": 0, "y": 0 } }
- nodepositionchange
Fired when a
Node()gets new coordinates.Example
detail{ "node": { "id": 1, "x": 0, "y": 0 } }
- nodedragstart
Fired before a
Node()is moved via drag and drop orGraphEditor.moveNode().Example
detail{ "node": { "id": 1, "x": 0, "y": 0 } "affectedChildren": new Set<string>() }
- nodedragend
Fired after a
Node()was moved via drag and drop orGraphEditor.moveNode().Example
detail{ "node": { "id": 1, "x": 0, "y": 0 } "affectedChildren": new Set<string>() }
- nodeadd
Fired when a
Node()gets added to the graph.Use
event.preventDefault()to prevent standard graph behaviour.Example
detail{ "node": { "id": 1, "x": 0, "y": 0 } }
- noderemove
Fired when a
Node()gets removed from the graph.Use
event.preventDefault()to prevent standard graph behaviour.Example
detail{ "node": { "id": 1, "x": 0, "y": 0 } }
Edge Events
Events marked with * have default behaviour that can be prevented with event.preventDefault().
- edgeclick
Fired when a user clicks on a
Edge(). Thekeycan be used to create custom buttons.Use
event.preventDefault()to prevent standard graph behaviour.Example
detail{ "sourceEvent": {}, "edge": { "source": 1, "target": 2 } }
- edgetextpositionchange
Fired when a
TextComponent()of anEdge()got moved by the user. This event could be used to limit the offset coordinates.Example
detail{ "sourceEvent": {}, "text": { "offsetX": 10, "offsetY": 24 }, "edge": { "source": 1, "target": 2 } }
- edgetextdragstart
Fired before a
TextComponent()is moved via drag and drop.Example
detail{ "text": { "offsetX": 10, "offsetY": 24 }, "edge": { "source": 1, "target": 2 } }
- edgetextdragend
Fired after a
TextComponent()was moved via drag and drop.Example
detail{ "text": { "offsetX": 10, "offsetY": 24 }, "edge": { "source": 1, "target": 2 } }
- edgeadd
Fired when an
Edge()gets added to the graph.Use
event.preventDefault()to prevent standard graph behaviour.Example
detail{ "edge": { "source": 1, "target": 2 } }
- edgeremove
Fired when an
Edge()gets removed from the graph.Use
event.preventDefault()to prevent standard graph behaviour.Example
detail{ "edge": { "source": 1, "target": 2 } }
Example Event Usage
This example uses a node template where one part has the data-click="remove" attribute.
This attribute is used in the event to populate the key attribute.
For custom buttons in Edges use markers with the clickEventKey attribute.
<template id="graph-template">
<svg slot="graph">
<defs>
<g id="simple-node" template-type="node">
<rect width="100" height="60" x="-50" y="-30"></rect>
<text class="text" data-click="remove" x="-40" y="-10">remove</text>
</g>
</defs>
</svg>
</template>
<network-graph svg-template="#graph-template"></network-graph>
<script>
var graph = document.querySelector('network-graph');
graph.addEventListener('nodeclick', function test(event) {
console.log(event.type, event.detail);
if (event.detail.key === 'remove') {
event.preventDefault();
}
});
</script>
Customization Using Callbacks
The GraphEditor can be furthor customized by setting some callback functions. This section describes these functions.
Customize Data Before Render
GraphEditor.onBeforeCompleteRender()
This callback can be used to update the graph data right before a render happens.
Customize How CSS Classes for Nodes and Edges are Set
Hint
All CSS classes must be set via the classes attribute first for these callbacks to work!
GraphEditor.setNodeClass()
This callback decides which classes of the classes attribute should be set for a node.
GraphEditor.setEdgeClass()
This callback decides which classes of the classes attribute should be set for an edge.
Customize How Nodes are Moved
GraphEditor.onBeforeNodeMove()
This callback can be used to customize how a node will be moved by manipulating the NodeMovementInformation().
It can also selectively prevent nodes from beeing moved.
Customize How Edges are Dragged
GraphEditor.onCreateDraggedEdge()
This callback can be used to customize the DraggedEdge() right after it is created and before it is rendered.
It can also selectively prevent the creation of a DraggedEdge.
GraphEditor.onDraggedEdgeTargetChange()
This callback can be used to check the current target of a dragged edge and update the edge according to that target. It can be used to create “smart” edges that look different depending on the target node.
GraphEditor.onDropDraggedEdge()
This callback can be used to change the dragged edge right after the user finished the drag gesture.
It is similar to GraphEditor.onDraggedEdgeTargetChange(), but will only be called once with the final target.
Customize Where Edges Attach to Nodes
GraphEditor.calculateLinkHandlesForEdge()
This callback can be used to customize the possible positions where an edge can attach to a node.