I wanted to make a select field that listed the counties of the UK grouped in to regions. I used the 'Allowed values function' field within the select list settings to specify a custom function uk_county_list() to build the allowed values.

<?php
function uk_county_list() {
  return array(
   
'North West' => array(
     
'Cheshire' => 'Cheshire',
     
'Cumbria' => 'Cumbria',
     
'Greater Manchester' => 'Greater Manchester',
     
'Isle of Man' => 'Isle of Man',
     
'Lancashire' => 'Lancashire',
     
'Merseyside' => 'Merseyside',
    ),
   ...
?>

This produced the desired select field with optgroups:

<select class="form-select required" name="field_job_county[und]" id="edit-field-job-county-und">
  <optgroup label="North West">
    <option value="Cheshire">Cheshire</option>
    <option value="Cumbria">Cumbria</option>
    <option selected="selected" value="Greater Manchester">Greater Manchester</option>
    <option value="Isle of Man">Isle of Man</option>
    <option value="Lancashire">Lancashire</option>
    <option value="Merseyside">Merseyside</option>
  </optgroup>
  <optgroup label="North East">
    <option value="County Durham">County Durham</option>
    <option value="Northumberland">Northumberland</option>
    ...

However, when a user selects a county on the node edit/creation screen, they get an 'illegal value' error on that field every time, regardless of the value selected.

I believe the problem lies with the list_field_validate() module within list.module of the core field module. The list of allowed_values is returned as a two-dimensional array but this function seems to assume that the list is always flat and in the case of the a select list with optgroups, the validate always fails.

My hack was to flatten the $allowed_values array before validating but there may be a cleaner way of doing it:

<?php
function list_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
 
$allowed_values = options_array_flatten(list_allowed_values($field)); // Flatten the array to accommodate optgroups
 
foreach ($items as $delta => $item) {
    if (!empty(
$item['value'])) {
      if (!empty(
$allowed_values) && !isset($allowed_values[$item['value']])) {
       
$errors[$field['field_name']][$langcode][$delta][] = array(
         
'error' => 'list_illegal_value',
         
'message' => t('%name: illegal value.', array('%name' => t($instance['label']))),
        );
      }
    }
  }
}
?>
Files: 
CommentFileSizeAuthor
#29 1180992-optgroup-validation-29.patch3.89 KBjorgegc
PASSED: [[SimpleTest]]: [PHP 5.4 MySQL] 65,304 pass(es).
[ View ]
#27 dropdown2.png109.53 KBprateek479
#25 1180992-optgroup-validation-24.patch3.89 KBsaki007ster
PASSED: [[SimpleTest]]: [MySQL] 63,145 pass(es).
[ View ]
#24 1180992-optgroup-validation-24.patch643.74 KBsaki007ster
PASSED: [[SimpleTest]]: [MySQL] 63,136 pass(es).
[ View ]
#19 1180992-optgroup-validation-19.patch2.78 KBcristiroma
FAILED: [[SimpleTest]]: [MySQL] 58,581 pass(es), 3 fail(s), and 0 exception(s).
[ View ]
#19 interdiff-1180992-18-19.txt2.04 KBcristiroma
#18 1180992-optgroup-validation-18.patch1.35 KBcristiroma
FAILED: [[SimpleTest]]: [MySQL] 58,647 pass(es), 3 fail(s), and 0 exception(s).
[ View ]
#15 1180992-optgroup-validation-15.patch1.45 KBToRum
PASSED: [[SimpleTest]]: [MySQL] 55,842 pass(es).
[ View ]
#13 1180992-optgroup-validation-13.patch1.37 KBToRum
PASSED: [[SimpleTest]]: [MySQL] 55,922 pass(es).
[ View ]
#10 1180992-optgroup-validation.patch844 bytesbleen18
FAILED: [[SimpleTest]]: [MySQL] 55,639 pass(es), 37 fail(s), and 16 exception(s).
[ View ]
#7 1180992-optgroup-validation-7.patch905 bytesToRum
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1180992-optgroup-validation-7.patch. Unable to apply patch. See the log in the details link for more information.
[ View ]
#1 1180992-optgroup-validation.patch838 bytesbleen18
PASSED: [[SimpleTest]]: [MySQL] 33,808 pass(es).
[ View ]

Comments

Version:7.x-dev» 8.x-dev
Status:Active» Needs review
StatusFileSize
new838 bytes
PASSED: [[SimpleTest]]: [MySQL] 33,808 pass(es).
[ View ]

I dont think there is anything hackey about your approach at all...

This bug should be fixed first (or concurrently) in d8. Here is a patch for d8 that uses your approach.

Assigned:Unassigned» chimericdream

Assigned:chimericdream» Unassigned

Sorry. Didn't mean to assign this to myself. Removing assignment.

Patch in #1 (https://drupal.org/files/1180992-optgroup-validation.patch) works fine for me (Drupal 7). Can it be added to a following release of Drupal 7?

StatusFileSize
new905 bytes
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1180992-optgroup-validation-7.patch. Unable to apply patch. See the log in the details link for more information.
[ View ]

Update: patch #1 became obsolete as source code has changed in the meanwhile. The following updated patch works fine for me.

Status:Needs review» Needs work

The last submitted patch, 1180992-optgroup-validation-7.patch, failed testing.

Update: patch in #7 is the backport for D7. That's why the test failed.

Status:Needs work» Needs review
StatusFileSize
new844 bytes
FAILED: [[SimpleTest]]: [MySQL] 55,639 pass(es), 37 fail(s), and 16 exception(s).
[ View ]

ToRum, the D8 version needs to go in before the D7 version will be considered...

This is a re-roll for D8

...ToRum. The best thing you can do to keep the wheels moving so this can get into D7 would be to test out the patch in #10 on D8 and (assuming all is well) mark this issue as RTBC.

Status:Needs review» Needs work

The last submitted patch, 1180992-optgroup-validation.patch, failed testing.

StatusFileSize
new1.37 KB
PASSED: [[SimpleTest]]: [MySQL] 55,922 pass(es).
[ View ]

Patch #10 failed because options_array_flatten() does not exist and passed parameters of list_allowed_values() were wrong. New patch for D8 attached.

Status:Needs work» Needs review

StatusFileSize
new1.45 KB
PASSED: [[SimpleTest]]: [MySQL] 55,842 pass(es).
[ View ]

Patch #13 contained a duplicate line (for $allowed_values = ...). It is removed in this new version.

Issue tags:+Needs tests

This probably needs a quick test

Status:Needs review» Needs work

StatusFileSize
new1.35 KB
FAILED: [[SimpleTest]]: [MySQL] 58,647 pass(es), 3 fail(s), and 0 exception(s).
[ View ]

Re-roll the code work with the current HEAD. Still needs the tests implemented.

Status:Needs work» Needs review
StatusFileSize
new2.04 KB
new2.78 KB
FAILED: [[SimpleTest]]: [MySQL] 58,581 pass(es), 3 fail(s), and 0 exception(s).
[ View ]

Changes:
1. Added a test case that checks the function options_array_flatten
2. Fixed code phpdoc

Status:Needs review» Needs work

The last submitted patch, 1180992-optgroup-validation-19.patch, failed testing.

Assigned:Unassigned» mikegoodwin

re-rolling

Assigned:mikegoodwin» Unassigned
Issue summary:View changes
Issue tags:+Needs reroll

feel free to jump in to do the reroll anytime. https://drupal.org/contributor-tasks/reroll

Assigned:Unassigned» saki007ster

Status:Needs work» Needs review
StatusFileSize
new643.74 KB
PASSED: [[SimpleTest]]: [MySQL] 63,136 pass(es).
[ View ]

re-rolling this patch.

StatusFileSize
new3.89 KB
PASSED: [[SimpleTest]]: [MySQL] 63,145 pass(es).
[ View ]

Sorry , earlier patch was my stupidity. Replaced it with new one.

Assigned:saki007ster» Unassigned

StatusFileSize
new109.53 KB

Select list working fine

Issue tags:-Needs reroll

patch currently applies.

StatusFileSize
new3.89 KB
PASSED: [[SimpleTest]]: [PHP 5.4 MySQL] 65,304 pass(es).
[ View ]

Re-rolling patch in #25

Just looked for the +Needs reroll tag and couldn't find it... I guess I've just rerolled a patch that applies LOL, my bad!