Skip to content

Binding

The Binding class manages the bidirectional binding between a draw.io file and a Y.Doc.

Constructor

ts
new Binding(file: any, options: BindDrawioFileOptions)

Parameters

file

The draw.io editor's internal file object, obtained via App.main((app) => app.currentFile).

options

ts
interface BindDrawioFileOptions {
  doc: Y.Doc;                  // required — externally provided Y.Doc
  awareness?: Awareness;       // optional — y-protocols awareness (cursors/selections)
  undoManager?: Y.UndoManager | false; // optional — pass instance to enable undo/redo; pass false to explicitly skip (e.g. iframe-bridge scenario)
  mouseMoveThrottle?: number;  // optional — cursor throttle in ms, default 100
  cursor?:                     // optional — remote cursor rendering config
    | boolean
    | {
        userNameKey?: string;  // awareness field for user name, default 'user.name'
        userColorKey?: string; // awareness field for color, default 'user.color'
      };
  initialContent?: InitialContentStrategy; // optional — default 'replace'
  applyFileData?: (file, xml) => void;     // optional — custom file data apply
  disableBeforeUnload?: boolean;           // optional — default true
  transformPatch?: (patch: FilePatch) => FilePatch | null | undefined; // optional — transform/filter local patches before syncing
}

initialContent

Controls how the file and Y.Doc are aligned when binding. Default is 'replace'.

StrategyBehavior
replaceIf doc has data, overwrite file with doc; if doc is empty, keep file as-is
merge-remoteUnion by diagram id; on conflict, doc wins (remote authoritative)
merge-clientUnion by diagram id; on conflict, file wins (local authoritative)

applyFileData

Custom function to apply XML to the draw.io file. Default only calls file.ui.setFileData(xml) (rebuilds UI/pages), intentionally not calling file.setData(xml) to avoid marking the file as "modified" which triggers draw.io's "Save diagrams to:" storage dialog.

If you need to sync file.data (e.g., for custom CollabFile or file.save()), provide a custom implementation:

ts
new Binding(file, {
  doc,
  applyFileData: (f, xml) => {
    f.ui.setFileData(xml);
    f.setData(xml);
  },
});

disableBeforeUnload

Whether to disable draw.io's beforeunload dialog. Default is true.

After Yjs takes over persistence, draw.io's native save state is no longer meaningful. However, draw.io internally shows "All changes will be lost" or "Ensure your data has been saved" dialogs under certain conditions (e.g., LocalFile without fileHandle, non-empty diagram, etc.).

Set to true (default) to completely disable these dialogs — suitable for pure Yjs collaboration scenarios. Set to false to preserve native behavior (e.g., when using File System Access API).

transformPatch

Optional callback to transform or filter local patches before syncing to Y.Doc. Useful for scenarios like external image storage.

Signature: (patch: FilePatch) => FilePatch | null | undefined

Return value:

  • undefined or original patch: no filtering, sync as-is
  • Modified FilePatch: use the modified patch for syncing
  • null: skip this sync entirely

Example — Image storage optimization:

ts
import { Binding } from 'y-mxgraph';

// Extract base64 images to IndexedDB, sync only img:<uuid> references
const binding = new Binding(file, {
  doc,
  transformPatch: (patch) => {
    // Detect and remove base64 images from patch
    // Upload images to storage asynchronously
    // Return modified patch with img:<uuid> references
    return transformedPatch;
  },
});

See IMAGE-STORAGE.md for a complete implementation.

Instance Properties

doc: Y.Doc

The bound Y.Doc instance. Read-only.

Static Methods

Binding.generateFileTemplate(diagramId?: string): string

Generates a standardized mxfile XML template to ensure consistent collaboration starting data across all clients.

Parameters:

  • diagramId — fixed diagram id, defaults to "diagram-0"

Returns: A minimal mxfile XML string

Why this is needed:

When draw.io creates a new diagram, it generates a random id (e.g., DEMOabHTdChjKBf1yHdD). If each client initializes with a different diagram id, the Y.Doc data cannot align with the local file.data, causing late-joining clients to see "orphan pages" and patch diffs to fail matching diagram/cell ids, breaking collaboration.

The consumer should use this method to generate a unified starting XML before initializing the draw.io file, then inject it into currentFile.data (see "Integration Notes" for details).

Example:

ts
import { Binding } from 'y-mxgraph';

// Use default id "diagram-0"
const template = Binding.generateFileTemplate();

// Or specify a fixed id (e.g., bound to room/project)
const template = Binding.generateFileTemplate("room-123-main");

Instance Methods

destroy(deep?: boolean): void

Destroys the binding and removes all listeners.

Parameters:

  • deep — whether to perform a full cleanup, defaults to false
    • false: removes only the core binding listeners (mxGraphModel change, Y.Doc observeDeep)
    • true: full cleanup including Awareness/UndoManager subsystems and restores the original undoManager

Recommendations:

  • Call destroy() on page unload/close
  • Call destroy(true) when dynamically switching draw.io files

Examples

Basic Usage

ts
import * as Y from 'yjs';
import { Binding } from 'y-mxgraph';

const doc = new Y.Doc();

App.main((app) => {
  const binding = new Binding(app.currentFile, { doc });

  window.addEventListener('beforeunload', () => {
    binding.destroy();
  });
});

With React / Vue

ts
// React
useEffect(() => {
  const binding = new Binding(file, { doc, awareness });
  return () => binding.destroy(true);
}, [file, doc]);

// Vue
const binding = new Binding(file, { doc, awareness });
onUnmounted(() => {
  binding.destroy(true);
});

About UndoManager

Binding no longer creates a Y.UndoManager internally. To enable undo/redo, create one externally and pass it in:

ts
const undoManager = new Y.UndoManager(doc, {
  trackedOrigins: new Set([LOCAL_ORIGIN]),
});

const binding = new Binding(file, { doc, undoManager });

LOCAL_ORIGIN is a static marker object exported by y-mxgraph used to distinguish local transactions from remote ones.

Released under the MIT License.