0

I have created several custom elements in a module, which work great for grouping several controls in a single form field.

However, I now need to add one that contains a drop-down list. The idea is to have a drop-down list of country codes, and a text field for the phone number.

It displays correctly and looks good until the form is submitted, which results in the error, "An illegal choice has been detected. Please contact the site administrator." This would seem to indicate that Drupal isn't recognising the options as being part of the select control.

Here's my code:

function my_module_element_info() {
  $types = array(
    'phone' => array(
      '#input' => TRUE,
      '#process' => array('my_module_phone_process'),
      '#element_validate' => array('my_module_phone_validate'),
      '#autocomplete_path' => FALSE,
      '#theme_wrappers' => array('my_module_inline_form_element'),
    ),
  );
  return $types;
}

function my_module_phone_process($element, &$form_state, $complete_form) {
  $element['#tree'] = TRUE;

  $element['prefix'] = array(
    '#type' => 'select',
    '#value' => $element['#value']['prefix'] ,
    '#options' => $element['#options'],
    '#required' => $element['#required'],
  );
  $element['number'] = array(
    '#type' => 'textfield',
    '#size' => 20,
    '#maxlength' => 40,
    '#value' => $element['#value']['number'],
    '#required' => $element['#required'],
  );
  if (isset($element['#attributes'])) {
    $element['prefix']['#attributes'] = $element['#attributes'];
    $element['number']['#attributes'] = $element['#attributes'];
  }
  $element['prefix']['#attributes']['class'][] = 'form-phone-prefix';
  $element['number']['#attributes']['class'][] = 'form-phone-number';
  if (isset($element['#ajax'])) {
    $element['prefix']['#ajax'] = $element['#ajax'];
    $element['number']['#ajax'] = $element['#ajax'];
  }

  return $element;
}

function my_module_phone_validate($element) {
  if (!preg_match('/^[0-9 ]+$/', $element['#value']['number'])) {
    form_error($element['number'], t('Phone number may contain only digits and spaces.'));
  }
  return $element;
}

Any help getting this working would be greatly appreciated.

Thanks for looking.

James

James Shields
  • 309
  • 4
  • 12
  • I've been digging in the Drupal core, and the Date control is constructed in a very similar manner, so I don't think I'm too far off. Just can't see where the error is coming from. – James Shields Nov 25 '12 at 10:06

2 Answers2

0

you can add the following attribute to the element causing this error.

'#validated' => TRUE,
Waqas
  • 51
  • 2
  • 2
  • Thanks for the suggestion! This did suppress the error I was getting. Unfortunately it also disabled all validation of the field. – James Shields Feb 16 '13 at 16:32
0

This problem got parked on the back burner for a while, but I got back to it this week.

I think I now understand the reason for the error. If an element has a "#options" property, it is expected to behave like a select control, and one of the options should be submitted. As the field itself is a container for other controls, so has no input directly, there is no posted value matching an entry in "#options" so Drupal flags it as an invalid form submission.

After a lot of trial and error, I hit on something very simple. The "#options" are used to populate the child control, but once it's been populated, they are no longer needed on the parent. So I added a "#after_build" function to the element, and used it to remove the "#options", and it worked perfectly.

function common_pricing_phone_after_build($element, &$form_state) {
    unset($element['#options']);
    return $element;
}
James Shields
  • 309
  • 4
  • 12