FormAlter as Plugin

Provides a plugin-based system for form alterations, replacing traditional hook_form_alter() implementations with object-oriented plugins.

pluginformalter
1,353 sites
23
drupal.org

Install

Drupal 11, 10 v8.x-1.8
composer require 'drupal/pluginformalter:8.x-1.8'
Drupal 9, 8 v8.x-1.7
composer require 'drupal/pluginformalter:8.x-1.7'

Overview

FormAlter as Plugin is a developer utility module that modernizes how Drupal forms are altered. Instead of using the traditional procedural hook_form_alter() approach, developers can create object-oriented plugins with annotations to modify forms. This approach brings better code organization, dependency injection support, and clearer separation of concerns.

The module supports three types of form alterations: standard Drupal forms (by form_id or base_form_id), Paragraphs widget forms (by paragraph_type), and Inline Entity Form forms (by entity_type and bundle). Each plugin type comes with its own annotation and manager service, allowing for precise targeting of specific forms.

Additionally, the module integrates with the Webprofiler module to display which plugins are altering each form in the debug toolbar, making development and debugging easier.

Note: As of Drupal 11.2, this module triggers deprecation warnings because Drupal core now supports OOP Hooks natively. The module will stop functioning in Drupal 12.0.0, and developers should migrate to core's OOP Hooks instead.

Features

  • Plugin-based form alteration system replacing hook_form_alter() with object-oriented approach
  • Support for targeting forms by form_id or base_form_id with wildcard matching
  • Paragraphs module integration for altering paragraph type widget forms
  • Inline Entity Form module integration for altering IEF entity forms, reference forms, and table fields
  • Weight-based plugin ordering to control the sequence of form alterations
  • Multiple plugins can alter the same form with predictable execution order
  • Webprofiler integration showing all form alter plugins in the debug toolbar
  • Full dependency injection support through ContainerFactoryPluginInterface
  • String translation trait included in base class for localization support

Use Cases

Organizing Form Alterations by Domain

Create separate FormAlter plugins for each functional area of your application. For example, create UserLoginFormAlter for login modifications, NodeFormAlter for content editing, and CommerceCheckoutFormAlter for e-commerce. Each plugin encapsulates its logic cleanly with dependency injection.

Altering All Node Forms

Use base_form_id targeting to alter all node forms at once. Create a plugin with @FormAlter(id = "node_form_base_alter", base_form_id = {"node_form"}) to add common functionality like custom validation or field modifications across all content types.

Conditional Form Alterations

Combine the plugin system with conditional logic inside the formAlter() method. The plugin is instantiated only when the target form is rendered, and you can add additional runtime conditions within your implementation.

Targeting Specific Paragraphs Types

When working with the Paragraphs module, create ParagraphsFormAlter plugins to customize specific paragraph type forms. For example, modify the image paragraph widget to add custom JavaScript behaviors or validation.

Extending Inline Entity Forms

Use InlineEntityFormAlter plugins to customize how entities are embedded in forms. Target specific entity types and bundles, or modify the table fields display for entity reference lists.

Controlling Alteration Order

When multiple plugins alter the same form, use the weight property to control execution order. Lower weights execute first. This is essential when one alteration depends on another's changes.

Debugging Form Alterations

When Webprofiler is enabled, the module displays all FormAlter plugins affecting each form in the debug toolbar. This helps identify which plugins are modifying forms and trace unexpected behavior.

Tips

  • Plugin classes must be placed in src/Plugin/FormAlter/ directory to be discovered
  • Use wildcard patterns (e.g., 'node_*_form') in form_id to target multiple forms
  • The base class FormAlterBase includes StringTranslationTrait and DependencySerializationTrait for convenience
  • Implement ContainerFactoryPluginInterface (included in FormAlterBase) to inject services into your plugins
  • Plugins support both form_id and base_form_id targeting; base_form_id alterations run before form_id alterations
  • As of Drupal 11.2+, consider migrating to core's OOP Hooks feature instead of this module
  • Clear caches after adding or modifying plugins for changes to take effect

Technical Details

Hooks 1
pluginformalter_form_alter_info_alter

Alter the form alter plugin definitions discovered by any of the three plugin managers.

Troubleshooting 5
Plugin not being discovered

Ensure your plugin is in the correct namespace (Drupal\yourmodule\Plugin\FormAlter), has the correct annotation (@FormAlter, @ParagraphsFormAlter, or @InlineEntityFormAlter), and clear all caches.

Plugin alterations not applying in expected order

Adjust the weight property in your plugin annotations. Lower weights execute first. Use pluginformalter_form_alter_info_alter hook to modify weights at runtime if needed.

Deprecation warnings appearing in Drupal 11.2+

These warnings indicate the module is deprecated in favor of Drupal core's OOP Hooks. Plan migration to core's hook_form_alter OOP implementation before upgrading to Drupal 12.

Webprofiler integration not showing form alters

Ensure both the pluginformalter and webprofiler modules are enabled. Clear caches to ensure the service provider decorates the forms data collector correctly.

Paragraphs form alter not triggering

Verify you're using the @ParagraphsFormAlter annotation (not @FormAlter) and that the paragraph_type matches exactly. The paragraph_type should be the machine name of your paragraph type.