Skip to main content
Version: 1.0.0

Load & Save Designs

Export the editor's design as JSON, persist it to your backend, and load it back later.

import { useRef } from "react";
import {
DragbleEditor,
DragbleEditorRef,
DesignJson,
} from "dragble-react-editor";

function EmailEditor() {
const editorRef = useRef<DragbleEditorRef>(null);

const handleSave = async () => {
const design = await editorRef.current?.editor?.exportJson();
await fetch("/api/designs/123", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ design }),
});
};

const handleLoad = async () => {
const res = await fetch("/api/designs/123");
const { design } = await res.json();
editorRef.current?.editor?.loadDesign(design);
};

return (
<>
<DragbleEditor
ref={editorRef}
editorKey="db_your_key"
editorMode="email"
onReady={() => handleLoad()}
/>
<button onClick={handleSave}>Save</button>
</>
);
}

:::tip Save JSON, not HTML Always persist the design JSON from exportJson(). It contains the full editor state (structure, styles, content) and can be loaded back with loadDesign(). HTML is a one-way render — you cannot load HTML back into the editor. :::

Load a design at init

Pass the design JSON directly as a prop or config option instead of calling loadDesign() manually:

<DragbleEditor
ref={editorRef}
editorKey="db_your_key"
design={savedDesignJson}
/>

Load a blank canvas

Call loadBlank() to reset the editor to an empty design:

editorRef.current?.editor?.loadBlank();

Auto-save with debounce

Listen to design:updated events and debounce to avoid hammering your API:

:::warning Debounce auto-save The design:updated event fires on every keystroke and drag. Without debouncing, you'll send hundreds of requests per minute. Use at least a 1-second debounce. :::

import { useRef, useCallback } from "react";
import {
DragbleEditor,
DragbleEditorRef,
DesignJson,
} from "dragble-react-editor";

function AutoSaveEditor() {
const editorRef = useRef<DragbleEditorRef>(null);
const timeoutRef = useRef<ReturnType<typeof setTimeout>>();

const handleChange = useCallback(() => {
clearTimeout(timeoutRef.current);
timeoutRef.current = setTimeout(async () => {
const design = await editorRef.current?.editor?.exportJson();
await fetch("/api/designs/123", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ design }),
});
}, 1000);
}, []);

return (
<DragbleEditor
ref={editorRef}
editorKey="db_your_key"
onChange={handleChange}
/>
);
}

Load with validation

Use loadDesignAsync() to get validation feedback when loading a design:

const result = await editorRef.current?.editor?.loadDesignAsync(design);
console.log(
`Loaded ${result?.validRowsCount} rows, ${result?.invalidRowsCount} invalid`,
);
if (result?.errors) {
console.warn("Validation errors:", result.errors);
}

Method reference

MethodReturnsDescription
exportJson()Promise<DesignJson>Export the current design as a JSON object
loadDesign(json, options?)voidLoad a design JSON into the editor
loadDesignAsync(json, options?)Promise<{ success, validRowsCount, invalidRowsCount, errors? }>Load a design with validation feedback
loadBlank(options?)voidReset to an empty canvas
getDesign()Promise<{ html, json }>Get both HTML and JSON in one call
save()voidTrigger the save event (emits save on the event bus)

Next steps