Skip to content

Instantly share code, notes, and snippets.

@alisonjo315
Last active November 7, 2023 23:56
Show Gist options
  • Save alisonjo315/886ca65485d3568f4a5e08ea9e74b74a to your computer and use it in GitHub Desktop.
Save alisonjo315/886ca65485d3568f4a5e08ea9e74b74a to your computer and use it in GitHub Desktop.
optgroup demo

optgroup demo

Adding optgroup elements to a "has taxonomy term (with depth)" exposed filter on a Drupal 9/10 view (for sharing on Drupal issue #2384203).

Screenshot of what the select with optgroup looks like on our site, edited for length: image

Select with optgroup HTML:

<select data-drupal-selector="edit-unique-category-depth-filter" id="edit-unique-category-depth-filter" name="unique_category_depth_filter" class="form-select">
  <option value="All" selected="selected">- Any -</option>
  <optgroup label="Approvals">
    <option value="1352">All in Approvals</option>
    <option value="1354">FPARs</option>
    <option value="1355">Municipal Reviews, Approvals and Permitting</option>
  </optgroup>
  <optgroup label="Procurement">
    <option value="1330">All in Procurement</option>
    <option value="1331">Consultant Selection</option>
    <option value="1332">Vendor selection</option>
    <option value="1333">Contractor selection</option>
    <option value="1334">Contracts</option></optgroup>
  <optgroup label="Design">
    <option value="1353">All in Design</option>
    <option value="1356">Submissions &amp; Reviews</option>
    <option value="1357">Process</option>
    <option value="1358">HazMat</option>
    <option value="1359">Site Design</option>
  </optgroup>
</select>

PHP code to make it happen -- I put it in our .theme file, but it could certainly go in a custom module. (And no, we didn't check for the view name/display -- we could've, maybe we should've, but we didn't :) )

<?php

/**
 *  Resources view > Document Category filter:
 * - Add "optgroup" elements for each parent term.
 * - Add the parent term as the first selectable option in each optgroup.
 */
function mysite_form_views_exposed_form_alter(&$form, $form_state, $form_id) {
  $filter_keys = array_filter(array_keys($form), fn($v) => str_starts_with($v, 'unique_category_depth_filter'));
  if (empty($filter_keys)) {
    return;
  }
  foreach ($filter_keys as $filter_key) {
    switch ($filter_key) {
      case 'unique_category_depth_filter':
        $current_options = $form[$filter_key]['#options'];
        $current_parent = "";
        $option_any = array_shift($current_options);
        $new_options = [];
        $new_options['All'] = $option_any;
        foreach ($current_options as $option) {
          $option_array = $option->option;
          $tax_id = array_key_first($option_array);
          $option_value = array_values($option_array)[0];
          if (str_starts_with($option_value, '-')) {
            $prefix = '-';
            if (substr($option_value, 0, strlen($prefix)) == $prefix) {
              $option_value = substr($option_value, strlen($prefix));
            }
            $new_options[$current_parent][$tax_id] = $option_value;
          }
          // or if it's a parent option
          else {
            $current_parent = $option_value;
            $new_options[$option_value] = [];
            $new_options[$option_value][$tax_id] = 'All in ' . $option_value;
          }
        }
        unset($form[$filter_key]['#size']);
        $form[$filter_key]['#type'] = 'select';
        $form[$filter_key]['#options'] = $new_options;
        // yes, that's it -- Drupal takes it from here.
        break;
    }
  }
}

?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment