Custom Field Types
Register a new field type across the builder, renderer, and submission handler.
Three places a field type lives
A field type isn't real until it's implemented in all three of these layers — adding it to just one gives you a field that looks right but doesn't actually work:
assets/src/builder/fields.js— the field-type registry. This makes the type draggable in the builder and defines its default config, but doesn't render or validate anything by itself.public/class-shortcode.php— the front-end renderer. Add acaseto the field-type switch that outputs the actual HTML markup visitors fill in.public/class-submission-handler.php— validation and storage. Add handling for how the submitted value is validated, sanitized, and stored in the entry'sresponseJSON.
A minimal example
A new "Star Count" field type (a plain number input styled as a star count) would need:
// fields.js
export function createField(type) {
if (type === 'star_count') {
return { type, label: 'Rating', maxStars: 5 };
}
// ...
}// class-shortcode.php
case 'star_count':
printf(
'<input type="number" name="%s" min="0" max="%d">',
esc_attr( $name ),
(int) $field['maxStars']
);
break;// class-submission-handler.php
// No special-casing needed here if the field is a plain number input —
// it falls through to the generic sanitize_text_field() + required-check
// path already used for simple fields.Live preview in the builder
assets/src/builder/components/Canvas.js has its own switch statement
for rendering a field's live preview while editing — this is separate
from the front-end renderer in class-shortcode.php and needs its own
case for the field to show correctly on the canvas rather than falling
back to a generic placeholder.