Remove Options from Drupal Webform Select Component

Sometimes it is necessary to remove one or more items from a Webform select list. For example, a client has a registration form for an event that will travel to a number of cities. After the event has passed for a particular city, the client desires the option to register for that city to be removed.

If the client simply removes the key|value pair for a city from the 'Options' list, then the key will remain stored in the database as the 'data' value for each submission in the 'webform_submitted_data' table; however, the value will be removed because the value is stored in the 'webform_component' table. As a result, when running reports or exporting data, only the key will be available (e.g. 'boston' but not 'Boston, MA').

The solution is to modify the Webform Select List component to allow for options to be 1) removed from the select list rendered for end users AND 2) maintained for data processing purposes.

Modify the Select List Component Edit Form

The first step is to modify edit form for the Select List component by adding an additional field to specify items to be removed:

/*
* Implements hook_form_FORM_ID_alter().
*/

function MYMODULE_form_webform_component_edit_form_alter(&$form, $form_state, $form_id) {
  // Check if this component edit form is for a 'select' component.
  if(isset($form_state['build_info']['args'][1]['type']) && $form_state['build_info']['args'][1]['type'] = 'select') {
    $form['extra']['items_remove']['#type'] = 'textarea';
    $form['extra']['items_remove']['#title'] = 'Remove Options';
    $form['extra']['items_remove']['#weight'] = 6;
    if(isset($form_state['build_info']['args'][1]['extra']['items_remove'])) {
      $form['extra']['items_remove']['#default_value'] = $form_state['build_info']['args'][1]['extra']['items_remove'];
    }
    $form['extra']['items_remove']['#description'] = 'Items listed here will be retained for data processing purposes but will
    not be presented as options for this component to end users filling out the form.<br><strong>List items by key
    with one item per line.</strong> Refer to the <em>safe_key</em> values from the <em>Options</em> field above. Items listed
    here that are not listed in the <em>Options</em> field above will be ignored.';
  }
}

A screenshot is provided below of the modified form:

Webform select list component form

In this example, four cities are listed in the 'Options' field: Boston, New York, Philadelphia, and Washington DC. In the 'Remove Options' field, Boston and New York are designated for removal. They will continue to be available for data processing; however, they will no longer be presented as options to end users completing the form.

Modify the Webform Client Form

The second step is to modify the Webform client form (i.e. the Drupal form that is presented to the end users, who will be filling out the form). It will be modified to remove options designated in the 'Options Remove' field from the rendered select list:

/*
* Implements hook_form_alter().
*/

function MYMODULE_form_alter(&$form, $form_state, $form_id) {
  // Check if form is a Webform form.
  if(substr($form_id, 0, 20) === "webform_client_form_") {
    foreach($form['submitted'] as $form_key => $component) {
      // Check if the type is set because not everything in this array is a component.
      if(isset($component['#webform_component']['type'])
      // Check that component type is 'select'.
      && $component['#webform_component']['type'] == 'select'
      // Check that 'items_remove' is set.
      && isset($component['#webform_component']['extra']['items_remove'])) {
        $items = $form['submitted'][$form_key]['#options'];
        // Use array_map trim to remove white space created by explode.
        $items_remove = array_map('trim', explode(PHP_EOL, $form['submitted'][$form_key]['#webform_component']['extra']['items_remove']));
        // Flip array so that the keys are values.
        $items_flipped = array_flip($items);
        // Remove items from options.
        $items = array_diff($items_flipped, $items_remove);
        // Flip array back and override #options.
        $form['submitted'][$form_key]['#options'] = array_flip($items);
      }
    }
  }
}

Below is the rendered select list, which is made available to end users. Notice that only Philadelphia and Washington DC are available as options:

Webform rendered select list

Add new comment