I use jQuery to alter the exposed form select options. Got error: "An illegal choice has been detected." How to bypass validation? I have a view that has three expose filters (Manufacturer, Type, Model), three options list (term reference to Printer vocabulary) .

Vocabulary: Printer (3 levels) 

-- HP           
---- xxx     
------ xxxx  
-- Apple
---- xxxx
------ xxxxxx
-- Dell
---- xxxx
------- xxxxx
-- ...
-- ...
(thousands of terms)


Since Form API AJAX doesn't work on views expose form, I am unable to make the them dependent select for exposed form fields. So I used jQuery to make the exposed form fields "dependent select / cascading select".



Basically, I empty all the options in views_exposed_form_alter() firstly:

$form['manufacturer_id']['#options'] = $form['type_id']['#options'] = $form['model_id']['#options'] = array();


then populate the option lists with my jQuery code accordingly.

However I get "An illegal choice has been detected." on page load, and form submit. 
Form submission is prevented due to Drupal form validation mechanism .



It's the form validation detect the options generated by jQuery are not come with the original form data, as I removed the options in form alter. Value of a select box is not present in its defined options .

So I tried to remove form validation in form alter as:

unset($form['#validate']);


still doesn't work, the illegal choice error remains.

============ UPDATED =================

Inspired by @kiamlaluno 's answer below, the only solution I came up is hack/patch the core. 
Here is what I done:

Edited /includes/form.inc : (line 2014)



I removed the code:

$element['#needs_validation'] = TRUE;


and added:

// if not these fields, mark for validation as usual. 
// so if are these fields, validation will be passed. 

if ($element['#name'] != 'manufacturer_id'  &amp;&amp; 
    $element['#name'] != 'type_id'          &amp;&amp; 
    $element['#name'] != 'model_id' ) {

  $element['#needs_validation'] = TRUE;
}


It works, the exposed form select option bypassed the validation. 

But my solution is very ugly which modified the core. 

I wonder if there is any other solution without touching the core?
How can I bypass the validation of these exposed form fields?

Thanks!
The function that shows those errors is _form_validate(), which contains the following code.

  // Validate the current input.
  if (!isset($elements['#validated']) || !$elements['#validated']) {
    // The following errors are always shown.
    if (isset($elements['#needs_validation'])) {

      // ...

      if (isset($elements['#options']) &amp;&amp; isset($elements['#value'])) {
        if ($elements['#type'] == 'select') {
          $options = form_options_flatten($elements['#options']);
        }
        else {
          $options = $elements['#options'];
        }
        if (is_array($elements['#value'])) {
          $value = in_array($elements['#type'], array('checkboxes', 'tableselect')) ? array_keys($elements['#value']) : $elements['#value'];
          foreach ($value as $v) {
            if (!isset($options[$v])) {
              form_error($elements, $t('An illegal choice has been detected. Please contact the site administrator.'));
              watchdog('form', 'Illegal choice %choice in !name element.', array('%choice' =&gt; $v, '!name' =&gt; empty($elements['#title']) ? $elements['#parents'][0] : $elements['#title']), WATCHDOG_ERROR);
            }
          }
        }

        // ...
      }


The function is always executed, whenever the form has a validation handler, or not.

You could set $form['#needs_validation'] to FALSE, but _form_builder_handle_input_element() sets it to TRUE. The function is called from form_builder(), which is then called from drupal_process_form(), or drupal_rebuild_form().

  // Mark all posted values for validation.
  if (isset($element['#value']) || (!empty($element['#required']))) {
    $element['#needs_validation'] = TRUE;
  }


After _form_builder_handle_input_element() is called, form_builder() calls any #process function set for the form element.

  // Handle input elements.
  if (!empty($element['#input'])) {
    _form_builder_handle_input_element($form_id, $element, $form_state);
  }
  // Allow for elements to expand to multiple elements, e.g., radios,
  // checkboxes and files.
  if (isset($element['#process']) &amp;&amp; !$element['#processed']) {
    foreach ($element['#process'] as $process) {
      $element = $process($element, $form_state, $form_state['complete form']);
    }
    $element['#processed'] = TRUE;
  }


It also calls any #after_build functions set for the form element.

  // The #after_build flag allows any piece of a form to be altered
  // after normal input parsing has been completed.
  if (isset($element['#after_build']) &amp;&amp; !isset($element['#after_build_done'])) {
    foreach ($element['#after_build'] as $function) {
      $element = $function($element, $form_state);
    }
    $element['#after_build_done'] = TRUE;
  }


You could set a #after_build function that executes code similar to the following one.

function mymodule_remove_validation($form_element) {
  unset($form_element['#needs_validation']);

  return $form_element;
}


I am using unset($form_element['#needs_validation']) because the if-statement in _form_validate() checks isset($elements['#needs_validation']), instead of !empty($elements['#needs_validation']). 

In this way, the form element would not have #needs_validation set to TRUE, and Drupal would not check the returned value for the form element is one of the possible values it can get, nor is the length of a textfield string longer than required.
It doesn't avoid the form validation handlers are run, thought.