0

I have some slightly complicated ajax form logic that I'm struggling with.

I would like to replicate the following form conditions.

radio1 - always visible option1 option2 option3

radio2 - only visible if option 2 and 3 are selected in radio1 option1 option2 option3

select3 - only visible if option 1 is selected in radio1 contents of select list to be controlled by on options in radio2

Problems

when radio2 is changed it still fires the ajax function

when the form is submitted the select list uses the default option set rather than one that has been built from the selection radio2

Below is the code I have used following the ajax example from the examples module.

function uk_general_form_views_exposed_form_alter(&$form, &$form_state, $form_id) {
if($form['#id'] == 'views-exposed-form-documentation-search-page') {
if(!empty($form_state['values'])) {
  $form_state['input'] = array_merge($form_state['input'], $form_state['values']);      
}
$doc_type_options = $form['type']['#options'];    
$form['type'] = array(
  '#type' => 'radios',
  '#options' => $doc_type_options,
  '#title' => '',
);

$doc_line_options = $form['line']['#options'];
$line_selected = isset($form_state['values']['line']) ? $form_state['values']['line'] : key($doc_line_options);    
$form['line'] = array(
  '#type' => 'radios',
  '#options' => $doc_line_options,
  '#title' => '',
  '#ajax' => array(
    'callback' => 'uk_general_forms_documents_products',
    'wrapper' => 'products-dropdown-replace',
  ),      
  '#states' => array(
    'visible' => array(
      ':input[name="type"]' => array(
        array('value' => '29'),
        array('value' => '31'),
        ),
      ),
    'disabled' => array(
      ':input[name="type"]' => array('value' => '30'),
      ),
    ),
  );
$form['title'] = array(
  '#type' => 'select',
  '#prefix' => '<div id="products-dropdown-replace">',
  '#suffix' => '</div>',
  '#options' => _get_products($line_selected),
  '#states' => array(
    'visible' => array(
      ':input[name="type"]' => array('value' => '29'),
    ),
    'disabled' => array(
      ':input[name="type"]' => array(
        array('value' => '30'),
        array('value' => '31'),
      ),
    ),
  ),
);
}
}

function uk_general_forms_documents_products($form, $form_state){
  return $form['title'];
}

function _get_products($selected) {
  $product_query = new EntityFieldQuery;
  $product_query->entityCondition('entity_type', 'node')->entityCondition('bundle', 'product')->fieldCondition('field_line', 'tid', $selected)->propertyOrderBy('title', 'ASC');  
  $result = $product_query->execute();
  $product_nids = array_keys($result['node']);
  $products = entity_load('node', $product_nids);  
  $titles['All'] = '- Any -';
  foreach($products as $product) {
    $titles[$product->title] = $product->title;        
  }  
 return $titles;
}
0

i finally worked this one out, I strppied the form right back and removed all the states and got the ajax call working first. This was a bit of a hack as I had to access the $_GET variable directly and using the following line I was able to check whether or not the page had already been searched.

if(isset($_GET['line_2'])) {
  $line_2_selected = $_GET['line_2'];
}
else{
$line_2_selected = isset($form_state['values']['line_2']) ? $form_state['values']['line_2'] : key($doc_line2_options);
}

After this the problem was either having the ajax selectively removed ot depending on the values in the parent checkboxes. What I actually did was add the same list twice and then disable one or the other depending on the value in the first checkbox. Doing this greatly reduced the complexity of the states array.

$form['line'] = array(
  '#type' => 'radios',
  '#options' => $doc_line_options,
  '#default_value' => $line_selected,
  '#title' => '',
  '#prefix' => '<div id="lines-dropdown-replace">',
  '#suffix' => '</div>',
  '#states' => array(
    'enabled' => array(
      ':input[name="type"]' => array('value' => 31)
    ),
    'visible' => array(
      ':input[name="type"]' => array('value' => 31)
      ),
  ),
);

$form['line_2'] = array(
  '#type' => 'radios',
  '#options' => $doc_line2_options,
  '#default_value' => $line_2_selected,
  '#title' => '',
  '#prefix' => '<div id="lines-dropdown-replace">',
  '#suffix' => '</div>',      
  '#ajax' => array(
    'callback' => 'uk_general_forms_documents_products',
    'wrapper' => 'products-dropdown-replace',
    ),
  '#states' => array(        
    'enabled' => array(
      ':input[name="type"]' => array('value' => 29)
      ),
    'visible' => array(
      ':input[name="type"]' => array('value' => 29)
      ),
    )
  );

The previous ajax functions all worked as expected.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.