Load & Save Designs
Export the editor's design as JSON, persist it to your backend, and load it back later.
- React
- Vue
- Angular
- Vanilla JS
import { useRef } from 'react';
import { PexelizeEditor, PexelizeEditorRef, DesignJson } from '@pexelize/react-editor';
function EmailEditor() {
const editorRef = useRef<PexelizeEditorRef>(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 (
<>
<PexelizeEditor
ref={editorRef}
editorKey="pk_your_key"
editorMode="email"
onReady={() => handleLoad()}
/>
<button onClick={handleSave}>Save</button>
</>
);
}
<template>
<PexelizeEditor
ref="editorRef"
editor-key="pk_your_key"
editor-mode="email"
@ready="handleLoad"
/>
<button @click="handleSave">Save</button>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { PexelizeEditor } from '@pexelize/vue-editor';
const editorRef = ref<InstanceType<typeof PexelizeEditor>>();
async function handleSave() {
const design = await editorRef.value?.exportJson();
await fetch('/api/designs/123', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ design }),
});
}
async function handleLoad() {
const res = await fetch('/api/designs/123');
const { design } = await res.json();
editorRef.value?.loadDesign(design);
}
</script>
import { Component, ViewChild } from '@angular/core';
import { PexelizeEditorComponent } from '@pexelize/angular-editor';
import type { PexelizeSDK, DesignJson } from '@pexelize/editor-types';
@Component({
selector: 'app-email-editor',
standalone: true,
imports: [PexelizeEditorComponent],
template: `
<pexelize-editor
#editor
editorKey="pk_your_key"
editorMode="email"
(ready)="onReady($event)"
></pexelize-editor>
<button (click)="handleSave()">Save</button>
`,
})
export class EmailEditorComponent {
@ViewChild('editor') editorComp!: PexelizeEditorComponent;
private sdk: PexelizeSDK | null = null;
async onReady(sdk: PexelizeSDK) {
this.sdk = sdk;
await this.handleLoad();
}
async handleSave() {
const design = await this.sdk?.exportJson();
await fetch('/api/designs/123', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ design }),
});
}
async handleLoad() {
const res = await fetch('/api/designs/123');
const { design } = await res.json();
this.sdk?.loadDesign(design);
}
}
<div id="editor-container" style="height: 600px;"></div>
<button id="save-btn">Save</button>
<script src="https://sdk.pexelize.com/latest/pexelize-sdk.min.js"></script>
<script>
pexelize.init({
containerId: 'editor-container',
editorKey: 'pk_your_key',
editorMode: 'email',
callbacks: {
onReady: () => handleLoad(),
},
});
async function handleSave() {
const design = await pexelize.exportJson();
await fetch('/api/designs/123', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ design }),
});
}
async function handleLoad() {
const res = await fetch('/api/designs/123');
const { design } = await res.json();
pexelize.loadDesign(design);
}
document.getElementById('save-btn').addEventListener('click', handleSave);
</script>
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:
- React
- Vue
- Angular
- Vanilla JS
<PexelizeEditor
ref={editorRef}
editorKey="pk_your_key"
design={savedDesignJson}
/>
<PexelizeEditor
ref="editorRef"
editor-key="pk_your_key"
:design="savedDesignJson"
/>
<pexelize-editor
#editor
editorKey="pk_your_key"
[design]="savedDesignJson"
></pexelize-editor>
pexelize.init({
containerId: 'editor-container',
editorKey: 'pk_your_key',
design: savedDesignJson,
});
Load a blank canvas
Call loadBlank() to reset the editor to an empty design:
- React
- Vue
- Angular
- Vanilla JS
editorRef.current?.editor?.loadBlank();
editorRef.value?.loadBlank();
this.sdk?.loadBlank();
pexelize.loadBlank();
Auto-save with debounce
Listen to design:updated events and debounce to avoid hammering your API:
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.
- React
- Vue
- Angular
- Vanilla JS
import { useRef, useCallback } from 'react';
import { PexelizeEditor, PexelizeEditorRef, DesignJson } from '@pexelize/react-editor';
function AutoSaveEditor() {
const editorRef = useRef<PexelizeEditorRef>(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 (
<PexelizeEditor
ref={editorRef}
editorKey="pk_your_key"
onChange={handleChange}
/>
);
}
<template>
<PexelizeEditor
ref="editorRef"
editor-key="pk_your_key"
@change="handleChange"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { PexelizeEditor } from '@pexelize/vue-editor';
const editorRef = ref<InstanceType<typeof PexelizeEditor>>();
let timeout: ReturnType<typeof setTimeout>;
function handleChange() {
clearTimeout(timeout);
timeout = setTimeout(async () => {
const design = await editorRef.value?.exportJson();
await fetch('/api/designs/123', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ design }),
});
}, 1000);
}
</script>
import { Component, ViewChild, OnDestroy } from '@angular/core';
import { PexelizeEditorComponent } from '@pexelize/angular-editor';
import type { PexelizeSDK } from '@pexelize/editor-types';
@Component({
selector: 'app-autosave-editor',
standalone: true,
imports: [PexelizeEditorComponent],
template: `
<pexelize-editor
#editor
editorKey="pk_your_key"
(ready)="onReady($event)"
(change)="handleChange()"
></pexelize-editor>
`,
})
export class AutoSaveEditorComponent implements OnDestroy {
@ViewChild('editor') editorComp!: PexelizeEditorComponent;
private sdk: PexelizeSDK | null = null;
private timeout?: ReturnType<typeof setTimeout>;
onReady(sdk: PexelizeSDK) {
this.sdk = sdk;
}
handleChange() {
clearTimeout(this.timeout);
this.timeout = setTimeout(async () => {
const design = await this.sdk?.exportJson();
await fetch('/api/designs/123', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ design }),
});
}, 1000);
}
ngOnDestroy() {
clearTimeout(this.timeout);
}
}
let saveTimeout: ReturnType<typeof setTimeout>;
pexelize.init({
containerId: 'editor-container',
editorKey: 'pk_your_key',
callbacks: {
onChange: () => {
clearTimeout(saveTimeout);
saveTimeout = setTimeout(async () => {
const design = await pexelize.exportJson();
await fetch('/api/designs/123', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ design }),
});
}, 1000);
},
},
});
Load with validation
Use loadDesignAsync() to get validation feedback when loading a design:
- React
- Vue
- Angular
- Vanilla JS
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);
}
const result = await editorRef.value?.editor?.loadDesignAsync(design);
console.log(`Loaded ${result?.validRowsCount} rows, ${result?.invalidRowsCount} invalid`);
const result = await this.sdk?.loadDesignAsync(design);
console.log(`Loaded ${result?.validRowsCount} rows, ${result?.invalidRowsCount} invalid`);
const result = await pexelize.loadDesignAsync(design);
console.log(`Loaded ${result.validRowsCount} rows, ${result.invalidRowsCount} invalid`);
Method reference
| Method | Returns | Description |
|---|---|---|
exportJson() | Promise<DesignJson> | Export the current design as a JSON object |
loadDesign(json, options?) | void | Load a design JSON into the editor |
loadDesignAsync(json, options?) | Promise<{ success, validRowsCount, invalidRowsCount, errors? }> | Load a design with validation feedback |
loadBlank(options?) | void | Reset to an empty canvas |
getDesign() | Promise<{ html, json }> | Get both HTML and JSON in one call |
save() | void | Trigger the save event (emits save on the event bus) |
Next steps
- Export HTML — render the design as production-ready HTML
- Export PDF, Image & ZIP — server-side rendering exports
- Customize Appearance — themes and accent colors