Diagram - Drag and Drop
Move one or several nodes, respect containment and editing policies, and cancel or undo a move.
#Usage
import { Diagram } from '@primeui/vue-diagram';
import MoveSelection from './MoveSelection.vue';<Diagram.Root :store="store" page-id="page">
<MoveSelection />
<Diagram.Viewport label="Workflow editor" style="height: 24rem" />
</Diagram.Root>Drag a selected node in the viewport or offer a non-drag action. Movement uses world units and current ownership constraints.
Create MoveSelection.vue and mount it under the root as above. The handler reads
the current session when activated, including after a page or source change.
<script setup lang="ts">
import { shallowRef } from 'vue';
import { useDiagramContext } from '@primeui/vue-diagram';
const { session } = useDiagramContext();
const feedback = shallowRef('');
function run() {
const result = session.value.edit({ kind: 'move', delta: { x: 40, y: 0 } });
feedback.value = result.status;
}
</script>
<template>
<button type="button" @click="run">Move selection right</button>
<output aria-live="polite">{{ feedback }}</output>
</template>This skeleton assumes an initialized store with page page. Use First Diagram for model creation, style imports and store disposal.
Select a node and drag its body to move it. The session previews geometry while dragging and commits the accepted move on release as one history operation. Connectors attached to the moved nodes follow their endpoints.
#Move one or several nodes
Select the first card or both cards, then drag a selected card. Release the selection modifier before dragging. Numeric X and Y values provide an application control for the same public editing gateway.
The following action reads the current session in a child component rendered
inside Diagram.Root. In setup, context refs require .value.
import { useDiagramContext } from '@primeui/vue-diagram';
const { session } = useDiagramContext();
session.value.select(['first', 'second']);
const result = session.value.edit({ kind: 'move', delta: { x: 40, y: 0 } });The default target is the current selection; pass an explicit ID list as the second argument when an application action has its own target. An explicit list does not itself select those records. Movement is a relative delta in world units. X increases to the right and Y downward. Both values must be finite. Numeric zero movement can be a no-op; it does not need a new Undo entry.
The editor normalizes selected node roots. If a parent and its child are selected, the child travels with the parent rather than receiving the delta twice. Selected connectors are excluded from node transforms. Attached or layout-owned geometry may reject independent movement and require its owner's API.
| Action | Default behavior |
|---|---|
| Drag an unselected node | Select it, then move after the pointer threshold |
| Drag a selected node | Move the selected node roots together |
| Shift, Command or Ctrl-click | Toggle selection; release the modifier before moving |
| Alt+Arrow / Alt+Shift+Arrow | Move selected nodes by 1 / 10 world units from the canvas |
| Plain arrow keys | Navigate keyboard focus |
| Undo / Command or Ctrl+Z | Replay a committed move if current policy permits |
The pointer threshold is 4 viewport CSS pixels. The world delta accounts for viewport zoom and each node's parent transform. A completed move changes authored geometry; selection and viewport navigation do not become model history.
#Stay within a container or reject a move
Try Move inside 30, Try outside 300, and Movement block. The
container has containment: 'inside'; an escaping child body rejects the numeric
command. A move: false policy rejects it independently of containment.
The gateway checks read-only state, record constraints, owning locks, affected
descendants and structure rules. Check result.status and result.diagnostics;
use session.availability(command, ids) to explain a currently unavailable action.
During a pointer drag an invalid frame does not replace the last valid preview.
A rejected finish cancels the gesture; it does not silently commit an invalid drop.
#Move between owners
An ordinary node-body drag changes position within its current owner. It does not infer a new parent from the node under the pointer. Use a structural command for an application-owned container change:
import { useDiagramContext } from '@primeui/vue-diagram';
const { session } = useDiagramContext();
const result = session.value.structure.execute({
kind: 'reparent',
ids: ['child'],
parentId: 'destination'
});Reparenting preserves world placement through parent transforms and checks the
prospective ownership rules. Use parentId: null to return a node to page space.
See containers and ownership for grouping,
clipping, collapse, pages, layers and destination constraints.
Swimlane transfer has its own selected-content handle and public transfer API. Move within a lane with ordinary node movement; move into or out of a lane with the transfer workflow. Invalid headers or a destination that cannot fit the content cancel the transfer. Lane records themselves are layout-owned and cannot be moved independently. The Swimlanes guide retains the dedicated transfer examples and exact ownership contract.
#Cancel or undo
Press Escape during a pointer drag to discard its preview. Pointer cancellation, lost capture and window blur also cancel an unfinished gesture. Cancellation adds no model history entry. Release an accepted gesture, then choose Undo to restore its previous geometry. Current policy can block history replay.
Reset restores the example's model, numeric values, history, selection and initial fitted view. Native numeric inputs retain their own keyboard behavior. Mouse and keyboard are the authored paths here; touch, pen and assistive-technology behavior remain subject to device-specific verification.