| Understand Form API basics |
Overview |
Use Form API when you need user input with validation and CSRF protection. Use render arrays for display-only content. |
| Choose the right base class |
Architecture: Core Classes |
Choose the appropriate base class based on your form's purpose. Use FormBase for general forms, ConfigFormBase for settings, ConfirmFormBase for confirmations. |
| Understand form lifecycle and caching |
Architecture: Lifecycle |
Understand the lifecycle to know when to cache forms (multi-step, AJAX) and where to place logic (buildForm vs submitForm). |
| Build a standard form with business logic |
Pattern: FormBase |
Use FormBase for general-purpose forms with custom business logic. Use ConfigFormBase for settings, EntityForm for entities, ConfirmFormBase for confirmations. |
| Build an admin settings form |
Pattern: ConfigFormBase |
Use ConfigFormBase for admin settings and system configuration. Use FormBase for non-configuration data or temporary workflow data. |
| Build a delete/confirm dialog |
Pattern: ConfirmFormBase |
Use ConfirmFormBase for delete operations and irreversible actions. Use FormBase for forms with additional input fields. |
| Choose the right form elements |
Elements: Overview |
Choose element types based on data type and UI needs. All elements are plugins discovered from Element/ directory. |
| Use text, number, date inputs |
Elements: Input |
Choose specific input types for HTML5 validation and mobile keyboard hints. Use textfield for generic text, email for emails, number for numeric input. |
| Use select, radio, checkbox, file uploads |
Elements: Selection |
Choose selection elements based on number of options and whether multiple selections are allowed. Use entity_autocomplete for >50 options. |
| Group elements and add buttons |
Elements: Grouping |
Use grouping elements to organize form structure and improve UX. Choose containers for AJAX wrappers, fieldsets for visual grouping, details for collapsible sections. |
| Understand element callbacks |
Elements: Lifecycle |
Use #process for adding child elements, #after_build for accessing complete tree, #pre_render for final display modifications. |
| Validate form input |
Validation Architecture |
Use element-level validation for single-field checks, form-level for cross-field validation, typed config for automatic schema validation. |
| Validate only specific fields (multi-step) |
Validation: Partial |
Use partial validation for multi-step forms with "Previous" buttons, "Save draft" vs "Publish" buttons, or progressive disclosure forms. |
| Handle form submission and redirects |
Submission Architecture |
Understand submission handler priority to control execution order. Always redirect after successful submit to prevent form resubmission. |
| Add AJAX to forms |
AJAX Architecture |
Use AJAX when you need server-side logic or dynamic options. Use #states for simple show/hide (faster, client-side only). |
| Secure AJAX and use advanced patterns |
AJAX: Security |
Always use render arrays in AJAX callbacks (auto-escaped). Use AJAX commands for multiple element updates. |
| Use FormState methods |
Form State Methods |
Use getValue() for submitted values (sanitized), set()/get() for persistent storage across rebuilds, setTemporaryValue() for single-request data. |
| Build multi-step forms |
Multi-Step Forms |
Use multi-step forms for complex workflows requiring user input across multiple pages. Always enable caching with setCached(TRUE). |
| Alter existing forms |
Form Alter System |
Use specific form alter hooks (hook_form_FORM_ID_alter) for performance. Use generic hook_form_alter only when altering multiple forms. |
| Use #states for conditional fields |
Form States System |
Use #states for client-side show/hide and enable/disable. Use AJAX when server-side logic or dynamic options needed. |
| Submit forms programmatically |
Programmatic Submission |
Use programmatic submission for batch operations, migrations, automated testing, and cron jobs. Never for user-submitted forms. |
| Optimize form performance |
Performance Optimization |
Optimize forms when buildForm() takes >200ms, AJAX callbacks >300ms, or you have >50 options. Target: <1s load, <2s submit. |
| Follow development standards |
Development Standards |
Development standards and anti-patterns - opinionated best practices and critical mistakes to avoid |
| Secure forms against attacks |
Security Best Practices |
Security best practices - CSRF, XSS, SQL injection, and file upload security |
| Make quick decisions |
Decision Trees |
Decision trees and quick reference matrices for form development |
| Find documentation and examples |
API References |
API references, core files, documentation links, and community resources |