Skip to main content
Version: 4.3

Interactivity

The interactive prop on <Paper> controls which of the built-in interactions a user is allowed to perform: dragging elements, moving and reconnecting links, adding vertices and labels, and drawing new links from ports. It accepts three forms:

  • a boolean to turn every interaction on or off at once,
  • an object of flags to enable or disable interactions individually,
  • a function to decide per cell.

Boolean form​

The simplest form is a boolean. false makes the paper read-only; true enables every interaction.

// read-only
<Paper interactive={false} />

// fully interactive
<Paper interactive={true} />

A static interactive={false} is the usual way to render a non-editable diagram, such as a thumbnail, a preview, or a published view.

Per-interaction flags​

Pass an object to enable or disable specific interactions. Assign false to the ones you want to turn off; most omitted flags default to true. The exceptions are labelMove and linkMove, which @joint/react keeps off by default even in the object form, so set them to true explicitly to enable them.

// elements can be selected and connected, but not dragged
<Paper interactive={{ elementMove: false }} />

// lock element positions and disallow drawing links from ports
<Paper interactive={{ elementMove: false, addLinkFromMagnet: false }} />

Common flags include elementMove, linkMove, labelMove, and addLinkFromMagnet. In @joint/react, the true shorthand keeps labelMove and linkMove off by default. For the complete list of recognized flags, see interactive in the dia.Paper reference.

Function form​

For per-cell logic, pass a function. It receives a context object and returns a boolean or a flags object. Branch on model, the only field you can count on, and return the flags you want to apply.

// elements whose data marks them locked can't be touched; the rest stay interactive
<Paper
interactive={({ model }) => (model.get('data')?.locked ? false : true)}
/>

This is the most flexible form. Use it when interactivity depends on the cell itself or on application state. The value you return is normalized the same way as the static forms: the @joint/react defaults (labelMove and linkMove off) are applied first, and any flags you return override them. Returning true or an empty object yields those same defaults.

Toggling interactivity dynamically​

Whichever form you use, interactive is an ordinary prop you can drive from state. The editor below keeps it in state and flips it with an Edit/View switch. In Edit mode the paper is fully interactive: drag shapes around, click one to select it, and edit its label in the property editor. Switch to View mode and the paper becomes read-only (interactive: false); dragging is disabled, and hovering a shape shows a read-out instead.

The toggle swaps the value passed to interactive, along with the event handlers that go with each mode:

const interactivity = useMemo(() => {
if (editMode) {
return {
interactive: true,
onElementPointerClick: ({ id }) => setSelectedId(id),
};
}
return {
interactive: false,
onElementMouseEnter: ({ id }) => setHovered(id),
};
}, [editMode]);

return <Paper renderElement={renderElement} {...interactivity} />;

API reference​

For the full option signature and the complete list of interactivity flags, see interactive in the dia.Paper API reference. If you need to set interactivity outside the prop (from a paper ref), dia.Paper also exposes an imperative setInteractivity().

Feature-level interactions

interactive governs cell-level interactions: moving elements, reconnecting links, adding vertices. JointJS+'s <Diagram> adds a separate feature-level layer (pan, zoom, rubber-band selection, undo/redo, copy/paste) toggled with its own interactions prop. See Built-in interactions.