custom form

How to Create Custom Form in Drupal

  • Profile picture of Mcs
  • by Mcs June 27, 2025

Follow these easy step to begin the process of creating a custom form with Drupal’s Form API:

  1. Create a .info.yml inside a custom module. (As we are creating a separate module for custom forms, this step is not required for adding forms in an existing module).
  2. Create a form class for returning the form array. (custom_module/src/Form/Registration.php
  3. Create a .routing.yml file
  4. Create a .module and hook_form_alter() and/or hook_form_FORM_ID_alter() to alter the form (If needed).

Here is a complete example of an employee registration form:

Folder structure:

employee-registration

1. employee_registration.info.yml

name: Employee Registration Form
type: module
description: Custom module for implementing custom employee registration form.
core_version_requirement: ^9 || ^10
package: Custom

2. src/Form/Registration.php


namespace Drupal\employee_registration\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;

/**
* Implements a custom form.
*/
class Registration extends FormBase {

 /**
  * {@inheritdoc}
  */
 public function getFormId() {
   return 'employee_registration_form';
 }

 /**
  * {@inheritdoc}
  */
 public function buildForm(array $form, FormStateInterface $form_state) {
   $form['emp_name'] = [
    '#type' => 'textfield',
    '#title' => $this->t('Enter Name'),
    '#required' => TRUE,
  ];

  $form['emp_no'] = [
    '#type' => 'textfield',
    '#title' => $this->t('Enter Employee Number'),
    '#required' => TRUE,
  ];

  $form['emp_mail'] = [
    '#type' => 'email',
    '#title' => $this->t('Enter Email ID'),
    '#required' => TRUE,
  ];

  $form['emp_phone'] = [
    '#type' => 'tel',
    '#title' => $this->t('Enter Contact Number'),
  ];

  $form['emp_dob'] = [
    '#type' => 'date',
    '#title' => $this->t('Enter DOB'),
    '#required' => TRUE,
  ];

  $form['emp_gender'] = [
    '#type' => 'select',
    '#title' => $this->t('Select Gender'),
    '#options' => [
      'Male' => $this->t('Male'),
      'Female' => $this->t('Female'),
      'Other' => $this->t('Other'),
    ],
  ];

   $form['submit'] = [
     '#type' => 'submit',
     '#value' => $this->t('Save'),
     '#button_type' => 'primary',
   ];

   return $form;
 }

 /**
  * {@inheritdoc}
  */
 public function validateForm(array &$form, FormStateInterface $form_state) {
   if (strlen($form_state->getValue('emp_phone')) < 10) {
     $form_state->setErrorByName('emp_phone', $this->t('The phone number is too short. Please enter a full phone number.'));
   }
 }

 /**
  * {@inheritdoc}
  */
 public function submitForm(array &$form, FormStateInterface $form_state) {
   // Processing form data.
   $this->messenger()->addMessage($this->t("Employee Registration Done!!"));
       foreach ($form_state->getValues() as $key => $value) {
      $this->messenger()->addMessage($key . ': ' . $value);
   }
 }

}

3. employee_registration.routing.yml

employee_registration.form:
 path: '/registration-form'
 defaults:
   _title: 'Employee Registration'
   _form: '\Drupal\employee_registration\Form\Registration'
 requirements:
   _permission: 'access content'

Result:

emp-reg-form
emp-reg-page

Comments

Add new comment

Restricted HTML

  • Allowed HTML tags: <br> <p> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id> <cite> <dl> <dt> <dd> <a hreflang href> <blockquote cite> <ul type> <ol type start> <strong> <em> <code> <li>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.