Vue examples

Concrete patterns for the current Vue root surface: mount bytes, save through the ref, compose custom chrome, and automate an open editor.

Import @docx-editor.dev/vue/styles.css once in your application entry before you use these examples.

Load DOCX bytes

<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { DocxEditor } from '@docx-editor.dev/vue';

const doc = ref<Uint8Array>();

onMounted(() => {
  void fetch('/template.docx')
    .then((response) => response.arrayBuffer())
    .then((buffer) => {
      doc.value = new Uint8Array(buffer);
    });
});
</script>

<template>
  <DocxEditor :document="doc" title="Proposal.docx" />
</template>

Save through the ref

<script setup lang="ts">
import { ref } from 'vue';
import { DocxEditor, type DocxEditorRef } from '@docx-editor.dev/vue';

const editorRef = ref<DocxEditorRef | null>(null);

async function save() {
  const next = await editorRef.value?.save();
  if (!next) return;
  await fetch('/api/documents/42', { method: 'PUT', body: next });
}
</script>

<template>
  <button @click="save">Save</button>
  <DocxEditor ref="editorRef" :document="bytes" />
</template>

Compose custom chrome

Create a button that reads the editor context:

<script setup lang="ts">
import { useEditorCommand } from '@docx-editor.dev/vue';

const bold = useEditorCommand('text.bold');
</script>

<template>
  <button
    @mousedown.prevent
    :disabled="!bold.isEnabled.value"
    :aria-pressed="bold.isActive.value"
    :title="bold.disabledReason.value ?? 'Bold'"
    @click="bold.execute()"
  >
    Bold
  </button>
</template>

Then place the button and editor parts under the root:

<script setup lang="ts">
import { DocxEditor } from '@docx-editor.dev/vue';
import BoldButton from './BoldButton.vue';
</script>

<template>
  <DocxEditor.Root :document="bytes">
    <DocxEditor.Toolbar>
      <BoldButton />
    </DocxEditor.Toolbar>
    <DocxEditor.Viewport>
      <DocxEditor.Navigation />
      <DocxEditor.Content />
      <DocxEditor.HyperLink />
      <DocxEditor.ContextMenu />
    </DocxEditor.Viewport>
  </DocxEditor.Root>
</template>

DocxEditor.Navigation shares the viewport with the document. DocxEditor.HyperLink and DocxEditor.ContextMenu provide overlay chrome.

Automate an open editor

Render this component anywhere below DocxEditor.Root:

<script setup lang="ts">
import { useDocxEditor } from '@docx-editor.dev/vue';
import { DocxEditor as AutomationEditor } from '@docx-editor.dev/editor-api/browser';

const editor = useDocxEditor();

async function inspectFirstParagraph() {
  if (!editor.value) return;
  const runtime = AutomationEditor.createBrowser(editor.value);

  try {
    await runtime.run(async (context) => {
      const first = context.document.body.paragraphs.getFirst();
      first.load('text');
      await context.sync();
      console.log(first.text);
    });
  } finally {
    runtime.dispose();
  }
}
</script>

<template>
  <button :disabled="!editor" @click="inspectFirstParagraph">Inspect first paragraph</button>
</template>

Install @docx-editor.dev/editor-api before you use this example. The runtime uses the editor that DocxEditor.Root created.

Fetch bytes and fonts together

<script setup lang="ts">
import {
  DocxEditorRoot,
  DocxEditorViewport,
  DocxEditorContent,
  useDocxSource,
} from '@docx-editor.dev/vue';
import { defaultFonts } from '@docx-editor.dev/fonts';

const { document, fonts, error, isLoading } = useDocxSource('/sample.docx', {
  fonts: defaultFonts,
});
</script>

<template>
  <DocxEditorRoot v-if="document" :document="document" :fonts="fonts">
    <DocxEditorViewport>
      <DocxEditorContent />
    </DocxEditorViewport>
  </DocxEditorRoot>
  <p v-else-if="error">{{ error.message }}</p>
  <p v-else-if="isLoading" aria-live="polite">Loading document</p>
</template>

Live demo

The examples/vue application shows composition chrome, menu overrides, rulers, navigation, and package build mode. Run it with bun run dev:vue.

The adapter parity demo serves React and Vue builds from examples/parity/dist.

Next steps

On this page