Go Back to Parent Doc

Validation

Forming Forms checks every submission twice. The browser checks it first, so visitors fix mistakes before sending. The server checks it again, without trusting anything the browser sent about the shape of the form.

In the browser

When a visitor clicks Submit, the form checks every field against the rules you set (required, lengths, patterns, formats, number limits and dates) before anything is sent.

  • Each problem appears under its field, and the form shows Please correct the highlighted fields.
  • Focus moves to the first field with a problem, so keyboard and screen-reader users land right on it.
  • Errors update as the visitor types, and disappear as soon as the answer is valid.
  • The messages are the same ones the server uses, including your custom messages, and they’re translated.

The browser check is a convenience for visitors. It can be bypassed, so the server always decides.

On the server: the schema is rebuilt on every submission

Most form plugins accept the field list that arrives with the request. Forming Forms doesn’t. When a submission comes in, the server:

  1. Reads the form ID and a signed reference to where the form lives (a post, synced pattern, template or template part).
  2. Loads that content and runs parse_blocks() over it.
  3. Finds the Form block with the matching ID, at any nesting depth.
  4. Rebuilds the exact field schema from the blocks inside it: names, types, required flags, options, lengths, patterns, dates and number limits.
  5. Validates the submitted values against that schema, field by field.

Anything the request contains that the schema doesn’t define is discarded. That means:

  • A tampered form can’t inject extra fields into your entries or emails.
  • A required field can’t be bypassed by removing the attribute in devtools.
  • A choice field can’t be given a value you never offered.
  • Forms in private or draft content can’t be targeted, because the form’s location is signed.

Edit a form (make a field required, say) and the next submission is checked against the new rule, with nothing to re-save or re-sync.

Per-field rules

FieldChecked for
TextOptional minimum and maximum length, and an optional pattern
EmailA valid email address
TextareaOptional minimum and maximum length. Line breaks are kept
PhoneDigits with spaces, dashes, dots, brackets and a leading +, or your own pattern. Optional length limits
URLA valid web address
NumberA number, within Minimum/Maximum, on the Step
DateA real YYYY-MM-DD date, on or after the earliest date and on or before the latest (either can be “today”)
Select, RadioOne of the options defined on the block, or a filled-in “Other” answer
Select (multiple), Checkbox (multiple)Only defined options are kept. If required, at least one must remain
Checkbox (single)If required, it must be checked
HiddenServer values are worked out again and replace whatever the browser sent

Required is enforced on every type. Pro fields have their own rules. See Pro Field Blocks.

Custom error messages

Every data field has a Message when empty setting in Field Settings, used when a required field is left blank. Input fields also have Message when the value is not valid in their Validation panel. Leave it empty to get a message that explains the rule, such as Please enter a number no greater than 10. or Please choose a date on or after 12/01/2026.

Write messages that say how to fix the problem: “Use your 6-digit member number” helps more than “Invalid”.

What visitors see

The form submits in the background, so the page doesn’t reload and nothing typed is lost.

  • Success: the form clears and your message appears, or the browser redirects, depending on the form’s After submit setting.
  • Validation errors: a form-level message plus a message under each failing field, whose wrapper gets the has-error class.
  • Expired session: on cached pages the form fetches a fresh security token and retries automatically. If that fails, visitors see Your session has expired. Please reload the page and try again.
  • Network failure: Network error. Please try again.

The response area is an ARIA live region, so screen readers announce the outcome.

Styling error states

.forming-field.has-error .forming-field__input {
	border-color: #d63638;
	background: #fef7f7;
}
.forming-field__error {
	font-weight: 600;
}

See Styling & Layout for the full class list.

Adding your own rules

For business rules (a date that must be in the future, an email domain you don’t accept, a member number that must exist), use the forming_validate_field filter for a single field, or forming_before_submission for rules across several fields:

add_filter( 'forming_validate_field', function ( $result, $field, $raw ) {
	if ( 'email' === $field['name'] && ! is_wp_error( $result ) && '@example.com' === substr( $result['value'], -12 ) ) {
		return new WP_Error( 'blocked_domain', __( 'Please use your work email address.', 'my-plugin' ) );
	}
	return $result;
}, 10, 3 );

The error message is shown under the field. See the Developer Reference.

Shopping Cart
  • Your cart is empty.