Validieren und bereichern Sie neue Kanten
Zwei Connect-Time-Hooks ermöglichen dem Verbraucher die eigene Edge-Erstellung. isValidConnection wird während der Geste live ausgeführt – ein ungültiges Ziel zeichnet eine rote Vorschau und kann nicht gelöscht werden, und der Hook vor dem Erstellen wird nie dafür herangezogen. onBeforeEdgeCreate wird ausgeführt, sobald ein gültiges Ziel ausgewählt wurde, kurz bevor die Kante existiert: false zurückgeben, um ein Veto einzulegen, oder { accept: true, data, style, directed }, um die neue Kante zu akzeptieren und mit einer Beschriftung, einem Stil und einer Richtung zu versehen. Es kann asynchron sein – die Schattenkantenvorschau bleibt bestehen, bis sie sich beruhigt.
Klicken Sie auf Diagramm bearbeiten (oben rechts) → Kante hinzufügen und verbinden Sie dann die Knoten. Hier dürfen Sie nur eine Person mit einem Projekt verknüpfen – gleichartige Links werden in der Vorschau rot angezeigt und werden nicht live angezeigt. Ein gültiger Drop simuliert einen Speichervorgang und erstellt dann eine beschriftete, gerichtete Kante – mit Ausnahme des archivierten-Projekts, das der Before-Create-Hook nachträglich deaktiviert.
// Both hooks live under the full UI mode's Edit Graph → Add Edge tool.
const options = {
// Off: `full` mode brings a minimap and the data dock, and this card is about
// neither (see the Minimap and Data table cards for those).
UI: { mode: 'full', minimap: false, table: false },
callbacks: {
// Live predicate — runs on every hover while connecting. Only cross-type
// links (person ↔ project) are valid; anything else previews red and can't
// be dropped. onBeforeEdgeCreate is never consulted for a rejected target.
isValidConnection: (source, target) =>
source.getData().type !== target.getData().type,
// Before-create hook — fires once a valid target is picked, before the edge
// exists. Async here: we simulate persisting the link, then either veto or
// accept with an enriched label / style / direction.
onBeforeEdgeCreate: async ({ source, target, origin }) => {
// Veto after the fact: no new links onto an archived project.
if (source.getData().archived || target.getData().archived) {
graph.notifier.warning('Archived', 'Project Orion is archived — no new links.')
return false
}
graph.notifier.info('Saving…', `${source.getData().label} → ${target.getData().label}`)
await wait(600) // stand-in for a backend POST that could fail
const person = source.getData().type === 'person' ? source : target
const project = person === source ? target : source
graph.notifier.success('Linked', `${person.getData().label} assigned to ${project.getData().label}`)
// Accept and stamp the new edge — the consumer decides what it carries.
return {
accept: true,
data: { label: 'assigned-to', via: origin },
style: { edge: { strokeColor: '#6366f1' } },
directed: true
}
}
}
}const data = {
nodes: [
{ id: 'alice', data: { label: 'Alice', type: 'person' } },
{ id: 'bob', data: { label: 'Bob', type: 'person' } },
{ id: 'carol', data: { label: 'Carol', type: 'person' } },
{ id: 'atlas', data: { label: 'Project Atlas', type: 'project' } },
{ id: 'nova', data: { label: 'Project Nova', type: 'project' } },
{ id: 'orion', data: { label: 'Orion (archived)', type: 'project', archived: true } }
],
edges: [
{ from: 'alice', to: 'atlas', data: { label: 'assigned-to' } }
]
}