Guide

Form Fields

Work with interactive PDF form fields

KViewer auto-detects and renders interactive form fields from PDFs. Users can fill in text inputs, check boxes, select radio buttons, choose from dropdowns, and place signatures.

Supported Field Types

TypeDescription
TextSingle or multi-line text input
CheckboxToggle on/off
RadioMutually exclusive options within a group
DropdownSelect from a list of options
SignatureSignature capture field
ButtonClickable button with label

Read Form Field Values

Use the template ref to read all form field values:

<template>
  <div class="h-screen">
    <KViewer ref="viewer" :source="'/Form.pdf'" />
    <button @click="readValues">Read Form</button>
  </div>
</template>

<script setup lang="ts">
const viewer = ref()

function readValues() {
  const fields = viewer.value?.getFormFieldValues()
  // Returns FormFieldValue[] with fieldId, fieldName, fieldType, and value
  console.log(fields)
}
</script>

Each FormFieldValue contains:

interface FormFieldValue {
  fieldId: string
  fieldName: string
  fieldType: 'text' | 'checkbox' | 'radio' | 'dropdown' | 'signature' | 'button'
  value: string | boolean | string[]
}

Set Form Field Values Programmatically

Pre-fill form fields using setFormFieldValue:

const viewer = ref()

// Fill a text field
viewer.value?.setFormFieldValue('email', 'user@example.com')

// Check a checkbox
viewer.value?.setFormFieldValue('agree_terms', true)

// Select a radio option
viewer.value?.setFormFieldValue('payment_method', 'credit_card')

// Select a dropdown option
viewer.value?.setFormFieldValue('country', 'DE')

Signature Fields and Click to Sign

By default, signature fields are passive markers: they render with a signature icon and a localized "Signature" label ("Unterschrift" for locale: 'de'), and clicking them does nothing. This keeps kviewer neutral when the host application owns the signing process — e.g. an embedding e-sign product with its own signing canvas. A field's promptText (e.g. "Sign here") only applies to the click-to-sign placeholder, since it is a call to action.

Opt in to kviewer's built-in signing flow with the clickToSign prop:

<KViewer :source="pdfUrl" click-to-sign />

With clickToSign enabled, clicking an unsigned field applies the first saved signature (see Signatures & Stamps) or opens the draw modal. It can also be toggled at runtime via setClickToSign(enabled) on the template ref or the embed bridge.

Either way, a signature value set programmatically (setFormFieldValue(name, dataUrl)) always renders in the field.

Breaking: click-to-sign used to be always on. Hosts that relied on it must now pass :click-to-sign="true".

Tracking the signed status

To gate an action (e.g. finalizing an e-sign envelope) on all signature fields being signed, use getSignedStatus() / getSignatureFieldStatus() on the template ref or the embed bridge, or listen to the push-style signed-status-changed event:

<template>
  <KViewer
    ref="viewer"
    :source="pdfUrl"
    click-to-sign
    @signed-status-changed="({ allSigned }) => (canFinalize = allSigned)"
  />
  <UButton label="Finalize" :disabled="!canFinalize" />
</template>

<script setup lang="ts">
const viewer = ref()
const canFinalize = ref(false)
</script>

getSignedStatus() is vacuously true for documents without signature fields — check getSignatureFieldStatus().length when at least one signature must exist.

Add Fields Programmatically

Use addFormField to drop a new field onto the document without going through the placement tool. The created field is exported into the PDF on exportPdf() like any user-placed field.

const viewer = ref()

// Single-line text field on page 1
const name = viewer.value?.addFormField({
  pageNumber: 1,
  fieldType: 'text',
  rect: [50, 700, 250, 720],
  fieldName: 'firstName',
  required: true,
})

// Checkbox with a non-default glyph
viewer.value?.addFormField({
  pageNumber: 1,
  fieldType: 'checkbox',
  rect: [50, 670, 65, 685],
  fieldName: 'agree_terms',
  checkboxStyle: 'cross',
})

// Dropdown with options
viewer.value?.addFormField({
  pageNumber: 1,
  fieldType: 'dropdown',
  rect: [50, 630, 250, 650],
  fieldName: 'country',
  options: [
    { displayValue: 'Germany', exportValue: 'DE' },
    { displayValue: 'France', exportValue: 'FR' },
  ],
})

// Radio group: same fieldName groups widgets into one option set
viewer.value?.addFormField({
  pageNumber: 1, fieldType: 'radio',
  rect: [50, 590, 65, 605], fieldName: 'plan', buttonValue: 'monthly',
})
viewer.value?.addFormField({
  pageNumber: 1, fieldType: 'radio',
  rect: [80, 590, 95, 605], fieldName: 'plan', buttonValue: 'yearly',
})

// Signature field that locks the form once signed
viewer.value?.addFormField({
  pageNumber: 1,
  fieldType: 'signature',
  rect: [50, 540, 250, 580],
  fieldName: 'signature',
  promptText: 'Click to sign',
  lockAction: 'all',
})
The rect is in PDF user-space coordinates (points) with a bottom-left origin: [x1, y1, x2, y2]. Most PDFs are 612 × 792 points (US Letter) or 595 × 842 points (A4).

fieldName is auto-generated when omitted (Text_1, Text_2, …). Multiple widgets that share a fieldName and fieldType act as one PDF field — values mirror across them on edit, and radios with the same fieldName form one option group.

See AddFormFieldPayload for every supported property.

Update or Remove a Field

addFormField returns the created FormFieldDefinition. Use its id to patch or remove the field later:

const def = viewer.value?.addFormField({ /* ... */ })

viewer.value?.updateFormField(def.id, { rect: [60, 700, 260, 720] })
viewer.value?.updateFormField(def.id, { readOnly: true })

viewer.value?.removeFormField(def.id)

List All Fields

getFormFields returns a flat list of every field definition — those parsed from the source PDF, those auto-detected via shape detection, and those placed (programmatically or via the UI):

const defs: FormFieldDefinition[] = viewer.value?.getFormFields()

Enable Shape Detection

Some PDFs use drawn shapes (rectangles, circles) to represent checkboxes instead of proper form fields. Enable shape detection to auto-detect these and convert them to interactive checkboxes:

<KViewer
  :source="pdfUrl"
  shape-detection
/>

Shape detection scans page content for rectangular and circular shapes that match common checkbox dimensions and creates synthetic form fields for them.

Shape detection works best on scanned forms with clearly drawn checkbox outlines. Enable it on a per-document basis using the shapeDetection prop.

Export with Form Data

Form field values are automatically included when exporting the PDF:

const bytes = await viewer.value?.exportPdf({ flatten: true })
// The exported PDF includes all filled form field values
Copyright © 2026