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
| Feature | Value |
|---|---|
| Anchor | true |
| Interactivity | true |
| Color (text, background, link, heading, button) | true |
| Layout | constrained (default contentSize 420px) |
| Spacing (margin, padding, blockGap) | true |
| Typography (fontSize, lineHeight, family, weight, …) | true |
| HTML | via __experimentalSelector: form |
| Class name | false |
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
formName | string | — | Human-readable name; used for localStorage keys and logging. |
method | string | "api" | "api" or "rest". |
namespace | string | — | REST namespace when method is "rest". |
action | string | — | Registered form action identifier. |
actionConfig | object | {} | Per-action config (e.g. forwardTo, Mailchimp segment). |
redirectUrl | string | — | Deprecated. Prefer per-action actionConfig when the action supports redirect. |
displayMessageEditing | boolean | false | Local editor-only flag (role: local). |
Block variations
| Variation | Description |
|---|---|
| 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:
| Block | Role |
|---|---|
prc-block/form-page | Multi-step page |
prc-block/form-submit | Locked submit + captcha template |
prc-block/form-message | Success / 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
- Insert the Form block (default template loads).
- Set Form Name.
- Choose Method and Action.
- Configure Action Settings when offered.
- 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.
- Registers interactivity context (
formId, action fields, captcha/submission flags,formFields,formPages, emptynonceTokenfor public forms). - Applies conditional field directives.
- Injects error and processing overlays.
- Registers initial state with
wp_interactivity_state( 'prc-block/form', … ).
Frontend interactivity
Store namespace: prc-block/form (src/form/view/index.js)
State
| Key | Type | Description |
|---|---|---|
formFields | object | Field name → value map from child blocks |
isSubmitting | boolean | Submission in progress |
isSubmitted | boolean | Successful submit |
isProcessing | boolean | Async processing |
hasErrors | boolean | Validation errors present |
errors | array | Error message strings |
captchaHidden | boolean | Captcha visibility |
captchaToken | string | null | Turnstile token |
captchaPassed | boolean | Captcha verified |
Actions and callbacks
| Name | Role |
|---|---|
onSubmit | Validate, reveal captcha if needed, then submit |
onReset | Reset fields and state |
onInputChange / onInputRangeChange / onInputCheckboxClick | Field updates |
onFormMount | Restore localStorage |
sendSubmission | API/REST submit; success message or redirect |
onCaptchaPassing | Continues submit when captcha passes |
Related blocks
| Block | Relationship |
|---|---|
prc-block/synced-form | Embeds a Forms CPT post |
prc-block/form-page | Multi-step page |
prc-block/form-submit | Submit + captcha |
prc-block/form-message | Result message |
prc-block/form-captcha | Turnstile (usually inside Form Submit) |
prc-block/form-input-* | Field blocks in @prc/block-library |