Skip to content

Examples

Discover the power of VuePDFIY through practical examples. From simple text to complex dynamic tables, these snippets show you how to build professional PDFs directly in your Vue 3 applications.

Note

The demos below use vue-pdf to render the generated PDF buffer directly in your browser. This allows for a smooth, seamless transition from generation to preview.

Simple Table

The SimpleTable example demonstrates the core functionality of the TableBuilder API. It shows how to define headers and rows programmatically with a fluent interface.

View Source Code
vue
<template>
  <div class="flex gap-4">
    <button class="button-style mb-4" @click="downloadPdf">
      <span> Download </span>
    </button>

    <button class="button-style mb-4" @click="renderPdf">
      <span> Render PDF </span>
    </button>
  </div>
  <div v-if="pdfUrl" class="pdf-style">
    <VuePDF :pdf="pdf" v-if="pdfUrl" :page="page" />
  </div>
</template>
ts
<script lang="ts" setup>
import { useJsPdf } from 'vue-pdfiy'
import { ref } from 'vue'
import { VuePDF, usePDF, type PDFSrc } from '@tato30/vue-pdf'

const pdfUrl = ref<PDFSrc | ArrayBuffer | null>(null)
const page = ref(1)
const { pdf } = usePDF(pdfUrl as PDFSrc)
const { addText, outputAsArrayBuffer, setFontSize, textColor, savePdf, createTableBuilder } =
  useJsPdf({})

const HEADER_HEIGHT = 30

const preparePdf = () => {
  setFontSize(60)
  textColor('#000000')
  addText('Simple Table', { x: 0, y: HEADER_HEIGHT, isCentered: true })
  createTableBuilder()
    .setStartY(HEADER_HEIGHT + 20)
    .addHeader(['Header 1', 'Header 2', 'Header 3'])
    .addRow(['Cell 1', 'Cell 2', 'Cell 3'])
    .addRow(['Cell 4', 'Cell 5', 'Cell 6'])
    .build()
}

const renderPdf = () => {
  preparePdf()
  const arrayBuffer = outputAsArrayBuffer()
  pdfUrl.value = arrayBuffer
}

const downloadPdf = () => {
  preparePdf()
  savePdf('simple-table.pdf')
}
</script>

Interactive Demo

Multi-Page Multi-Table

The MultiTablesWithHeaderFooter example demonstrates the core functionality of the TableBuilder API. It shows how to define headers and rows programmatically with a fluent interface.

View Source Code
vue
<template>
  <div class="flex gap-4">
    <button class="button-style mb-4" @click="downloadPdf">
      <span> Download </span>
    </button>

    <button class="button-style mb-4" @click="renderPdf">
      <span> Render PDF </span>
    </button>
  </div>
  <div v-if="pdfUrl" class="pdf-style">
    <VuePDF :pdf="pdf" v-if="pdfUrl" :page="page" />
  </div>
</template>
ts
<script lang="ts" setup>
import { useJsPdf } from 'vue-pdfiy'
import { ref } from 'vue'
import { VuePDF, usePDF, type PDFSrc } from '@tato30/vue-pdf'

const pdfUrl = ref<PDFSrc | ArrayBuffer | null>(null)
const page = ref(1)
const { pdf } = usePDF(pdfUrl as PDFSrc)
const { addText, outputAsArrayBuffer, setFontSize, textColor, savePdf, createTableBuilder } =
  useJsPdf({})

const HEADER_HEIGHT = 30

const preparePdf = () => {
  setFontSize(60)
  textColor('#000000')
  addText('Simple Table', { x: 0, y: HEADER_HEIGHT, isCentered: true })
  createTableBuilder()
    .setStartY(HEADER_HEIGHT + 20)
    .addHeader(['Header 1', 'Header 2', 'Header 3'])
    .addRow(['Cell 1', 'Cell 2', 'Cell 3'])
    .addRow(['Cell 4', 'Cell 5', 'Cell 6'])
    .build()
}

const renderPdf = () => {
  preparePdf()
  const arrayBuffer = outputAsArrayBuffer()
  pdfUrl.value = arrayBuffer
}

const downloadPdf = () => {
  preparePdf()
  savePdf('simple-table.pdf')
}
</script>

Interactive Demo

Table From Objects

The TableFromObjects example demonstrates the core functionality of the TableBuilder API. It shows how to define headers and rows programmatically with a fluent interface.

View Source Code
vue
<template>
  <div class="flex gap-4">
    <button class="button-style mb-4" @click="downloadPdf">
      <span> Download </span>
    </button>

    <button class="button-style mb-4" @click="renderPdf">
      <span> Render PDF </span>
    </button>
  </div>
  <div v-if="pdfUrl" class="pdf-style">
    <VuePDF :pdf="pdf" v-if="pdfUrl" :page="page" />
  </div>
</template>
ts
<script lang="ts" setup>
import { fromObjects, useJsPdf } from '@/composables'
import type { CellDefAutoTable } from '@/types/table'
import { usePDF, VuePDF, type PDFSrc } from '@tato30/vue-pdf'
import { ref } from 'vue'
const { createTableBuilder, savePdf, outputAsArrayBuffer } = useJsPdf({
  orientation: 'p',
  unit: 'mm',
  format: 'a4',
})

const pdfUrl = ref<PDFSrc | ArrayBuffer | null>(null)
const page = ref(1)
const { pdf } = usePDF(pdfUrl as PDFSrc)

const preparePdf = () => {
  // Data as array of objects
  const employees = [
    { name: 'John Doe', department: 'Engineering', salary: 75000 },
    { name: 'Jane Smith', department: 'Marketing', salary: 65000 },
    { name: 'Bob Johnson', department: 'Sales', salary: 70000 },
  ]

  // Convert objects to table data
  const { header, body } = fromObjects(employees)

  createTableBuilder()
    .setHeader(header as CellDefAutoTable[][])
    .addRows(body as CellDefAutoTable[][])
    .setTheme('grid')
    .setHeaderStyles({ fillColor: '#673AB7', textColor: '#fff' })
    .build()
}

const renderPdf = () => {
  preparePdf()
  const arrayBuffer = outputAsArrayBuffer()
  pdfUrl.value = arrayBuffer
}

const downloadPdf = () => {
  preparePdf()
  savePdf('simple-table.pdf')
}
</script>

Invoice Table

The InvoiceTable example demonstrates the core functionality of the TableBuilder API. It shows how to create an invoice table with header, rows, and totals.

View Source Code
vue
<template>
  <div class="flex gap-4">
    <button class="button-style mb-4" @click="downloadPdf">
      <span> Download </span>
    </button>

    <button class="button-style mb-4" @click="renderPdf">
      <span> Render PDF </span>
    </button>
  </div>
  <div v-if="pdfUrl" class="pdf-style">
    <VuePDF :pdf="pdf" v-if="pdfUrl" :page="page" />
  </div>
</template>
vue
<script lang="ts" setup>
import { formatCurrency, fromObjects, useJsPdf } from '@/composables'
import type { CellDefAutoTable } from '@/types/table'
import { usePDF, VuePDF, type PDFSrc } from '@tato30/vue-pdf'
import { nextTick, ref } from 'vue'
const { createTableBuilder, savePdf, outputAsArrayBuffer, setFontSize, textColor, addText } =
  useJsPdf({
    orientation: 'p',
    unit: 'mm',
    format: 'a4',
  })

const pdfUrl = ref<PDFSrc | ArrayBuffer | null>(null)
const page = ref(1)
const { pdf } = usePDF(pdfUrl as PDFSrc)

const preparePdf = () => {
  // Invoice header
  setFontSize(24)
  addText('INVOICE', { x: 105, y: 20 })
  setFontSize(10)
  addText('Invoice #: INV-2024-001', { x: 20, y: 35 })
  addText('Date: January 28, 2024', { x: 20, y: 40 })

  // Invoice items
  const items = [
    ['Web Development', 40, 150, 6000],
    ['UI/UX Design', 20, 120, 2400],
    ['Consulting', 10, 200, 2000],
  ]

  const subtotal = items.reduce((sum, item) => sum + (item[3] as number), 0)
  const tax = subtotal * 0.1
  const total = subtotal + tax

  // Create total rows
  const bodyRows = items.map((item) => [
    item[0] as string,
    item[1] as number,
    formatCurrency(item[2] as number),
    formatCurrency(item[3] as number),
  ])

  createTableBuilder()
    .addHeader(['Description', 'Hours', 'Rate', 'Amount'])
    .addRows(bodyRows as CellDefAutoTable[][])
    .addRow(['', '', 'Subtotal:', formatCurrency(subtotal)])
    .addRow(['', '', 'Tax (10%):', formatCurrency(tax)])
    .addRow(['', '', 'Total:', formatCurrency(total)])
    .setStartY(50)
    .setTheme('grid')
    .setHeaderStyles({
      fillColor: '#1a237e',
      textColor: '#fff',
      fontSize: 11,
      fontStyle: 'bold',
    })
    .setColumnStyles(3, { halign: 'right', fontStyle: 'bold' })
    .setMargin({ top: 50, right: 20, bottom: 20, left: 20 })
    .build()
}

const renderPdf = () => {
  preparePdf()
  nextTick(() => {
    const arrayBuffer = outputAsArrayBuffer()
    pdfUrl.value = arrayBuffer
  })
}

const downloadPdf = () => {
  preparePdf()
  savePdf('invoice-table.pdf')
}
</script>

Reusable Table Builder

The ReusableTableBuilder example demonstrates how to create a reusable table builder that can be used to create multiple tables with the same styles and settings.

View Source Code
vue
<template>
  <div class="flex gap-4">
    <button class="button-style mb-4" @click="downloadPdf">
      <span> Download </span>
    </button>

    <button class="button-style mb-4" @click="renderPdf">
      <span> Render PDF </span>
    </button>
  </div>
  <div v-if="pdfUrl" class="pdf-style">
    <VuePDF :pdf="pdf" v-if="pdfUrl" :page="page" />
  </div>
</template>
vue
<script lang="ts" setup>
import { useJsPdf } from '@/composables'
import { usePDF, VuePDF, type PDFSrc } from '@tato30/vue-pdf'
import { nextTick, ref } from 'vue'
const { createTableBuilder, savePdf, outputAsArrayBuffer } = useJsPdf({
  orientation: 'p',
  unit: 'mm',
  format: 'a4',
})

const pdfUrl = ref<PDFSrc | ArrayBuffer | null>(null)
const page = ref(1)
const { pdf } = usePDF(pdfUrl as PDFSrc)

const preparePdf = () => {
  // Create a styled builder
  const styledBuilder = createTableBuilder({
    defaultTheme: 'striped',
    defaultMargin: 20,
  }).setHeaderStyles({
    fillColor: '#3F51B5',
    textColor: '#fff',
    fontStyle: 'bold',
  })

  // Clone and use for first table
  const table1 = styledBuilder
    .clone()
    .addHeader(['Column 1', 'Column 2', 'Column 3'])
    .addRows([
      ['Data A1', 'Data B1', 'Data C1'],
      ['Data A2', 'Data B2', 'Data C2'],
    ])

  table1.build()

  // Clone and use for second table
  const table2 = styledBuilder
    .clone()
    .addHeader(['Name', 'Value', 'Status'])
    .addRows([
      ['Item 1', '100', 'Active'],
      ['Item 2', '200', 'Pending'],
    ])
    .setStartY(table1.build() as unknown as number) // Start after first table

  table2.build()
}

const renderPdf = () => {
  preparePdf()
  nextTick(() => {
    const arrayBuffer = outputAsArrayBuffer()
    pdfUrl.value = arrayBuffer
  })
}

const downloadPdf = () => {
  preparePdf()
  savePdf('reusable-table-builder.pdf')
}
</script>

Dynamic Table

The DynamicTable example demonstrates how to create a dynamic table with a loop.

View Source Code
vue
<template>
  <div class="flex gap-4">
    <button class="button-style mb-4" @click="downloadPdf">
      <span> Download </span>
    </button>

    <button class="button-style mb-4" @click="renderPdf">
      <span> Render PDF </span>
    </button>
  </div>
  <div v-if="pdfUrl" class="pdf-style">
    <VuePDF :pdf="pdf" v-if="pdfUrl" :page="page" />
  </div>
</template>
vue
<script lang="ts" setup>
import { formatCurrency, useJsPdf } from '@/composables'
import { usePDF, VuePDF, type PDFSrc } from '@tato30/vue-pdf'
import { nextTick, ref } from 'vue'
const { createTableBuilder, savePdf, outputAsArrayBuffer, setFontSize, textColor, addText } =
  useJsPdf({
    orientation: 'p',
    unit: 'mm',
    format: 'a4',
  })

const pdfUrl = ref<PDFSrc | ArrayBuffer | null>(null)
const page = ref(1)
const { pdf } = usePDF(pdfUrl as PDFSrc)

const preparePdf = () => {
  setFontSize(60)
  textColor('#000000')
  addText('Dynamic Table', { x: 0, y: HEADER_HEIGHT, isCentered: true })
  // Sample data - could come from API or database
  const products = [
    { name: 'Product A', price: 100, quantity: 5 },
    { name: 'Product B', price: 200, quantity: 3 },
    { name: 'Product C', price: 150, quantity: 7 },
  ]

  const builder = createTableBuilder().addHeader(['Product', 'Price', 'Quantity', 'Total'])

  // Add rows dynamically
  for (const product of products) {
    const total = product.price * product.quantity
    builder.addRow([
      product.name,
      formatCurrency(product.price),
      product.quantity.toString(),
      formatCurrency(total),
    ])
  }

  builder.addFooter(['Total', '', '', formatCurrency(grandTotal)]).build()
}
const renderPdf = () => {
  preparePdf()
  nextTick(() => {
    const arrayBuffer = outputAsArrayBuffer()
    pdfUrl.value = arrayBuffer
  })
}

const downloadPdf = () => {
  preparePdf()
  savePdf('dynamic-table.pdf')
}
</script>