Guide

Form

Container block that wraps form inputs into a submittable form. Manages form state, field registration, submission, captcha handoff, errors, localStorage persistence, and conditional field display. Central orchestrator for form-input-* child blocks (those inputs ship in @prc/block-library).

For Forms CPT, Synced Form embeds, response logging, and security, see the user guide and architecture.

Namespace

prc-block/form

Category

common

Block inserter example

block.json defines an example with name and email form-input-text fields, form-submit, and form-message with a thank-you paragraph.

Supports

FeatureValue
Anchortrue
Interactivitytrue
Color (text, background, link, heading, button)true
Layoutconstrained (default contentSize 420px)
Spacing (margin, padding, blockGap)true
Typography (fontSize, lineHeight, family, weight, …)true
HTMLvia __experimentalSelector: form
Class namefalse

Attributes

AttributeTypeDefaultDescription
formNamestringHuman-readable name; used for localStorage keys and logging.
methodstring"api""api" or "rest".
namespacestringREST namespace when method is "rest".
actionstringRegistered form action identifier.
actionConfigobject{}Per-action config (e.g. forwardTo, Mailchimp segment).
redirectUrlstringDeprecated. Prefer per-action actionConfig when the action supports redirect.
displayMessageEditingbooleanfalseLocal editor-only flag (role: local).

Block variations

VariationDescription
Newsletter Signup (Mailchimp)subscribe API action with email, submit, captcha, thank-you message.
Newsletter Selection (Mailchimp)Multi-segment signup via subscribeSelect and mailchimp-select credentials.

Inner blocks

allowedBlocks in block.json includes layout/core blocks, form-input-* inputs from block-library, plus:

BlockRole
prc-block/form-pageMulti-step page
prc-block/form-submitLocked submit + captcha template
prc-block/form-messageSuccess / result message

Default template includes name, email, message fields, submit, and message area (src/form/constants.js).

Provides context: form/displayMessage (legacy message-display flag for children).

Uses context: prc-block/form/formPostId (from Synced Form / Form_Renderer).

Nesting a form inside another form is prevented in registration logic.

Usage

Create a form in the editor

  1. Insert the Form block (default template loads).
  2. Set Form Name.
  3. Choose Method and Action.
  4. Configure Action Settings when offered.
  5. Adjust fields; place Form Submit and Form Message as needed.

Action templates

Selecting an action registered with a template in prc-block-library/forms opens Use Form Template? (use template / keep existing / start blank). Templates replace inner blocks only; Form attributes stay.

Registering a template from a consumer plugin:

dispatch('prc-block-library/forms').registerForm({
  label: 'My Form',
  namespace: 'my-plugin/namespace',
  action: 'myAction',
  method: 'api',
  template: [
    ['prc-block/form-input-text', { /* … */ }],
    ['prc-block/form-submit', {}],
    ['prc-block/form-message', {}],
  ],
});

Conditional fields and persistence

Inputs can use formDisplayMode / formDisplayCondition. The form processes these during render via handle_conditional_form_field_display.

Field values persist to localStorage (prc-form-{formName}, 24-hour expiry) and restore on mount.

Public form security

Do not treat nonceToken as the primary gate on edge-cached pages. Use Turnstile (form-captcha inside Form Submit), rate limiting, and server-side recipient resolution. Details: architecture.

Block markup example

<!-- wp:prc-block/form {"formName":"contact-form","method":"api","action":"contact"} -->
<form class="wp-block-prc-block-form">
	<!-- wp:prc-block/form-input-text {"type":"text","metadata":{"name":"fullName"}} -->
	<!-- /wp:prc-block/form-input-text -->

	<!-- wp:prc-block/form-input-text {"type":"email","metadata":{"name":"emailAddress"}} -->
	<!-- /wp:prc-block/form-input-text -->

	<!-- wp:prc-block/form-submit /-->

	<!-- wp:prc-block/form-message /-->
</form>
<!-- /wp:prc-block/form -->

PHP rendering

Server-side via render_form_callback in src/form/class-form.php.

  1. Registers interactivity context (formId, action fields, captcha/submission flags, formFields, formPages, empty nonceToken for public forms).
  2. Applies conditional field directives.
  3. Injects error and processing overlays.
  4. Registers initial state with wp_interactivity_state( 'prc-block/form', … ).

Frontend interactivity

Store namespace: prc-block/form (src/form/view/index.js)

State

KeyTypeDescription
formFieldsobjectField name → value map from child blocks
isSubmittingbooleanSubmission in progress
isSubmittedbooleanSuccessful submit
isProcessingbooleanAsync processing
hasErrorsbooleanValidation errors present
errorsarrayError message strings
captchaHiddenbooleanCaptcha visibility
captchaTokenstring | nullTurnstile token
captchaPassedbooleanCaptcha verified

Actions and callbacks

NameRole
onSubmitValidate, reveal captcha if needed, then submit
onResetReset fields and state
onInputChange / onInputRangeChange / onInputCheckboxClickField updates
onFormMountRestore localStorage
sendSubmissionAPI/REST submit; success message or redirect
onCaptchaPassingContinues submit when captcha passes
BlockRelationship
prc-block/synced-formEmbeds a Forms CPT post
prc-block/form-pageMulti-step page
prc-block/form-submitSubmit + captcha
prc-block/form-messageResult message
prc-block/form-captchaTurnstile (usually inside Form Submit)
prc-block/form-input-*Field blocks in @prc/block-library

Was this helpful?