diff --git a/core/lib/Drupal/Core/Render/Element/Optgroup.php b/core/lib/Drupal/Core/Render/Element/Optgroup.php index 03bc474..7e43234 100644 --- a/core/lib/Drupal/Core/Render/Element/Optgroup.php +++ b/core/lib/Drupal/Core/Render/Element/Optgroup.php @@ -33,6 +33,9 @@ public function getInfo() { array($class, 'processOptgroup'), array($class, 'processAjaxForm'), ), + '#pre_render' => array( + array($class, 'preRenderOptgroup'), + ), '#theme' => 'optgroup', '#options' => array(), ); @@ -83,7 +86,6 @@ public static function processOptgroup(&$element, FormStateInterface $form_state $weight += 0.001; $empty_choice = $empty_value && $key == '_none'; - $is_default = $value_valid && ((!$value_is_array && (string) $element['#value'] === $key || ($value_is_array && in_array($key, $element['#value']))) || $empty_choice); $element += array($key => array()); $element[$key] += array( @@ -102,4 +104,12 @@ public static function processOptgroup(&$element, FormStateInterface $form_state return $element; } + /** + * Prepares an option group render element. + */ + public static function preRenderOptgroup($element) { + $element['#attributes']['label'] = $element['#title']; + return $element; + } + } diff --git a/core/lib/Drupal/Core/Render/Element/Option.php b/core/lib/Drupal/Core/Render/Element/Option.php index 9877d69..3251fa6 100644 --- a/core/lib/Drupal/Core/Render/Element/Option.php +++ b/core/lib/Drupal/Core/Render/Element/Option.php @@ -41,7 +41,7 @@ public function getInfo() { } /** - * Prepares a select render element. + * Prepares an option render element. */ public static function preRenderOption($element) { $element['#attributes']['value'] = $element['#return_value']; diff --git a/core/lib/Drupal/Core/Render/Element/Select.php b/core/lib/Drupal/Core/Render/Element/Select.php index 08e3716..0280811 100644 --- a/core/lib/Drupal/Core/Render/Element/Select.php +++ b/core/lib/Drupal/Core/Render/Element/Select.php @@ -127,6 +127,45 @@ public static function processSelect(&$element, FormStateInterface $form_state, } } + // Process option groups. + // @TODO Fix weights with mixed optgroups and options. + if (count($element['#options']) > 0) { + // @TODO This is ported from form_select_options(). But instead of + // checking #value, #default_value should be used here and below, right? + $value_valid = isset($element['#value']) || array_key_exists('#value', $element); + $value_is_array = $value_valid && is_array($element['#value']); + // Check if the element is multiple select and no value has been selected. + $empty_value = (empty($element['#value']) && !empty($element['#multiple'])); + + $weight = 0; + foreach ($element['#options'] as $key => $choice) { + $key = (string) $key; + + if (is_array($choice)) { + // Maintain order of options as defined in #options, in case the element + // defines custom option sub-elements, but does not define all option + // sub-elements. + $weight += 0.001; + + $element += array($key => array()); + $element[$key] += array( + '#type' => 'optgroup', + '#title' => $key, + // The key is sanitized in Drupal\Core\Template\Attribute during output + // from the theme function. + '#options' => $choice, + '#ajax' => isset($element['#ajax']) ? $element['#ajax'] : NULL, + '#weight' => $weight, + ); + + // @TODO + static::processOptgroup($element[$key], $form_state, $complete_form); + + unset($element['#options'][$key]); + } + } + } + // Process the '#options' element in the same way that option groups do. static::processOptgroup($element, $form_state, $complete_form);