Skip to main content
drupalreleases

Use direct release data with your AI assistant.

Learn more

Form Decorator

Security covered Under active development 193 sites

This module provides a way to customize Drupal forms by decorating them. Form decoration allows developers to modify form behavior by adding functionality without altering the original form class, offering benefits similar to working within the form class itself, such as dependency injection.

This module introduces an innovative way to customize Drupal forms through decoration. Form decoration allows developers to modify and enhance form behavior by applying a layer of additional functionality, without altering the original form class directly.

In Drupal forms are provided by form classes. In the form class you have to provide several methods:

getFormId()
buildForm()
validateForm()
submitForm()

It is also possible to inject services using dependency injection and to implement additional methods that are useful for this form.

That is very nice! But there is no easy way to extend a form class. If you want to alter a form you have to rely on hook_form_alter. Of course that works just fine but you loose all the nice features of the original form class (No object, no dependency injection, you have to change submit/validation handlers).

The form_decorator module introduces an easy way to change the form class itself. And because we want to be able to alter one form multiple times we use decoration.

In short: The key benefit over hook_form_alter hooks and event based solutions like https://www.drupal.org/project/hook_event_dispatcher is that in a decorator you can in principle work like you would in the form class itself.

We try to get this into core

See #3422081

Examples

Add custom validation to the user register form:

#[FormDecorator('form_user_register_form_alter')]
final class ValidateOnly extends FormDecoratorBase {

  public function validateForm(array &$form, FormStateInterface $form_state) {
    $this->inner->validateForm($form, $form_state);
    // Do your magic
    }
  }

}

Use dependency injection:

#[FormDecorator('form_user_login_form_alter')]
final class DependencyInjection extends FormDecoratorBase implements ContainerFactoryPluginInterface {

  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('entity_type.manager')
    );
  }

  public function __construct(
    array $configuration,
    $plugin_id,
    $plugin_definition,
    protected EntityTypeManagerInterface $entityTypeManager,
  ) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
  }

  public function buildForm(array $form, FormStateInterface $form_state, ...$args) {
    // Do your magic
  }

Allow to edit the created date of nodes:

#[FormDecorator('form_node_form_alter')]
final class NodeCreatedDate extends ContentEntityFormDecoratorBase {

  public function buildForm(array $form, FormStateInterface $form_state, ...$args) {
    $form = $this->inner->buildForm($form, $form_state, ...$args);
    $node = $this->getEntity();
    assert($node instanceof NodeInterface);
    $created_time = time();
    if (!$this->getEntity()->isNew()) {
      $created_time = $node->getCreatedTime();
    }

    $form['created_datepicker'] = [
      '#title' => $this->t('Created date'),
      '#type' => 'datetime',
      '#default_value' => DrupalDateTime::createFromTimestamp($created_time),
      '#weight' => 100,
    ];
    return $form;
  }

  public function save(array $form, FormStateInterface $form_state) {
    $node = $this->getEntity();
    assert($node instanceof NodeInterface);
    $node->setCreatedTime($form_state->getValue('created_datepicker')->getTimestamp());
    return $this->inner->save($form, $form_state);
  }
Drupal 10–11

Ask your assistant about Form Decorator

Check compatibility with your Drupal and PHP version, maintenance and security coverage, from current release data. How it works

Depends on

Dependencies of the latest stable release

No dependencies recorded for this project.

Required by

Tracked projects that depend on this one

No tracked projects depend on this one yet.

Activity

Tracked releases
10
Tracked since
Feb 2024
Latest release
3 months ago
Releases (12 mo)
3 ▼ from 4
Maintenance
Active

Release Timeline

Releases

Version Type Core PHP Release date
1.1.0 Stable 10–11 Jul 12, 2026
1.1.x-dev Dev 10–11 Jul 12, 2026
1.0.1 Stable 10–11 Jan 27, 2026
1.0.0 Stable 10–11 Jul 16, 2025
1.0.0-rc1 Pre-release 10–11 May 28, 2025
1.0.0-beta1 Pre-release 10–11 Jan 30, 2025
1.0.0-alpha3 Pre-release 10–11 Jan 13, 2025
1.0.0-alpha2 Pre-release 10 May 7, 2024
1.0.0-alpha1 Pre-release 10 Apr 5, 2024
1.0.x-dev Dev 10–11 Feb 17, 2024