New

docx-editor 1.x has shipped. Vue support, i18n, agents. Read the migration guide →

Vue

Props

DocxEditorProps for the Vue 3 adapter: the same prop shape as the React component, bound with Vue's kebab-case attribute syntax.

The Vue adapter accepts the same props as React; the differences are Vue's kebab-case attribute binding and template refs in place of useRef. Anything documented under React props applies, this page focuses on the Vue-specific bits. Full generated reference: /docs/1.x/api/vue.

Binding props

Camel-case in TS, kebab-case in the template. Bind with : for non-string values:

<script setup lang="ts">
import { ref } from "vue";
import { DocxEditor, type EditorMode } from "@eigenpal/docx-editor-vue";
import "@eigenpal/docx-editor-vue/styles.css";
 
const buf = ref<ArrayBuffer | null>(null);
const mode = ref<EditorMode>("editing");
</script>
 
<template>
  <DocxEditor
    :document-buffer="buf"
    :mode="mode"
    author="Jess Lin"
    :show-zoom-control="true"
    @mode-change="(m) => (mode = m)"
  />
</template>

Props that are React callbacks become Vue events. So onModeChange in React is @mode-change in Vue. Same payload shape.

Template ref

Capture the editor ref with useTemplateRef (Vue 3.5+) or ref="..." + a ref():

<script setup lang="ts">
import { useTemplateRef } from "vue";
import { DocxEditor, type DocxEditorRef } from "@eigenpal/docx-editor-vue";
 
const editor = useTemplateRef<DocxEditorRef>("editor");
 
async function save() {
  const buf = await editor.value?.save();
  if (buf) await fetch("/api/documents/1", { method: "PUT", body: buf });
}
</script>
 
<template>
  <button @click="save">Save</button>
  <DocxEditor ref="editor" :document-buffer="null" />
</template>

Methods on DocxEditorRef match React one-to-one (save, addComment, proposeChange, findInDocument, scrollToParaId, scrollToPosition, getDocument). See React props for the table.

Props by group

The groupings under React props all apply identically. Quick map of the binding syntax for each group.

Document input

<DocxEditor :document-buffer="buf" />
<!-- or, pre-parsed -->
<DocxEditor :document="parsed" />

Mode and read-only

<DocxEditor :document-buffer="buf" :mode="mode" @mode-change="(m) => (mode = m)" />
<DocxEditor :document-buffer="buf" read-only />

Comments and collaboration

<DocxEditor
  :document-buffer="buf"
  author="Jess Lin"
  :comments="comments"
  @comments-change="(next) => (comments = next)"
/>

Toolbar and chrome

<DocxEditor
  :document-buffer="buf"
  :show-toolbar="false"
  :show-zoom-control="false"
  :initial-zoom="1.25"
/>

Fonts

:font-families controls what the toolbar dropdown offers. :fonts (added in 1.1.0) registers the actual font faces so the editor can render and measure them. A FontDefinition is { family, src, weight? }, where src is a URL to a woff2/woff/ttf/otf file you host. Share family across entries to register multiple weights.

<script setup>
import { DocxEditor } from "@eigenpal/docx-editor-vue";
 
const fonts = [
  { family: "Custom Sans", src: "/fonts/CustomSans-Regular.woff2" },
  { family: "Custom Sans", src: "/fonts/CustomSans-Bold.woff2", weight: 700 },
];
</script>
 
<template>
  <DocxEditor
    :document-buffer="buf"
    :fonts="fonts"
    :font-families="['Custom Sans', 'Arial']"
  />
</template>

Keep the array reference stable (declared once in setup, not rebuilt inline) so faces aren't re-registered on every render. Font-load failures surface through the @error event; with no listener attached they fall back to console.warn.

Title bar slots

Vue uses named slots in place of React's render-prop callbacks:

<DocxEditor :document-buffer="buf" document-name="Q3 Memo">
  <template #titleBarRight>
    <SaveIndicator :dirty="dirty" />
  </template>
</DocxEditor>

The slot names map directly to the React callback names: renderLogo#logo, renderTitleBarRight#titleBarRight.

Callbacks become events

React propVue event
onChange@change
onSave@save
onSelectionChange@selection-change
onError@error
onFontsLoaded@fonts-loaded
onCommentAdd@comment-add
onCommentResolve@comment-resolve
onCommentDelete@comment-delete
onCommentReply@comment-reply
onPrint / onCopy / onCut / onPaste@print / @copy / @cut / @paste
onModeChange@mode-change
onDocumentNameChange@document-name-change
<DocxEditor
  :document-buffer="buf"
  @change="onChange"
  @save="onSave"
  @error="reportError"
/>

Styling

<DocxEditor
  :document-buffer="buf"
  class="rounded-lg shadow-md"
  :style="{ height: '80vh' }"
>
  <template #placeholder>
    <EmptyState />
  </template>
</DocxEditor>

i18n

<script setup>
import pl from "@eigenpal/docx-editor-i18n/pl";
import { DocxEditor } from "@eigenpal/docx-editor-vue";
</script>
 
<template>
  <DocxEditor :document-buffer="buf" :i18n="pl" />
</template>

Agents

<DocxEditor
  ref="editor"
  :document-buffer="buf"
  :agent-panel="{ render: () => h(AgentChatLog, { messages }) }"
/>

Or use the #agentPanel named slot if you prefer template syntax:

<DocxEditor :document-buffer="buf">
  <template #agentPanel>
    <AgentChatLog :messages="messages" />
  </template>
</DocxEditor>

Full agent wiring in Agents → Live editor.

See also