0

If I add new select field and define ajax, all works fine. Whereas if I attach #ajax to the existing select field it just does not work. (I can see ajax loader spining for a while and that is all.) I'm also getting error: "An illegal choice has been detected. Please contact the site administrator."

I'm suspecting my callback function is not correctly implemented. Is it valid to make changes to the form in the callback function?

function hook_form_alter(&$form, &$form_state, $form_id) {
    //...

        // add wrapper to existing select field
        $form['field_event_1_role']['und']['#prefix'] = '<div id="select-event-role">';
        $form['field_event_1_role']['und']['#suffix'] = '</div>';
        $form['field_event_1_role']['und']['#options'] = array('_none' => t(' - '));

        $events_list_options = array('1' => t('1'), '2' => t('2'));

        // **add new select field with ajax - This is working fine**
        $form['test_select_ajax'] = array(
            '#title' => t('Test select ajax'),
            '#type' => 'select',
            '#options' => $events_list_options,
            '#ajax' => array(
              'event'=>'change',
              'callback' =>'event_roles_ajax_callback',
              'wrapper' => 'select-event-role',
            ),
        );

        // **attach ajax to the existing select field - NOT working?!**
        $form['field_event_1']['und']['#options'] = $events_list_options;
        $form['field_event_1']['und']['#ajax'] = array( 
            'event'=>'change',
            'callback' =>'event_roles_ajax_callback',
            'wrapper' => 'select-event-role',
        );                  
    }

    // Ajax callback function
    function event_roles_ajax_callback($form, &$form_state) {
        $form['field_event_1_role']['und']['#options'] = array('populated' => t('populated'));
        return $form['field_event_1_role'];
    }

Additional info: The form I'm altering here is registration_form from Entity Registration module

  • what is the value of $events_list_options? – xurshid29 Dec 19 '13 at 5:31
  • It's an array. Just edited the code. – Antonio Dec 19 '13 at 5:46
  • please, look at this post: drupal.stackexchange.com/questions/96648/… I think you have the same problem. look at my answer in that post. – xurshid29 Dec 19 '13 at 5:55
  • Nope, it's not that! Note that both lists: $form['test_select_ajax'] and $form['field_event_1'] are using same settings. First one is working, the second one is not. This is just incredible! – Antonio Dec 19 '13 at 6:16
1

for this you can delete this line

$form['field_event_1_role']['und']['#options'] = array('_none' => t(' - '));

The problem is most likely because of a requirement for FAPI ajax which is documented, though can be easily missed:

Changes to the form must only be made in the form builder function (ajax_example_autocheckboxes() in the example here), or validation will fail. The callback function must not alter the form or any other state.

From AJAX Forms in Drupal 7.

The fact that you're setting the form element [#options] in the ajax callback is definitely a problem. The ajax callback should only return the array or HTML to be printed, not change the form. Only the return line should be in that callback.

The changes to your form should be made in the form_alter. Also, you should use the form_state array to check whether a value has been selected for your first dropdown. This will be updated during an AJAX request.

I recommend looking at the examples module, as well as these pages for more information on AJAX in FAPI. It can definitely be tricky.

  • No that cannot work! Devel says $form['field_event_1']['und']['#ajax'] is right. – Antonio Dec 19 '13 at 6:25
  • does devel themer module is enable in your site, it yes disable that,clear cache and temp file, run with your 'und' code. – madhurjya Dec 19 '13 at 6:26
  • I do not have devel themer module. – Antonio Dec 19 '13 at 6:44
  • see my edit on answer – madhurjya Dec 19 '13 at 11:03
0

Finally I got it working! Man this was a pain! Every bit of code is potentially a bomb.

Below is the code that is working:

function custom_form_alter(&$form, &$form_state, $form_id) {

    if ($form_id == 'registration_form' && $form['#bundle'] == 'free_registration_volunteer_call') {        

            $options_first = custom_first_dropdown_options();
            $value_field_event_1 = isset($form_state['values']['field_event_1']) ? $form_state['values']['field_event_1']['und'][0]['value'] : key($options_first);

            // Setup field_event_1 select and bind ajax
            $form['field_event_1']['und']['#options'] = $options_first;
            $form['field_event_1']['und']['#default_value'] = $value_field_event_1;
            $form['field_event_1']['und']['#ajax'] = array(
                    'event' => 'change',
                    'callback' => 'custom_ajax_callback',
                    'wrapper' => 'field_event_1_role_replace',
            ); 

            // Setup field_event_1_role select
            $form['field_event_1_role']['und']['#prefix'] = '<div id="field_event_1_role_replace">';
            $form['field_event_1_role']['und']['#suffix'] = '</div>';
            $form['field_event_1_role']['und']['#options'] = custom_second_dropdown_options($value_field_event_1);
            $form['field_event_1_role']['und']['#default_value'] = isset($form_state['values']['field_event_1_role']) ? $form_state['values']['field_event_1_role'] : '';

    }

}


/**
* Ajax callback for Event roles dropdown
*/
function custom_ajax_callback($form, $form_state) {
    return $form['field_event_1_role'];
}


/**
 * Helper function to populate the first dropdown.
 */
function custom_first_dropdown_options() {
    $node = node_load(arg(1));
    $i = 0;
    if(!empty($node->field_events_for_volunteering['und'])) {
        foreach ($node->field_events_for_volunteering['und'] as $event) {
            if (!$i) $events_list_options['_none'] = '- Select Event -';
            $events_list_options[(string)$event['node']->nid] = $event['node']->title;
            $i++;
        }
        return $events_list_options;
    }
}


/**
 * Helper function to populate the second dropdown.
 */
function custom_second_dropdown_options($key = '') {
    if ($key) {
        $node = node_load($key);
        $i = 0;
        if(!empty($node->field_volunteer_roles['und'])) {
            foreach ($node->field_volunteer_roles['und'] as $role) {
                if (!$i) $role_list_options['_none'] = '- Select Volunteer Role -';
                $role_list_options[(string)$role['value']] = $role['value'];
                $i++;
            }
            return $role_list_options;
        }
    }
    return array();
}

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.