Web SDKv1.0.0

Forms

How the viewer fills form fields: a read-only switch, holding back Download while a required field is empty, the touch stepper, and the field highlight tint. Whether fields are flattened on download is export.flatten (off by default). Filling fields needs a license that includes forms; reading them out (doc.forms.fields, getValues) needs extract.
FormsConfigconfig.forms

Example

viewer.tsTypeScript
new PDFViewer(container, doc, {
  forms: {
    validateRequired: true,
    highlightColor: '#fff3c4', // a warmer field tint
  },
});

Options 4

readOnlybooleanDefaultfalse
Show fields and values, fill nothing. Every field shows its value and takes no input, while the rest of the mode (tools, Download, Print) stays as it is. A signature field opens nothing. doc.forms.setValues() refuses every field with read_only (a signature field with unsupported_type), as it does a field the document marks read-only.
readOnlyTypeScript
forms: { readOnly: true }
validateRequiredbooleanDefaultfalse
Hold back Download while a required field is empty. The toolbar's Download (with or without your onDownload) does nothing while a required text, choice, check box or radio field is empty: a message names up to three empty fields (by their field names), then a count, and focus moves to the first. Read-only and hidden fields are skipped, and a check box or radio group counts as filled once any of its widgets is on. Signature fields are not checked. viewer.createExporter() is not held back; gate it yourself with doc.forms.getValues(), which carries the live input, and the fields.
validateRequiredTypeScript
import type { FormValue } from '@kernstra/pdf-web-sdk';

// One value per field; a check box or radio group reports 'Off' when nothing is on.
const values = await doc.forms.getValues();
const blank = (value: FormValue | undefined): boolean => {
  if (value === undefined || value === 'Off') return true;
  return typeof value === 'string' ? value.trim() === '' : value.length === 0;
};
const empty = new Set(
  (await doc.forms.fields())
    .filter((field) => field.required && !field.readOnly && blank(values[field.name]))
    .map((field) => field.name),
);
stepperbooleanDefaulttrue
On a touch screen, a bar with Previous, Next and Done replaces the Tab key while a field has focus (a centered pill on a tablet). false leaves only the fields. See Layout for how the stepper follows the keyboard.
stepperTypeScript
forms: { stepper: false }
highlightColorstringDefaultnone given (the token's)
Sets --ks-field-bg, the tint drawn over fillable fields; the hover shade is derived from it. A hex, a name or one color function, like theme.accentColor; anything else is ignored with a warning. Leave it out to keep the SDK's own tint, or set --ks-field-bg (and --ks-field-bg-hover, which the option derives for you) in CSS instead.
highlightColorTypeScript
forms: { highlightColor: '#fff3c4' } // a warmer field tint

Notes

Saved appearance. A filled value is saved as the field's appearance, in the font the form names for it. A form that names a font it never embeds and that no reader has (an Acrobat-made form often names HelveticaLTStd-Bold or ArialMT) is saved naming the standard face it stands for instead — Helvetica-Bold, Times-Roman, Courier — so Acrobat and every other reader draw the value in a real face with the right spacing.

Date fields are the ones Acrobat treats as dates: a text field whose format script is AFDate_FormatEx / AFDate_Format. Such a field with a whole date (no time) gets the date picker, and the date is stored in the field's own format (dateFormat on FormFieldInfo); doc.forms.setValues takes it in that format or as YYYY-MM-DD. A field named "Date" without the script is an ordinary text field. A date with a time, or without a day or year, is typed as text and stored in the field's format once entered (3/4/26 2:05 pm → 03/04/2026 14:05).

Formats, ranges and calculations. A field that uses Acrobat's standard form functions behaves as it does in Acrobat: a number, currency or percentage (AFNumber_Format, AFPercent_Format) shows formatted — $1,234.50, 15.0% — and as stored while it is edited; a percentage is typed as one (15 or 15%) and stored as Acrobat stores it, the fraction 0.15 (Acrobat itself would read a typed 15 as 1,500 %), which doc.forms.setValues takes too; a zip code, phone or social security number (AFSpecial_Format) and a masked field take only what fits; a time (AFTime_Format) is stored in its format; a value out of the field's range (AFRange_Validate) is refused with a message, and the field keeps what it held.

Calculated fields. A calculated field (AFSimple_Calculate — sum, product, average, minimum, maximum — Acrobat's simplified field notation, Qty * Price, or a hand-written calculation of the common shape, such as var s = Number(this.getField("subtotal").value); event.value = s * 0.1;) is calculated as the form opens, as Acrobat does, and recalculated whenever a field changes, each after those it reads, reporting formFieldChanged. A hand-written script is read only when it is nothing but variables set from field values, numbers and + - * /, then the result; anything else in it and the field is not calculated. A download saves a formatted field as Acrobat does: its value as entered (1234.5), its appearance formatted (an encrypted file shows the value as entered). FormFieldInfo says what a field does (format, range, calculation) and how its widget draws its box (look): the viewer draws that box under the field's editor, in place of the widget's own appearance, which would show the value twice.

The SDK runs no script. These calls are recognized by their exact form and done by the SDK itself; a field with any other JavaScript (custom code) behaves as a plain field, and doc.forms.setValues takes a value only as typing could have entered it (a percentage as the fraction it is stored as).

XFA forms. A static XFA form (doc.forms.type() resolves to 'xfa-foreground') is filled through the AcroForm it is laid over; when a download changes a value, the XFA is removed so every reader, Acrobat included, shows what was entered, as Acrobat does when it saves a static form it filled. A dynamic XFA form ('xfa') cannot lose its XFA: what is filled here goes into its AcroForm fallback, which other readers show, while Acrobat draws the XFA and its own values.