DEV Community

Ramy Othman
Ramy Othman

Posted on Originally published at grafloria.com

Custom nodes without the props mystery

Originally published on the Grafloria engineering blog.

Two of the most-viewed custom-node questions on Stack Overflow — "Can you pass props to a custom node?" (9.7k views) and "saving additional data to a node after it has been created" (25k views) — are really one question asked from two directions: who owns a node's data? Get that model wrong and every read and write becomes a mystery.

The mental model

A node has exactly one data home: the data dictionary on the node itself, in the diagram's model. Your component doesn't receive "props you passed" — it receives the node's data, and updating means writing to the node, not to a component. Once that clicks, every framework binding is the same pattern wearing local idiom:

// The spec — identical in all three frameworks:
{ id: 'a', type: 'card', position: { x: 80, y: 90 },
  size: { width: 230, height: 110 },
  data: { title: 'Build', owner: 'CI' } }     // ← the one data home
Enter fullscreen mode Exit fullscreen mode

React — a component per type via nodeTypes, receiving
{ id, data, selected, node } (mark the spec custom: true):

function Card({ data, selected }) {
  return {data.title};
}

Enter fullscreen mode Exit fullscreen mode

Vue — a named slot per type; declaring the slot is the opt-in:


    {{ data.title }}

Enter fullscreen mode Exit fullscreen mode

Angular — an ng-template per type, same auto-opt-in:


    {{ data['title'] }}

Enter fullscreen mode Exit fullscreen mode

And the 25k-view question: writing data later

Because the node owns its data, "saving additional data after creation" is a write to the node — tracked for undo and events like any other model change:

const node = instance.getModel().getNode('a');
node.setData('status', 'passing');   // undoable, observable, serialized
instance.renderNow();
Enter fullscreen mode Exit fullscreen mode

No syncing a parallel store, no cloning the nodes array to smuggle a field in. The escape hatch is symmetric: your component/template also receives the live
node, so reads that outgrow data have somewhere to go.

Deep guides per framework: React · Vue · Angular · plain JavaScript.


Grafloria is an MIT-licensed diagram engine for React, Angular, Vue and plain JavaScript — grafloria.com. If this post was useful, the demo gallery is where the ideas live as running code.

Top comments (0)