I have 2 dropdown select lists. The first a kanban process and the second a kanban step. When i select a kanban process the second dropdown should change based on the kanban process. But when i do i get an error: "An illegal choice has been detected. Please contact the site administrator."

<?php
function kanban_form_kanban_task_node_form_alter(&$form, &$form_state, $form_id) {
   
$options_step = $form['field_kanban_step_ref']['und']['#options'];
    if(
$form)
   
$form['field_kanban_process']['und']['#ajax'] = array(
           
'event' => 'change',
           
'callback' => 'ajax_dependent_dropdown_callback',
           
'wrapper' => 'dropdown-second-replace',
           
'method' => 'replace',
    );
   
$form['field_kanban_step_ref']['und']['#prefix'] = '<div id ="dropdown-second-replace">';
   
$form['field_kanban_step_ref']['und']['#suffix'] = '</div>';
   
$form['field_kanban_step_ref']['und']['#options'] = $options_step;
}
function
ajax_dependent_dropdown_callback($form, $form_state) {
   
$process = $form['field_kanban_process']['und']['#value'];
   
$form['field_kanban_step_ref']['und']['#options'] = get_step_reference($process);
    return
$form['field_kanban_step_ref'];
}
function
get_step_reference($kanban) {
$result = db_query('Select n.entity_id FROM {field_data_field_kanban_process_ref} n WHERE n.field_kanban_process_ref_target_id = :field_kanban_process_ref_target_id', array(':field_kanban_process_ref_target_id' => $kanban));
    foreach(
$result as $record) {
        
$entity_id[] = $record->entity_id;
    }
    foreach(
$entity_id as $id) {
       
$result2 = db_query('Select t.title FROM {node} t WHERE t.nid = :nid', array(':nid' => $id));
            foreach(
$result2 as $record2) {
               
$title[] = $record2->title;
            }
    }
    return
$title;
}
?>

Comments

<?php
function ajax_dependent_dropdown_callback($form, $form_state) {
   
$process = $form['field_kanban_process']['und']['#value'];
   
$form['field_kanban_step_ref']['und']['#options'] = get_step_reference($process);
    return
$form['field_kanban_step_ref'];
}
?>

Two problems:

1) You are changing the $form element in your ajax callback above. This is causing the error you are seeing. Th only thing you should be doing in this function is returning the part of the form that should be inserted into the existing form. So everything in the above function that isn't part of the return statement should be part of your form definition.

2) You need to render the content that you return, using render().

Jaypan
Our newest Drupal site: PacificAikido.com (Drupal showcase)

Could you demonstrate how i could do that?

If you download the examples module, there is an ajax example in there. That will show you how to do it.

Jaypan
Our newest Drupal site: PacificAikido.com (Drupal showcase)

It should be mentioned that this dependent dropdown is going to be used in the function hook_form_alter()

I have looked at the example. But i'm totally frustrated now. Could you please show me how do it?

It's fine that it's in hook_form_alter(). That doesn't make a difference.

Here's an example:

<?php
function my_form($form, &$form_state)
{
 
$form['location'] = array
  (
   
'#prefix' => '<div id="location_wrapper">',
   
'#suffix' => '</div>',
  );
 
$form['location']['country'] = array
  (
   
'#type' => 'select',
   
'#title' => t('Country'),
   
'#options' => array
    (
     
'' => '---',
     
'canada' => t('Canada'),
     
'japan' => t('Japan'),
    ),
   
'#ajax' => array
    (
     
// Wrapper set in $form['location']
     
'wrapper' => 'location_wrapper',
     
// Callback function to be shown later
     
'callback' => 'my_ajax_callback',
    );
  );
 
// The next part will only be entered if a country is selected,
  // ie - during the AJAX callback
 
if(isset($form_state['values']['country']) && in_array($form_state['values']['country'], array('canada', 'japan')))
  {
    if(
$form_state['values']['country'] === 'canada')
    {
     
$cities= array
      (
       
'' => '---',
       
1 => t('Vancouver'),
       
2 => t('Montreal'),
      );
    }
    else
    {
    
$cities= array
      (
       
'' => '---',
       
1 => t('Tokyo'),
       
2 => t('Yokohama'),
      );
    }
   
$form['location']['city'] = array
    (
     
'#type' => 'select',
     
'#title ' => t('City'),
     
'#options' => $cities,
    );
  }
}
// Ajax callback
function my_ajax_callback($form, &$form_state)
{
  return
render($form['location']);
}
?>

As you can see, any alterations to the form are done in the form definition, as explained in the comments. In the ajax callback, I have only returned the section to be rendered, and I rendered it using render().

Jaypan
Our newest Drupal site: PacificAikido.com (Drupal showcase)

Now it works fine. It populates the right things. But the selected is not saved inside the field_kanban_step_ref. How can i do this?

<?php
function kanban_form_kanban_task_node_form_alter(&$form, &$form_state, $form_id) {
   
//$form['field_kanban_process']['#tree'] = true;
   
$form['field_kanban_process']['und']['#ajax'] = array(
           
'event' => 'change',
           
'callback' => 'ajax_dependent_dropdown_callback',
           
'wrapper' => 'dropdown-second-replace',
           
'method' => 'replace',
    );
   
$form['field_kanban_step_ref']['und']['#prefix'] = '<div id ="dropdown-second-replace">';
   
$form['field_kanban_step_ref']['und']['#suffix'] = '</div>';
    if(isset(
$form_state['values']['field_kanban_process'])) {
   
$process = $form_state['values']['field_kanban_process']['und'][0]['target_id'];
        if(
strstr($process, '14')) {
           
$options_step get_step_reference(14);
        }
        else if(
strstr($process, '39')){
          
$options_step = get_step_reference(39);
        }
        else {
           
$options_step = array(
               
'' => '- None -',
            );
        }
   
$form['field_kanban_step_ref']['und']['#options'] = $options_step;
    }
}
function
ajax_dependent_dropdown_callback($form, &$form_state) {
    return
render($form['field_kanban_step_ref']);
}
function
get_step_reference($kanban) {
   
$result = db_query('Select n.entity_id FROM {field_data_field_kanban_process_ref} n WHERE n.field_kanban_process_ref_target_id = :field_kanban_process_ref_target_id', array(':field_kanban_process_ref_target_id' => $kanban));
    foreach(
$result as $record) {
        
$entity_id[] = $record->entity_id;
    }
   
$title = array();
   
$title[''] = '- None -';
    foreach(
$entity_id as $id) {
       
$result2 = db_query('Select t.title FROM {node} t WHERE t.nid = :nid', array(':nid' => $id));
            foreach(
$result2 as $record2) {
               
$title[$record2->title] = $record2->title;
            }
    }
    return
$title;
}
?>

It looks like you have set up your ajax properly, which will let the user select a value from the options you give. The next thing you need to do is to attach a submit function to be called after the form is submitted. You can add your submit function to the $form element's #submit array, and it will be called after any existing submit callbacks:

<?php
function my_module_form_alter(&$form, &$form_state, $form_id)
{
 
// Rest of form not shown
 
if($form_id === 'my_form_id')
  {
    
$form['#submit'][] = 'my_submit_function';
  }
}
function
my_submit_function($form, &$form_state)
{
 
// The value submitted to your #ajax form element
  // is part of the $form_state['values'] array. You can
  // take care of saving it to the database or whatever, here.
}
?>

Jaypan
Our newest Drupal site: PacificAikido.com (Drupal showcase)