Creating Drupal forms, tabs and vertical tabs using Form API

Drupal makes me happy

Sites are easy to create using Drupal CMS. But giving nice forms which client can use and set different things on the site will really make our life a lot easy. In this tutorial, I will show how we would use the Forms API and Vertical tabs to create pages in the admin section.

The Drupal 7 Form API really comes a long way with a lot of new features which I really like. One thing which I always use a lot if the vertical tabs. It allows us to categorize the different type of settings just in one page and the client can use it with ease.

So, here is what we are going to do:

  1. Create three pages using hook menu
  2. Creating the form

So, here is the code where I have implemented hook_menu

/**
 * Implementing hook_menu()
 */
function adminform_menu() {
    
  // The basic page.
  $items['admin/jr'] = array(
    'title' => t('SA Admin'),
    'description' => t('Change the content of the contact form'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array('adminform_contact_form'),
    'access arguments' => array('access administration pages'),
    'weight' => 1
  );
    
  // This will be the default page when the link is clicked.
  $items['admin/jr/contactform'] = array(
    'title' => t('Contact form'),
    'description' => t('Change the content of the contact form'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array('adminform_contact_form'),
    'access arguments' => array('access administration pages'),
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => 2
  );
    
  // This is just a copy for the tab and nothing else.
  $items['admin/jr/somethingelse'] = array(
    'title' => t('Some other form'),
    'description' => t('Change the content of the contact form'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array('adminform_contact_form'),
    'access arguments' => array('access administration pages'),
    'type' => MENU_LOCAL_TASK,
    'weight' => 3
  );
    
  return $items;
}

The first item is creating a path [admin/jr] which is the main section. This is where the subpages will fall into. It is always a good idea to have all the custom settings page inside a category so that your client can easily access it. For example, all the settings in my site is under admin/XXX ? (can’t reveal it).

The second and the third are the subpages which later gets converted into tabs. Take a look at line number 23 which says MENU_DEFAULT_LOCAL_TASK. This means that the [admin/jr/contactform] is the first page that will come up when someone goes to [admin/jr].

And then the code for the form

/**
 * Building the form for the contact setting page.
 */
function adminform_contact_form() {
    
  // This is to specify the vertical tab holder.
  // One page can have two vertical tabs, but it's always one main tab with sub tabs.
  $form['contactform'] = array(
    '#type' => 'vertical_tabs',
  );
    
  // This is the field fieldset.
  $form['contactformset'] = array(
    '#type' => 'fieldset',
    '#title' => t('Attention, new comment posted'),
    '#collapsible' => TRUE,
    '#description' => t('Edit the email body for the new comment posted on the site.'),
    '#group' => 'contactform'
  );
    
  // Adding a simple textarea.
  $form['contactformset']['mailbody'] = array(
    '#type' => 'textarea',
    '#required' => TRUE,
    '#default_value' => 'Default',
    '#title' => t('Contact mail.'),
    '#description' => t('Body text when a new comment is posted by users.'),
    '#group' => 'contactform'
  );
    
  // This is second fieldset, this will make the two sections under the vertical tab.
  $form['settingformset'] = array(
    '#type' => 'fieldset',
    '#title' => t('Site wide settings'),
    '#collapsible' => TRUE,
    '#description' => t('Set different settings which will effect site wide.'),
    '#group' => 'contactform'
  );
    
    
  // Replicating the above textarea, this is just for demo.
  $form['settingformset']['setting'] = array(
    '#type' => 'textarea',
    '#required' => TRUE,
    '#default_value' => 'Default',
    '#title' => t('Contact mail.'),
    '#description' => t('Body text when a new comment is posted by users.'),
    '#group' => 'contactform'
  );
    
  $form['#submit'][] = 'adminform_contact_form_submit'; //Submit button call back.
  return system_settings_form($form);
}

Here the comments are more than enough I guess, but still. We need a main vertical tab form element which will contain all the sub tabs. Then we have two fieldsets which are the actual subgroups inside the vertical tab on line number 13 and 32. The rest are just text area.

And then I have added the submit function just in case. This does not do anything, but only so that the module does not fail.

/**
 * Logic behind the form submit.
 */
function adminform_contact_form_submit($form, $form_state) {
  // Kept it empty, intentionally.
}

And this is my final output. You can download the code here.

Drupal makes me happy