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.
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:
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']))),
);
}
}
}
}
D7 backport: #1530486: [D7] list_field_validate() doesn't seem to accommodate select lists with <optgroup>
Comment | File | Size | Author |
---|---|---|---|
#33 | 1180992-33.patch | 3.88 KB | ravi.khetri |
#29 | 1180992-optgroup-validation-29.patch | 3.89 KB | jorgegc |
#27 | dropdown2.png | 109.53 KB | prateek479 |
#25 | 1180992-optgroup-validation-24.patch | 3.89 KB | saki007ster |
#24 | 1180992-optgroup-validation-24.patch | 643.74 KB | saki007ster |
Comments
Comment #1
bleen CreditAttribution: bleen commentedI 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.
Comment #2
cweagansUpdating tags per http://drupal.org/node/1517250
Comment #3
chimericdream CreditAttribution: chimericdream commentedBackported patch to D7.
See: https://drupal.org/node/1530486#comment-6463840
Comment #4
chimericdream CreditAttribution: chimericdream commentedSorry. Didn't mean to assign this to myself. Removing assignment.
Comment #5
Simon Georges CreditAttribution: Simon Georges commentedClosed #1012640: Support grouping in allowed values for select list as a duplicate of this one.
Comment #6
ToRum CreditAttribution: ToRum commentedPatch 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?
Comment #7
ToRum CreditAttribution: ToRum commentedUpdate: patch #1 became obsolete as source code has changed in the meanwhile. The following updated patch works fine for me.
Comment #9
ToRum CreditAttribution: ToRum commentedUpdate: patch in #7 is the backport for D7. That's why the test failed.
Comment #10
bleen CreditAttribution: bleen commentedToRum, the D8 version needs to go in before the D7 version will be considered...
This is a re-roll for D8
Comment #11
bleen CreditAttribution: bleen commented...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.
Comment #13
ToRum CreditAttribution: ToRum commentedPatch #10 failed because
options_array_flatten()
does not exist and passed parameters oflist_allowed_values()
were wrong. New patch for D8 attached.Comment #14
ToRum CreditAttribution: ToRum commentedComment #15
ToRum CreditAttribution: ToRum commentedPatch #13 contained a duplicate line (for
$allowed_values = ...
). It is removed in this new version.Comment #16
bleen CreditAttribution: bleen commentedThis probably needs a quick test
Comment #17
bleen CreditAttribution: bleen commentedComment #18
cristiroma CreditAttribution: cristiroma commentedRe-roll the code work with the current HEAD. Still needs the tests implemented.
Comment #19
cristiroma CreditAttribution: cristiroma commentedChanges:
1. Added a test case that checks the function options_array_flatten
2. Fixed code phpdoc
Comment #21
Anonymous (not verified) CreditAttribution: Anonymous commentedre-rolling
Comment #22
YesCT CreditAttribution: YesCT commentedfeel free to jump in to do the reroll anytime. https://drupal.org/contributor-tasks/reroll
Comment #23
saki007sterComment #24
saki007sterre-rolling this patch.
Comment #25
saki007sterSorry , earlier patch was my stupidity. Replaced it with new one.
Comment #26
saki007sterComment #27
prateek479 CreditAttribution: prateek479 commentedSelect list working fine
Comment #28
martin107 CreditAttribution: martin107 commentedpatch currently applies.
Comment #29
jorgegc CreditAttribution: jorgegc commentedRe-rolling patch in #25
Comment #30
jorgegc CreditAttribution: jorgegc commentedJust looked for the +Needs reroll tag and couldn't find it... I guess I've just rerolled a patch that applies LOL, my bad!
Comment #32
jhedstromEven though this patch still applies, it needs a reroll keeping this change in mind.
Comment #33
ravi.khetri CreditAttribution: ravi.khetri commentedRerolled.
Comment #34
dcam CreditAttribution: dcam commented#33 applies to HEAD. Removing the "Needs reroll" tag.
Comment #35
jOksanen CreditAttribution: jOksanen at Realityloop commentedWorks for me.
Comment #43
drummWe ran into this on Drupal.org with #315583: Group and sort version options on the issue form.
Comment #44
drumm(forgot the tag)
Comment #45
dwwNot clear why this and #1530486: [D7] list_field_validate() doesn't seem to accommodate select lists with <optgroup> are separate issues. Seems like that one is duplicate. But for now, at least prefixing them with core major version so we can tell them apart.
Comment #46
drummI believe the convention for core backports is a separate issue nowadays. This lets the issue credits be awarded for the versions it is resolved in as soon as it is fixed there. May be other benefits too.
Comment #47
xjmYep, we file a separate issue for backport to D7. The D7 and D8 maintainers agreed on that a few years back because the D8 patch usually does not even remotely resemble the D7 patch, so juggling them both on the same issue was very confusing. All they have to do nowadays is wait for commit on the D8 issue to ensure there's no regressions on upgrade.
Comment #49
catchhook_list_validate() no longer exists. The equivalent code is in ListItemBase::getPossibleValues(), which handles optgroups. Marking outdated.