Skip to content
D
Documentation

Edit and route edges

how-to
3 min readUpdated

Use an edge specification for semantic intent, then let the mounted diagram route and edit the geometry. This page shows obstacle avoidance, endpoint reconnection, and editable waypoints in JavaScript, Angular, Qwik, React, and Vue.

Choose the edge geometry

An EdgeSpec needs only source and target. Set type for the line's shape and router for the path it takes. orthogonal produces right-angle segments; manhattan uses grid-based right-angle routing; avoid routes around nodes and re-routes as they move; elk uses the ELK edge router. connector changes how the routed segments are drawn.

In JavaScript, render mounts the spec and returns a live DiagramInstance. The following mounted diagram puts a wall between A and B. The avoid edge bends around it rather than crossing it. Replace avoid with orthogonal, manhattan, or elk when you want to choose a different router.

The same mounted instance is exposed by GrafloriaFlow in the Qwik binding; the React, Vue, and Angular bindings use the same engine and edge data.

js
import { render } from '@grafloria/element';

const host = document.getElementById('diagram');
if (!host) throw new Error('Missing #diagram');
host.style.height = '100vh';
const nodes = [
  { id: 'a', position: { x: 80, y: 305 }, size: { width: 120, height: 60 }, label: 'A' },
  { id: 'b', position: { x: 840, y: 305 }, size: { width: 120, height: 60 }, label: 'B' },
  { id: 'wall', position: { x: 430, y: 250 }, size: { width: 140, height: 170 }, label: 'obstacle' },
];
const edges = [{ id: 'e1', source: 'a', target: 'b', router: 'avoid', connector: 'rounded' }];
const instance = render({ nodes, edges }, host);
instance.fitView();

The wire visibly detours around the wall. Move the wall through the corridor and the route follows it; remove the wall and the clear route becomes a two-point line. See the edge routing demo.

A right-angle wire bends around the labelled obstacle between A and B.

Reconnect an endpoint

Select an edge, then drag its endpoint handle onto another node's port. The mounted diagram changes the link from A→B to A→C and emits the reconnect event. Pin handles when the endpoint must land on a particular side.

js
import { render } from '@grafloria/element';

const host = document.getElementById('diagram');
if (!host) throw new Error('Missing #diagram');
host.style.height = '100vh';
const instance = render({
  nodes: [
    { id: 'a', position: { x: 80, y: 260 }, size: { width: 120, height: 60 }, label: 'A' },
    { id: 'b', position: { x: 660, y: 110 }, size: { width: 120, height: 60 }, label: 'B' },
    { id: 'c', position: { x: 660, y: 430 }, size: { width: 120, height: 60 }, label: 'C' },
  ],
  edges: [{ id: 'e1', source: 'a', target: 'b', sourceHandle: 'right', targetHandle: 'left', type: 'direct' }],
}, host);
const unsubscribe = instance.on('reconnect', ({ link }) => {
  console.log(`edge now targets ${link.targetNodeId}`);
});

// Keep `unsubscribe` and call it from your host's unmount or teardown hook.

The selected edge displays endpoint handles; dropping the target handle on C rewires the existing edge, rather than creating a second edge. The change is one undoable edit. See the reconnect edge demo.

A selected wire runs from A to C with its endpoint handle on C.

Add editable waypoints

Waypoint editing is opt-in. Enable it through the mounted diagram's interaction configuration, select an edge, click its path to add an interior point, then drag that point. The endpoints remain attached to their nodes, and each bend is one undoable edit.

js
import { render } from '@grafloria/element';

const host = document.getElementById('diagram');
if (!host) throw new Error('Missing #diagram');
host.style.height = '100vh';
const instance = render({
  nodes: [
    { id: 'a', position: { x: 120, y: 260 }, size: { width: 120, height: 60 }, label: 'A' },
    { id: 'b', position: { x: 660, y: 260 }, size: { width: 120, height: 60 }, label: 'B' },
  ],
  edges: [{ id: 'e1', source: 'a', target: 'b', type: 'direct' }],
}, host, { interaction: { enableWaypointEditing: true, showWaypointHandles: true } });

instance.renderNow();

The selected line gains a handle at the clicked position; dragging it bends the route while A and B stay fixed. points contains the resulting interior coordinates, so an edited route can be saved and restored as edge data. See the editable edge demo.

A selected edge has a waypoint handle below its straight path between A and B.

For a saved route, pass points in the edge spec. The points are interior world coordinates of Point values; the renderer supplies the endpoint geometry. Use waypoints when you want to declare the bends as the edge's routing intent rather than restore an edited route.

Options that matter

OptionTypeDefaultWhat it does
type'direct' | 'smooth' | 'orthogonal' | 'bezier'—Selects the line shape.
router'straight' | 'orthogonal' | 'manhattan' | 'avoid' | 'elk'—Selects the path algorithm.
connector'straight' | 'rounded' | 'smooth' | 'bezier'—Selects the drawing treatment for the route.
sourceHandle / targetHandlestring—Pins an endpoint to a port, side, or positioned side such as right@36.
pointsPoint[]—Restores explicit interior waypoints.
waypointsPoint[]—Declares the bends the router must keep.
interaction.enableWaypointEditingbooleanoffEnables adding and dragging waypoints from the mounted interaction layer.
interaction.showWaypointHandlesboolean—Shows waypoint handles while editing.

Pitfalls

  • Give the host a resolved height such as 100vh; a canvas without height appears blank. See Style a diagram.
  • Use the instance's getEngine().undo() for undo; undo() is not a DiagramInstance method. See Commands, events, and undo.
  • A declarative layout prop does not re-run when node data changes. Call the engine layout method explicitly when your application changes data. See How Grafloria works.

Was this page helpful?