A PDF form is only as good as the data it produces. Without validation, users will leave required fields blank, type "N/A" where you expected a number, enter dates in any of seven formats, and produce data that downstream tools have to clean up by hand. With validation, the form catches errors at fill time, when the user can fix them. This guide walks through the practical mechanics of validating PDF form fields.
Three levels of validation
Validation in PDF forms operates at three escalating levels:
- Format validation, built into the field. Numbers must look like numbers, dates must look like dates, etc.
- Range validation, the field's value must fall within bounds.
- Custom validation (JavaScript), arbitrary logic. Phone number patterns, ZIP code formats, conditional requirements.
Plus the foundational checkbox:
- Required fields, the field must have any value at all before submit.
Use each at the right level. Format and required are cheap to set; range is straightforward; JavaScript is for everything else.
Setting required fields
In Acrobat Pro:
- Open the field's properties
- General tab → check Required
- Save the form
A required field is visually flagged in most readers (typically a red border or asterisk). The Submit button can refuse submission if required fields are empty, provided the reader honors the spec, which most do.
For belt-and-suspenders, add a JavaScript validation script on the Submit button that explicitly checks required fields.
Format validation
Each text field can be formatted as:
- None, free text
- Number, integer or decimal, with optional currency symbol
- Percentage
- Date, with a format mask (mm/dd/yyyy, dd-mm-yy, etc.)
- Time
- Special, ZIP code, phone number, social security number (US-specific format masks)
- Arbitrary mask, pattern of letters and numbers using #/A/X codes
- Custom, JavaScript-driven format
In Acrobat Pro: Properties → Format tab → choose category.
A field formatted as Number with 2 decimals automatically rejects non-numeric input. A field formatted as Phone with the US mask accepts only the pattern (###) ###-####.
For numeric format, see PDF form field types explained for how this links with calculations.
Range validation
For numeric fields:
- Properties → Validate tab
- Field value is in range: from X to Y
- The form rejects out-of-range values
Common ranges:
- Quantity: 1 to 1000
- Age: 0 to 120
- Year: 1900 to 2100
- Percentage: 0 to 100
The reader shows a validation error if the user enters a value outside the range.
Custom JavaScript validation
For anything beyond format and range, JavaScript:
- Properties → Validate tab
- Run custom validation script
- Type your JavaScript
Examples:
Validate an email field:
var pattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (event.value && !pattern.test(event.value)) {
app.alert("Please enter a valid email address.");
event.rc = false;
}
Validate that a date is in the future:
var input = util.scand("mm/dd/yyyy", event.value);
var today = new Date();
if (input < today) {
app.alert("Date must be in the future.");
event.rc = false;
}
Validate a US ZIP code:
var pattern = /^\d{5}(-\d{4})?$/;
if (!pattern.test(event.value)) {
app.alert("Please enter a valid ZIP code (12345 or 12345-6789).");
event.rc = false;
}
Set event.rc = false to reject the input. The user must correct it before moving to the next field.
Conditional required fields
A field that becomes required based on another field's value:
// On the dependent field's Validate event:
var primary = this.getField("primary_option").value;
if (primary === "Yes" && !event.value) {
app.alert("Please complete this required field.");
event.rc = false;
}
This rejects empty values if the primary option is "Yes".
Cross-field validation
Validate that two fields agree:
// On confirm_password's Validate event:
var pwd = this.getField("password").value;
if (event.value !== pwd) {
app.alert("Passwords do not match.");
event.rc = false;
}
Or validate that an end date is after a start date:
var start = util.scand("mm/dd/yyyy", this.getField("start_date").value);
var end = util.scand("mm/dd/yyyy", event.value);
if (start && end <= start) {
app.alert("End date must be after start date.");
event.rc = false;
}
Submit-time validation
Field-level validation runs when the user leaves a field. Submit-level validation runs when the user clicks Submit. They are complementary.
On the Submit button:
- Properties → Actions tab
- Mouse Up → Run JavaScript
- Validate the entire form
Example:
var fields = ["customer_name", "email", "phone"];
var errors = [];
for (var i = 0; i < fields.length; i++) {
if (!this.getField(fields[i]).value) {
errors.push(fields[i].replace("_", " "));
}
}
if (errors.length > 0) {
app.alert("Please complete: " + errors.join(", "));
} else {
// proceed to submit
this.submitForm({cURL: "https://example.com/submit"});
}
This is the final gate. Even if field-level validation passes, submit-time validation catches anything missed.
Visual feedback
Validation that pops up a modal alert is functional but jarring. Better:
- Color the field red on error, green on success. Set the field's border or background color in the validation script.
- Show a help message in a separate text field that updates with the error.
- Highlight all required fields with a visible mark (asterisk or color) so users know what to fill.
Acrobat Pro lets you set field colors dynamically:
event.target.borderColor = color.red;
event.target.fillColor = color.ltGray;
Use this in custom validation to provide visual cues.
Accessibility
Validation alerts must be accessible to screen-reader users. Practical patterns:
- Set the field's tooltip to describe the validation requirement ("Enter a valid email address in the format name@example.com")
- Use
ariaattributes through tagged PDF accessibility, see PDF/UA accessibility standard explained - Provide a text-based error message field in addition to (or instead of) modal alerts, so screen readers can pick up the error
For more accessibility concerns, see PDF accessibility guide.
Common gotchas
Validation runs only when field loses focus. A user who never leaves the field never triggers validation. Submit-time validation catches this.
JavaScript disabled. Some readers disable JavaScript for security. Format-level validation (Number, Date) usually still works; custom JavaScript validation does not.
Browser readers ignore validation. Chrome's built-in PDF viewer, Firefox's pdf.js, and others have limited form-validation support. For browser-based form filling, validation may not fire. Plan for server-side re-validation.
Validation messages are jarring. Modal alerts interrupt flow. Use inline visual feedback when possible.
Validation script errors silently. A typo in JavaScript causes the script to throw an error but the form proceeds. Test with realistic input.
Date format inconsistency. A date field validated as mm/dd/yyyy will reject dd/mm/yyyy even if it represents a valid date. Use a date picker if possible; otherwise validate format explicitly with util.scand.
Locale-dependent validation. A US-formatted phone validator rejects international phone formats. Plan for multinational forms.
Required not enforced on submit. As above, some readers honor the required attribute; some do not. Submit-time JavaScript validation provides a uniform safety net.
Performance considerations
Validation that fires on every keystroke (using the Keystroke event instead of Validate) can feel sluggish on slow devices. Use Validate (which fires only on field exit) for most checks.
Validation in calculation-driven forms
If a field is calculated (not user-entered), validation typically runs on the calculation result:
- The user enters quantity and price
- The form calculates line total
- Validation on line total checks that it does not exceed a maximum
This catches downstream issues (e.g., a customer ordering 1000 units of a $1,000 item) that might be missed by per-field validation.
Practical recipes
Email field validation:
if (event.value && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(event.value)) {
app.alert("Please enter a valid email.");
event.rc = false;
}
Phone field with mask:
Properties → Format → Special → Phone Number. The mask handles validation; no script needed.
Number range 1-100:
Properties → Format → Number. Properties → Validate → "Field value is in range: 1 to 100".
Submit button with full validation:
var required = ["name", "email", "phone"];
var missing = required.filter(function(f) {
return !this.getField(f).value;
}.bind(this));
if (missing.length > 0) {
app.alert("Required: " + missing.join(", "));
} else {
this.submitForm({cURL: "https://example.com/submit"});
}
Takeaway
Validation in PDF forms catches data errors at fill time, before they propagate downstream. Use format validation for numeric and date fields; range validation for bounded values; JavaScript for arbitrary patterns and conditional rules. Always pair field-level validation with submit-time validation as a safety net. Account for readers with limited JavaScript support, most of your audience uses Acrobat, but some use browser-built-in viewers where validation is partial. For browser-based form creation, Docento.app supports field validation as part of the broader form workflow. For the related topics of calculations and field types, see how to add calculations to a PDF form and PDF form field types explained.