I would use 3 dependent selects using D7 Form Api #ajax. It almost works, that is, when I change the level 1 select, the level 2 is populated, then if I change the second one, the third is well populated.
But when I validate my form (ajax validation), if an error occurs (not related to the selects, just missing field, wrong value etc.), I return the whole form to display error messages. And in this case, the level 2 and level 3 select loose their options et selected value. And as the level 1 select keeps the selected value, I have to change it twice to polulate level 2 select again... not good.
I suppose I loose my selects options because the form is rebuild from cache, and the selects options are not in cache... So I'm doing something in the wrong way. Maybe related to selects or maybe related to form (maybe both !).
// Called when select level n change to populate select level n+1
// It does work, but in case of form rebuild, select level n+1 looses its
// options
function mymod_fiche_select_ajax_callback(&$form, &$form_state) {
// Get select caller
$sel1 = $form_state['triggering_element']["#name"];
// Get its value
$val1 = $form_state["input"][$sel1];
// Get an array to get the next select level
$info = mymod_var("select_ajax_$sel1");
$tab=$info["TAB"];
$col=$info["COL"];
$table=$info["TABLE"];
$fld=$info["FLD"];
$linkfld=$info["LINKFLD"];
$sel2=$info["SEL2"];
// Get the options form database
$options = mymod_get_fen($table, array($linkfld=>$val1));
// All my form are structured in tab/col
$form['mc'][$tab]['form_container'][$col][$sel2]['#options']=$options;
return $form['mc'][$tab]['form_container'][$col][$sel2];
}
// This function links two selects
function mymod_fiche_select_ajax(&$form, &$form_state,$sel1, $sel2,$table,$tab){
$linkfld=$sel1;
$fld=$sel2;
// Liste les colonnes (left/right)
$cols=array("left","right");
foreach($cols as $column){
if (isset($form['mc'][$tab]['form_container'][$column][$sel1])){
$formsel1 = &$form['mc'][$tab]['form_container'][$column][$sel1];
}
if (isset($form['mc'][$tab]['form_container'][$column][$sel2])){
$formsel2 = &$form['mc'][$tab]['form_container'][$column][$sel2];
$col=$column;
}
if (isset($formsel1) && isset($formsel2)){
break;
}
}
$wrapper="wrapper-$sel1-$sel2";
if (isset($formsel1) && isset($formsel2)){
$formsel1['#ajax'] = array(
'callback' => 'mymod_fiche_select_ajax_callback',
'wrapper' => $wrapper,
);
$formsel2['#prefix']=(isset($formsel2['#prefix']) ? $formsel2['#prefix']."<div id='$wrapper'>" : "<div id='$wrapper'>");
$formsel2['#suffix']=(isset($formsel2['#suffix']) ? "</div>".$formsel2['#suffix'] : "</div>");
// this will be get in the callback function
mymod_var("select_ajax_$sel1",array("TABLE"=>$table,"FLD"=>$fld,"TAB"=>$tab,"LINKFLD"=>$linkfld,"SEL2"=>$sel2,"COL"=>$col));
// sel1 initial value
if (isset($formsel1["#default_value"]) && $formsel1["#default_value"]!=""){
$options=mymod_get_fen($table, array($linkfld=>$formsel1["#default_value"]));
$formsel2["#options"]=$options;
/* select sample
$form['mc'][$tab]['form_container'][$column][$field] = array(
'#type' => 'select',
'#access' => $access,
'#title' => t($title),
'#options' => $options,
'#default_value' => $value,
'#required' => $required,
'#validated' => true,
'#attributes' => array("class"=>array()),
);*/
}
// Ajax validation function
function mymod_fiche_ajax(&$form, &$form_state){
// Save changes in database
$ret = mymod_query_form_save($form, $form_state);
if ($ret==0){ // No change detected..
return $form;
}
else if($ret==1) { // Changes saved without error
$commands = array();
$commands[] = ajax_command_invoke(NULL, 'fen_close');
return array(
'#type' => 'ajax',
'#commands' => $commands,
);
}
else{ // Errors detected, returning form to display messages
$form_state['rebuild'] = true;
return $form; // $ret contient la form + messages d'erreur
}
}
Thanks in advance.