blog-banner

Create Dynamic Form Fields in Drupal 7

  • Drupal 7
  • Drupal Planet
  • Form API

Create Dynamic Drupal Form

Drupal's Form API helps developers to build complex, extensible forms with minimal code and also gives the option to make the form fields dynamic. It means to change/create form fields fields based on the other field's given value. There is a cool trick to making dynamic fields in drupal.

Normally we are using #states elements to change other fields' values, show/hide based on the field's given value. I think it is not possible to give dynamic values (for example, give values from a database based on the field's given value). But we could do that with #ajax elements. Let's see the trick with an example.

I want to list all students from a particular selected class using a checkboxes field. If we change any class on the select box, then the current class students should be shown in the checkboxes.

/**
 * Implementation of hook_form().
 */
function knackforge_dynamic_form($form, $form_state) {
  $class = array(0 => 'Select', 1 => 'Class 1', 2 => 'Class 2');

  $form['class_from'] = array(
    '#type' => 'select',
    '#title' => t('Class'),
    '#description' => t('Select any one of the class from the list.'),
    '#options' => $class,
    '#default_value' => $class[1],
    '#ajax' => array(
      'callback' => 'knackforge_migrate_student_list', // Callback will replace the students field with new values.
      'wrapper' => 'migrate-students-list',
      'method' => 'replace',
      'event' => 'change',
    ),
  );

  // Students checkboxes field container.
  $form['students'] = array(
    '#type' => 'container',
    '#tree' => TRUE,
    '#prefix' => '
', '#suffix' => '
',
  );

  // Create default checkboxes field with default selected class's students options.
  $form['students']['list'] = array(
    '#type' => 'checkboxes',
    '#options' => _knackforge_get_student_list_options($class[1]),
  );

  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Migrate'),
  );
  return $form;
}

In the above form, we have used #ajax elements with change events on them. It means if we change the select box value then it will trigger the "knackforge_migrate_student_list" callback and the callback will replace the student field options values with newly selected class students. See the callback code,

/**
* Custom callback to build form fields.
*/
function knackforge_migrate_student_list($form, &$form_state) {
  $values = $form_state['values'];
  // Overwrite the student list fields with new options value.
  $form['students']['list'] = array(
    '#type' => 'checkboxes',
    '#options' => _knackforge_get_student_list_options($values['class_from']), // Api will return the class students list as array.
  );
  $form['students']['list'] = form_process_checkboxes($form['students']['list']); // Process the checkboxes fields.
  return $form['students']; // return full students field container.
}

/**
* API to return class's students list.
*/
function _knackforge_get_student_list_options($class) {
  $students = db_query('SELECT etid FROM {og_membership} WHERE entity_type = :entity_type AND gid = :gid', array(':entity_type' => 'user', 'gid' => $class))->fetchAll();
  $students_list = array();
  foreach ($students as $student) {
    $user = user_load($student->etid);
    If (in_array('student', $user->roles)) {
      $students_list[$user->uid] = $user->name; // Make array to fit with checkboxes options.
    }
  }
  return $students_list;
}

It's enough to make your form dynamic. The same trick will work in all other fields too.

Get awesome tech content in your inbox