When adding custom configuration toggles to the root Form element (via renderingOptions or properties) in the Form Editor, these values are entirely stripped from the JSON response. The FormDefinitionDecorator hardcodes a strict mapping of allowed root keys (id, api, i18n, elements) and discards root-level renderingOptions.
This prevents integrators from passing form-level configuration (e.g., custom UI flags) to headless frontends.
To Reproduce
Extend the global Form prototype in YAML to add custom fields to the Form Editor under a public namespace (or at root level).
Expected Behavior
The native TYPO3 Form Framework uses renderingOptions to pass configuration to the renderer. The headless extension should support exposing safe, client-facing renderingOptions to the JSON payload so headless frontends (Astro, Next.js, Nuxt, etc.) can react to form-level settings.
Implementation
Directly passing $definition['renderingOptions'] as-is could inadvertently leak sensitive server-side paths (honeypot, Fluid templateRootPaths, finisher internals).
A safe, idiomatic solution for FormDefinitionDecorator::__invoke() would be to adopt a dedicated frontend namespace convention under renderingOptions (alongside safe native root keys like submitButtonLabel), while allowing integrators to flatten it if needed via decorators/events:
Example:
YAML
TYPO3:
CMS:
Form:
prototypes:
standard:
formElementsDefinition:
Form:
renderingOptions:
frontend:
enableTurnstile: true
formEditor:
predefinedDefaults:
renderingOptions:
frontend:
enableTurnstile: true
editors:
700:
identifier: enableTurnstile
templateName: Inspector-CheckboxEditor
label: "Enable Turnstile"
propertyPath: renderingOptions.frontend.enableTurnstile
PHP
// In \FriendsOfTYPO3\Headless\Form\Decorator\FormDefinitionDecorator::__invoke()
if (isset($definition['renderingOptions']) && is_array($definition['renderingOptions'])) {
$renderingOptions = $definition['renderingOptions'];
$publicRenderingOptions = [];
// 1. Pass native safe client-facing keys
$safeNativeKeys = ['submitButtonLabel', 'previousButtonLabel', 'nextButtonLabel'];
foreach ($safeNativeKeys as $key) {
if (array_key_exists($key, $renderingOptions)) {
$publicRenderingOptions[$key] = $renderingOptions[$key];
}
}
// 2. Pass custom frontend-flagged options namespace
if (isset($renderingOptions['frontend']) && is_array($renderingOptions['frontend'])) {
$publicRenderingOptions['frontend'] = $renderingOptions['frontend'];
}
if (!empty($publicRenderingOptions)) {
$result['form']['renderingOptions'] = $publicRenderingOptions;
}
}
(Currently working around this by hooking into a custom FormDecorator to manually extract and expose these options, but native support for renderingOptions in the extension is needed).
When adding custom configuration toggles to the root Form element (via renderingOptions or properties) in the Form Editor, these values are entirely stripped from the JSON response. The FormDefinitionDecorator hardcodes a strict mapping of allowed root keys (id, api, i18n, elements) and discards root-level renderingOptions.
This prevents integrators from passing form-level configuration (e.g., custom UI flags) to headless frontends.
To Reproduce
Extend the global Form prototype in YAML to add custom fields to the Form Editor under a public namespace (or at root level).
Expected Behavior
The native TYPO3 Form Framework uses renderingOptions to pass configuration to the renderer. The headless extension should support exposing safe, client-facing renderingOptions to the JSON payload so headless frontends (Astro, Next.js, Nuxt, etc.) can react to form-level settings.
Implementation
Directly passing $definition['renderingOptions'] as-is could inadvertently leak sensitive server-side paths (honeypot, Fluid templateRootPaths, finisher internals).
A safe, idiomatic solution for FormDefinitionDecorator::__invoke() would be to adopt a dedicated frontend namespace convention under renderingOptions (alongside safe native root keys like submitButtonLabel), while allowing integrators to flatten it if needed via decorators/events:
Example:
YAML
PHP
(Currently working around this by hooking into a custom FormDecorator to manually extract and expose these options, but native support for renderingOptions in the extension is needed).