1

I have dependent select list (dynamic dropdown) in my form. When I change a value of the first select list, the second select list is automatically pouplated using ajax callback. Both select fields are required! All works fine, except validation.

There are 3 scenarios when submiting form:

  1. If I do not change any values of my select lists (leaving default "- select -"), and just click submit button; page refreshes and displays message about required fields - This is working fine!
  2. If I set values in both lists, click submit, validation passes, form is saved - This is working fine as well!
  3. If I set value of just one select list and click submit button: BOOM! - All options from that select list are gone.

If I do dsm($form_state['values']) in validate function I can see that all values are set correctly.

Below is my code:

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'] : '';

            $form['#validate'][] = 'custom_form_validate';

    }

}


/**
* 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();
}


    /**
     * Validate form
     */
function custom_form_validate($form, &$form_state) {
    if (empty($form_state['values']['field_event_1']['und'][0]['value'])) {
        form_set_error('field_event_1', t('Event 1: field is required'));
    } 
    if (empty($form_state['values']['field_event_1_role']['und'][0]['value'])) {
        form_set_error('field_event_1_role', t('Role for event 1: field is required'));
    } 
    if (empty($form_state['values']['field_event_2']['und'][0]['value'])) {
        form_set_error('field_event_2', t('Event 2: field is required'));   
    } 
    if (empty($form_state['values']['field_event_2_role']['und'][0]['value'])) {
        form_set_error('field_event_2_role', t('Role for event 2: field is required'));
    }
    dsm($form_state['values']);
}

submit handler:

/**
* Custom Form Submit Handler (for free registration)
*/
function custom_form_submit(&$form, &$form_state){
    $registration_id = $form_state['build_info']['args'][0]->registration_id;
    entity_registration_custom_confirm_registration($registration_id); //Process registration - Set registration state to 'complete'
    $node = node_load(arg(1)); // Load current node
    $form_state['redirect'] = 'event/registration/success/' . $node->nid; // Redirect to success msg
}
  • 1.where is your submit callback? 2.If, after submission the values are being lost it's because of, you have if(!empty($node->field_events_for_volunteering['und'])) { and if ($key) { in your first and second select options' callbacks. You must be sure that after submission the select lists are receiving the values from that callbacks. Try to debug that functions also.. – xurshid29 Dec 21 '13 at 6:19
  • Just tried commenting out those if conditions you pointed out - No luck with that. – Antonio Dec 21 '13 at 6:39
  • did you debug the values of that functions? – xurshid29 Dec 21 '13 at 6:40
  • One more thing, check the form_id after validation fails.. Is it remaining as 'registration_form' or changes as registration_form_*? – xurshid29 Dec 21 '13 at 6:48
  • 1
    may be, arg(1) is not receiving a nid after the validation fails... – xurshid29 Dec 21 '13 at 7:07
1

I resolved this finally!

arg(1) returns ajax on ajax request, so I added:

$node_id = arg(1) == 'ajax' ? $form_state['build_info']['args']['0']->entity_id : arg(1);

There was another issue as well. For some strange reason node_load does not return all collections on ajax request. So I had to pull event's title using another node_load call in foreach loop.

This was not working:

/**
 * 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 -';
            // $event['node'] is NULL here on ajax request?!?!
            $events_list_options[(string)$event['node']->nid] = $event['node']->title;
            $i++;
        }
        return $events_list_options;
    }
}

So I replaced it with this:

/**
 * Helper function to populate the first dropdown.
 */
function custom_first_dropdown_options($node_id) {
    $node = node_load($node_id);
    $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 -';
            $node2 = node_load($event['nid']);
            $events_list_options[(string)$event['nid']] = $node2->title;
            $i++;
        }
        return $events_list_options;
    }
}

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.