Skip to content

Imperative API

The editor exposes an imperative API for driving it from your own buttons or logic. Get it from the ready event or a template ref.

ts
interface EditorApi {
  getDesign(): Design            // deep-cloned snapshot of the current design
  loadDesign(design: Design): void
  newDesign(): void              // clear to a fresh, empty design (no prompt)
  exportHtml(): string           // email-safe HTML for the current design
  save(): void | Promise<void>   // fire the Save flow (emit `save` + onSave prop)
  export(): void | Promise<void> // fire the Export flow (emit `export` + onExport)
  undo(): void
  redo(): void
  registerBlock(def: BlockDefinition): void
  selectBody(): void             // select the email body (opens its inspector)
}

Commands vs. state

The imperative API holds commands (do-a-thing-once). UI state — dark/light mode and preview — is controlled with v-model:colorMode and v-model:preview instead, so there is a single source of truth you can both set and read. See Theming and Props & events.

Getting the API

Via the ready event

vue
<script setup lang="ts">
import { ref } from 'vue'
import { EmailEditor } from 'vue-mail-editor'
import type { EditorApi } from 'vue-mail-editor'

const api = ref<EditorApi>()
</script>

<template>
  <EmailEditor @ready="api = $event" />
  <button @click="api?.undo()">Undo</button>
  <button @click="downloadHtml(api!.exportHtml())">Export</button>
</template>
vue
<script setup>
import { ref } from 'vue'
import { EmailEditor } from 'vue-mail-editor'

const api = ref()
</script>

<template>
  <EmailEditor @ready="api = $event" />
  <button @click="api?.undo()">Undo</button>
  <button @click="downloadHtml(api.exportHtml())">Export</button>
</template>

Via a template ref

vue
<script setup lang="ts">
import { ref } from 'vue'
import { EmailEditor } from 'vue-mail-editor'

const editor = ref<InstanceType<typeof EmailEditor>>()
function save() {
  myBackend.save(editor.value!.getDesign())
}
</script>

<template>
  <EmailEditor ref="editor" />
</template>
vue
<script setup>
import { ref } from 'vue'
import { EmailEditor } from 'vue-mail-editor'

const editor = ref()
function save() {
  myBackend.save(editor.value.getDesign())
}
</script>

<template>
  <EmailEditor ref="editor" />
</template>

Methods

MethodReturnsDescription
getDesign()DesignA deep-cloned snapshot — safe to mutate/store.
loadDesign(design)voidReplace the current design.
newDesign()voidClear to a fresh, empty design. No confirm prompt — show your own first if you want one.
exportHtml()stringRender the design to email-safe HTML (returns it).
save()void | PromiseFire the Save flow — emits save and runs the onSave prop.
export()void | PromiseFire the Export flow — emits export and runs the onExport prop.
undo()voidUndo the last change.
redo()voidRedo the last undone change.
registerBlock(def)voidRegister a custom block at runtime.
selectBody()voidSelect the body and open its inspector.

exportHtml() vs export()

exportHtml() returns the HTML string and does nothing else — use it when you want the markup. export() triggers the full export flow (opens the preview modal, emits export, runs onExport) just like the toolbar button.

TIP

For most apps the events (change, save, export) are enough. Reach for the imperative API when you build a fully custom toolbar with the #header slot.

Released under the MIT License.