Skip to content
Pivotick
Main Navigation HomeGetting StartedConfigurationGalleryTry it out!Generated API docs

Appearance

Sidebar Navigation

Getting Started

Configuration

Callbacks

Layout

Render

Simulation

Customizing UI

Sidebar

Tooltip

Context Menu

Styling UI

Pivotick API

Security

API docs

Gallery

Basics

Node styling

Edge styling

Layouts

Events & callbacks

UI customization

Editing & authoring

Notes & annotations

Filtering, search & hierarchy

Programmatic control

Theming & performance

Showpieces

Validate & enrich new edges ​

Two connect-time hooks let the consumer own edge creation. isValidConnection runs live during the gesture — an invalid target draws a red preview and can't be dropped, and the before-create hook is never consulted for it. onBeforeEdgeCreate runs once a valid target is chosen, just before the edge exists: return false to veto, or { accept: true, data, style, directed } to accept and stamp the new edge with a label, style, and direction. It may be async — the shadow-edge preview stays up until it settles.

Click Edit Graph (top-right) → Add Edge, then connect nodes. Here you may only link a person to a project — same-type links preview red and are refused live. A valid drop simulates a save, then creates a labeled, directed edge — except onto the archived project, which the before-create hook vetoes after the fact.

js
// Both hooks live under the full UI mode's Edit Graph → Add Edge tool.
const options = {
    UI: { mode: 'full' },
    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
            }
        }
    }
}
js
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' } }
    ]
}

Last updated:

Pager
Next pageGetting Started