JavaScript is required

Interactive Line Path Editing

This example shows how to click an existing line and reshape its route with relation-graph's built-in line editing overlay. It also coordinates node selection, canvas clearing, runtime canvas settings, and toast feedback inside a compact editor-style workspace.

Editing Existing Line Paths with Built-In Overlay Handles

What This Example Builds

This example builds a compact graph editing workspace for modifying the route of an existing connection. The screen shows a full-height graph canvas, a floating instruction window, green curved links by default, and a dotted background that makes the canvas feel like an editing surface rather than a read-only viewer.

Users can click a line to activate built-in path editing handles, drag selection across the canvas to select nodes, and clear the current editing state by clicking empty space. The main point of interest is that the example isolates line-route editing without turning into a full graph editor, so the relationship between selection state and line editing stays easy to study.

How the Data Is Organized

The graph data is declared inline as a single RGJsonData object. It uses a rootId, a flat nodes array with simple id and text fields, and a lines array with from, to, text, and occasional per-line overrides such as lineShape and junction points.

There is no preprocessing pipeline before setJsonData(). The component creates the dataset inside initializeGraph(), loads it on mount, and then calls zoomToFit() so the default graph arrangement is visible immediately.

In a production system, the same structure could represent workflow steps, dependency edges, approval routes, lineage links, or any other record set where a connection’s path may need manual adjustment after the graph is rendered.

How relation-graph Is Used

The example does not configure a custom layout algorithm. Instead, it loads a small root-based dataset into RelationGraph, lets relation-graph render it with the library’s default behavior, and then adjusts the viewport with zoomToFit().

The graph options stay intentionally small: defaultLineShape is set to RGLineShape.StandardCurve, and defaultLineColor is set to #00a63e. Most of the lesson is in runtime editing APIs rather than in initial layout configuration.

RGProvider wraps the example so RGHooks.useGraphInstance() can retrieve the active graph instance. That instance drives setJsonData, zoomToFit, setEditingNodes, setEditingLine, toggleEditingNode, getNodesInSelectionView, clearChecked, and addLines. The floating settings panel also uses RGHooks.useGraphStore() to read current options and setOptions() to switch wheel and drag behavior at runtime.

The editing UI is attached in RGSlotOnView, not by replacing the node or line renderers. RGEditingConnectController and RGEditingLineController are mounted as view-layer overlays, with textEditable={false} and pathEditable={true}. That combination keeps the example focused on route geometry instead of label editing.

The stylesheet customizes the visual shell rather than the graph model. It adds a scale-aware dotted canvas background using relation-graph transform variables, keeps line labels colored by each line’s current color, and inverts checked line labels so the active connection stands out during editing.

Key Interactions

  • Clicking a line makes that line the active editing target, which exposes the built-in route editing overlay.
  • Dragging a line path handle triggers toast feedback during path changes and vertex move lifecycle events.
  • Clicking a node without modifiers replaces the editing-node set with that node; clicking with Shift, Ctrl, or Meta toggles the node in the current editing set.
  • Drag-box selection collects all nodes inside the selection rectangle and replaces the editing-node set with those results.
  • Clicking empty canvas space clears editing nodes, clears the active editing line, and removes checked-state highlighting.
  • Opening the floating settings panel lets the user switch wheel behavior, switch canvas drag behavior, and export the canvas as an image.

Key Code Fragments

This fragment shows that the example uses an inline graph dataset and loads it directly on mount.

const myJsonData: RGJsonData = {
    rootId: 'a',
    nodes: [
        { id: 'a', text: 'Border color' },
        { id: 'a1', text: 'No border' },
        { id: 'a2', text: 'Plain' },
        // ... more nodes and lines ...
    ]
};

This fragment shows the mount-time load step that sends the dataset into relation-graph and fits the viewport.

// setJsonData is async
await graphInstance.setJsonData(myJsonData);
graphInstance.zoomToFit();

This fragment shows how node selection and line selection are kept in sync instead of being treated as separate, unrelated modes.

const onNodeClick = (nodeObject: RGNode, $event: RGUserEvent) => {
    if ($event.shiftKey || $event.ctrlKey || ($event.metaKey && !$event.altKey)) {
        graphInstance.toggleEditingNode(nodeObject);
    } else {
        graphInstance.setEditingNodes([nodeObject]);
    }
    graphInstance.setEditingLine(null);
};

This fragment shows the canvas-level handoff that replaces the editing-node set after a drag-box selection.

const onCanvasSelectionEnd = (selectionView: RGSelectionView) => {
    const willSelectedNodes = graphInstance.getNodesInSelectionView(selectionView) || [];
    graphInstance.setEditingNodes(willSelectedNodes);
};

This fragment shows the exact overlay configuration that makes existing lines route-editable while keeping inline text editing disabled.

<RGSlotOnView>
    <RGEditingConnectController />
    <RGEditingLineController
        textEditable={false}
        pathEditable={true}
        onLinePathChanged={onLinePathChanged}
        onMoveLineVertexStart={onMoveLineVertexStart}
        onMoveLineVertexEnd={onMoveLineVertexEnd}
    />
</RGSlotOnView>

This fragment shows that the example does more than expose handles visually: it also reacts to edit lifecycle callbacks and surfaces feedback to the user.

const onMoveLineVertexEnd = (
    fromNode: RGNode | RGLineTarget | RGPosition,
    toNode: RGNode | RGLineTarget | RGPosition,
    newLineJson?: JsonLine
) => {
    if (newLineJson && newLineJson.from && newLineJson.to) {
        graphInstance.addLines([newLineJson]);
        SimpleGlobalMessage.success('LineVertexChanged:' + newLineJson.text);
    } else {
        SimpleGlobalMessage.error('Line Removed!');
    }
};

This fragment shows the stylesheet that turns the canvas into a dotted editing surface and makes checked line labels visually stronger.

background-position: var(--rg-canvas-offset-x) var(--rg-canvas-offset-y);
background-size: calc(var(--rg-canvas-scale) * 15px) calc(var(--rg-canvas-scale) * 15px);
background-image: radial-gradient(
    circle,
    rgb(197, 197, 197) calc(var(--rg-canvas-scale) * 1px),
    transparent 0
);

What Makes This Example Distinct

Compared with nearby examples such as change-line-vertices and change-line-text, this one is the clearest route-geometry reference. It enables pathEditable={true} while keeping textEditable={false}, so the lesson is about reshaping an existing line’s path rather than reconnecting endpoints or maintaining labels.

It also stands out among the editor-style VIP examples because it combines several rare features in a small file set: selected-line overlay handles, selection-state handoff between nodes, lines, and canvas clicks, toast feedback for path edits, and a dotted canvas with checked-line emphasis. That combination makes it a practical starting point when a team needs editable edge routing without adopting a larger graph-authoring surface.

The comparison data also makes an important boundary clear. This is not the custom-toolbar example, not the node-alignment example, and not the node-originated line-creation example. Its distinctive value is built-in editing of an already existing connection route.

Where Else This Pattern Applies

This pattern can be reused in workflow designers where users need to clean up connector paths after automatic layout. It also fits dependency diagrams, data-lineage tools, and architecture maps where the graph structure is known in advance but some edges need manual route correction for readability.

A second extension is review or maintenance tooling. Teams can adapt the same selection handoff and callback pattern to persist edited routes, record audit events for geometry changes, or attach validation rules before accepting an updated line path.