- Issue created by @pdureau
- ๐ซ๐ทFrance Grimreaper France ๐ซ๐ท
Proposed resolution:
In the YAML, a new "form" root level entry to contain those form "props" (ajax, description, etc.).
Or
Normal props declaration, and a mapping system to say "this 'message' prop/slot is sourced by 'description' form property".
- ๐ซ๐ทFrance pdureau Paris
Let's have a look on all 37 Render Elements from Core:
$ grep -r "\[FormElement(" . | sort | grep -v test ./lib/Drupal/Core/Datetime/Element/Datelist.php:#[FormElement('datelist')] ./lib/Drupal/Core/Datetime/Element/Datetime.php:#[FormElement('datetime')] ./lib/Drupal/Core/Entity/Element/EntityAutocomplete.php:#[FormElement('entity_autocomplete')] ./lib/Drupal/Core/Render/Element/Button.php:#[FormElement('button')] ./lib/Drupal/Core/Render/Element/Checkboxes.php:#[FormElement('checkboxes')] ./lib/Drupal/Core/Render/Element/Checkbox.php:#[FormElement('checkbox')] ./lib/Drupal/Core/Render/Element/Color.php:#[FormElement('color')] ./lib/Drupal/Core/Render/Element/Date.php:#[FormElement('date')] ./lib/Drupal/Core/Render/Element/Email.php:#[FormElement('email')] ./lib/Drupal/Core/Render/Element/File.php:#[FormElement('file')] ./lib/Drupal/Core/Render/Element/Hidden.php:#[FormElement('hidden')] ./lib/Drupal/Core/Render/Element/ImageButton.php:#[FormElement('image_button')] ./lib/Drupal/Core/Render/Element/Item.php:#[FormElement('item')] ./lib/Drupal/Core/Render/Element/LanguageSelect.php:#[FormElement('language_select')] ./lib/Drupal/Core/Render/Element/MachineName.php:#[FormElement('machine_name')] ./lib/Drupal/Core/Render/Element/Number.php:#[FormElement('number')] ./lib/Drupal/Core/Render/Element/PasswordConfirm.php:#[FormElement('password_confirm')] ./lib/Drupal/Core/Render/Element/Password.php:#[FormElement('password')] ./lib/Drupal/Core/Render/Element/PathElement.php:#[FormElement('path')] ./lib/Drupal/Core/Render/Element/Radio.php:#[FormElement('radio')] ./lib/Drupal/Core/Render/Element/Radios.php:#[FormElement('radios')] ./lib/Drupal/Core/Render/Element/Range.php:#[FormElement('range')] ./lib/Drupal/Core/Render/Element/Search.php:#[FormElement('search')] ./lib/Drupal/Core/Render/Element/Select.php:#[FormElement('select')] ./lib/Drupal/Core/Render/Element/Submit.php:#[FormElement('submit')] ./lib/Drupal/Core/Render/Element/Table.php:#[FormElement('table')] ./lib/Drupal/Core/Render/Element/Tableselect.php:#[FormElement('tableselect')] ./lib/Drupal/Core/Render/Element/Tel.php:#[FormElement('tel')] ./lib/Drupal/Core/Render/Element/Textarea.php:#[FormElement('textarea')] ./lib/Drupal/Core/Render/Element/Textfield.php:#[FormElement('textfield')] ./lib/Drupal/Core/Render/Element/Token.php:#[FormElement('token')] ./lib/Drupal/Core/Render/Element/Url.php:#[FormElement('url')] ./lib/Drupal/Core/Render/Element/Value.php:#[FormElement('value')] ./lib/Drupal/Core/Render/Element/VerticalTabs.php:#[FormElement('vertical_tabs')] ./lib/Drupal/Core/Render/Element/Weight.php:#[FormElement('weight')] ./modules/file/src/Element/ManagedFile.php:#[FormElement('managed_file')] ./modules/language/src/Element/LanguageConfiguration.php:#[FormElement('language_configuration')]
Form elements with #theme
23 of them are wrapper around theme hooks:
$ grep -r -A 1000 "\[FormElement(" . | grep '#theme..=' | sort | grep -v test ./lib/Drupal/Core/Datetime/Element/Datelist.php- '#theme' => 'datetime_form', ./lib/Drupal/Core/Datetime/Element/Datetime.php- '#theme' => 'datetime_form', ./lib/Drupal/Core/Render/Element/Checkbox.php- '#theme' => 'input__checkbox', ./lib/Drupal/Core/Render/Element/Color.php- '#theme' => 'input__color', ./lib/Drupal/Core/Render/Element/Date.php- '#theme' => 'input__date', ./lib/Drupal/Core/Render/Element/Email.php- '#theme' => 'input__email', ./lib/Drupal/Core/Render/Element/File.php- '#theme' => 'input__file', ./lib/Drupal/Core/Render/Element/Hidden.php- '#theme' => 'input__hidden', ./lib/Drupal/Core/Render/Element/MachineName.php- '#theme' => 'input__textfield', ./lib/Drupal/Core/Render/Element/Number.php- '#theme' => 'input__number', ./lib/Drupal/Core/Render/Element/Password.php- '#theme' => 'input__password', ./lib/Drupal/Core/Render/Element/Radio.php- '#theme' => 'input__radio', ./lib/Drupal/Core/Render/Element/Range.php- '#theme' => 'input__range', ./lib/Drupal/Core/Render/Element/Search.php- '#theme' => 'input__search', ./lib/Drupal/Core/Render/Element/Select.php- '#theme' => 'select', ./lib/Drupal/Core/Render/Element/Table.php- '#theme' => 'table', ./lib/Drupal/Core/Render/Element/Tableselect.php- '#theme' => 'table__tableselect', ./lib/Drupal/Core/Render/Element/Tel.php- '#theme' => 'input__tel', ./lib/Drupal/Core/Render/Element/Textarea.php- '#theme' => 'textarea', ./lib/Drupal/Core/Render/Element/Textfield.php- '#theme' => 'input__textfield', ./lib/Drupal/Core/Render/Element/Token.php- '#theme' => 'input__hidden', ./lib/Drupal/Core/Render/Element/Url.php- '#theme' => 'input__url', ./modules/file/src/Element/ManagedFile.php- '#theme' => 'file_link', ./modules/file/src/Element/ManagedFile.php- '#theme' => 'file_managed_file',
file_managed_file:
{{ element }}input.html.twig:
<input{{ attributes }} />{{ children }}
textarea.html.twig:
{{ value }}select.html.twig:
<select{{ attributes }}> {% for option in options %} ... {% endfor %} </select>
datetime-form.html.twig:
<div{{ attributes }}> {{ content }} </div>
Other form elements
The other 14 (15?) are:
./lib/Drupal/Core/Entity/Element/EntityAutocomplete.php:#[FormElement('entity_autocomplete')] ./lib/Drupal/Core/Render/Element/Button.php:#[FormElement('button')] ./lib/Drupal/Core/Render/Element/Checkboxes.php:#[FormElement('checkboxes')] ./lib/Drupal/Core/Render/Element/ImageButton.php:#[FormElement('image_button')] ./lib/Drupal/Core/Render/Element/Item.php:#[FormElement('item')] ./lib/Drupal/Core/Render/Element/LanguageSelect.php:#[FormElement('language_select')] ./lib/Drupal/Core/Render/Element/MachineName.php:#[FormElement('machine_name')] ./lib/Drupal/Core/Render/Element/PathElement.php:#[FormElement('path')] ./lib/Drupal/Core/Render/Element/PasswordConfirm.php:#[FormElement('password_confirm')] ./lib/Drupal/Core/Render/Element/Radios.php:#[FormElement('radios')] ./lib/Drupal/Core/Render/Element/Submit.php:#[FormElement('submit')] ./lib/Drupal/Core/Render/Element/Value.php:#[FormElement('value')] ./lib/Drupal/Core/Render/Element/VerticalTabs.php:#[FormElement('vertical_tabs')] ./lib/Drupal/Core/Render/Element/Weight.php:#[FormElement('weight')] ./modules/language/src/Element/LanguageConfiguration.php:#[FormElement('language_configuration')]
- ๐ซ๐ทFrance pdureau Paris
Current state of our investigation.
Slot or prop:
- #description: (string) Help or description text for the element. In an ideal user interface, the #title should be enough to describe the element, so most elements should not have a description; if you do need one, make sure it is translated. If it is not already wrapped in a safe markup object, it will be filtered for XSS safety.
- #description_display: (string) Where and how to display the #description.
- #prefix: (string) Prefix to display before the HTML input element. Should be translated, normally. If it is not already wrapped in a safe markup object, will be filtered for XSS safety.
- #suffix: (string) Suffix to display after the HTML input element. Should be translated, normally. If it is not already wrapped in a safe markup object, will be filtered for XSS safety.
- #title: (string) Title of the form element. Should be translated.
- #title_display: (string) Where and how to display the #title.
Already covered ion our POC:
- #name
- #default_value: Default value for the element. See also #value.
- #required: (bool) Whether or not input is required on the element.
- #value: Used to set values that cannot be edited by the user
To evaluate:
- #ajax: (array) Array of elements to specify Ajax behavior. See the Javascript API and AJAX Forms guides for more information.
- #disabled: (bool) If TRUE, the element is shown but does not accept user input.
- #required_error: (string) Override default error message "@field_title is required" will be used if this is undefined.
- Merge request !11876Draft: Issue #3508641 by pdureau, grimreaper: Define form elements from SDC โ (Open) created by Grimreaper
- ๐ซ๐ทFrance Grimreaper France ๐ซ๐ท
MR created from https://git.drupalcode.org/project/drupal/-/merge_requests/11866, so now in this other issue MR, I can remove what is purely to have form element as SDC component.
- ๐ซ๐ทFrance pdureau Paris
For information, Grimreaper is currently testing his proposal:
- With a "normal" form fully built in a PHP class
- As Field Widgets, using an UI Patterns โ mechanism (context-sensitive data sources, to retrieve and check field properties), but it will be relevant for other SDC usage
- ๐ซ๐ทFrance Grimreaper France ๐ซ๐ท
Before cleaning my workspace, here is the result of friday at the end of DDD 2025.