The new trait, Drupal\Core\Recipe\RecipeInputFormTrait, can be added to form classes if you want to create a UI that collects input values for a recipe which needs them.
For recipe authors
To work with forms, your recipe needs to define how it wants its inputs to look when rendered in a form. For example, from core's feedback_contact_form recipe:
input:
recipient:
data_type: email
description: 'The email address that should receive submissions from the feedback form.'
constraints:
NotBlank: []
prompt:
method: ask
arguments:
question: 'What email address should receive website feedback?'
form:
'#type': email
'#title': 'Feedback form email address'
default:
source: config
config: ['system.site', 'mail']
Anything under the form key will be used to build the form element for this input. If form is not present, the input will never be shown in a form at all. If it is present, it must be an array containing only form element properties (i.e., every key must begin with #) -- it cannot contain any child elements.
For developers building a recipe UI
In your form class, load the recipe as an object using \Drupal\Core\Recipe\Recipe::createFromDirectory(), and then generate a set of elements for the recipe's inputs and all of its dependencies, validate them, and apply the recipe programmatically with the submitted values:
class MyRecipeForm extends FormBase {
use RecipeInputFormTrait;
public function buildForm(array $form, FormStateInterface $form_state): array {
$recipe = Recipe::createFromDirectory('core/recipes/feedback_contact_form');
$form += $this->buildRecipeInputForm($recipe);
// $form['feedback_contact_form']['recipient'] will now exist, and have '#type' => 'email'.
return $form;
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state): void {
$recipe = Recipe::createFromDirectory('core/recipes/feedback_contact_form');
$this->validateRecipeInput($recipe, $form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state): void {
$recipe = Recipe::createFromDirectory('core/recipes/feedback_contact_form');
$this->setRecipeInput($recipe, $form_state);
RecipeRunner::processRecipe($recipe);
}
}
See core/modules/system/tests/modules/form_test/src/Form/FormTestRecipeInputForm.php for an example of how this works.