0

UPDATE: the code is now cleaner and shorter. An autocomplete field triggers the ajax callback which reloads a field. The whole thing works for one field but not so well for multiple fields.

function my_module_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'form_id_form') {
$form['triggering_field_id'][LANGUAGE_NONE][0]['value'] += array(
    '#autocomplete_path' => 'my_auto_path',
    '#ajax' => array(
        'callback' => 'my_ajax_callback',
            'wrapper' => 'my_ajax_wrapper',
            'method' => 'replace',
            'effect' => 'fade',
        ),
    );

    $form['dependant_field1'] += array(
        '#prefix' => '<div id="my_ajax_wrapper">',
    );
    $form['dependant_field2'] += array(
        '#suffix' => '</div>',
    );
  }
}

function my_module_menu() {
    $items = array();

    $items['my_auto_path'] = array(
        'title' => '',
        'page callback' => '_my_auto_path',
        'access arguments' => array('access content'),
        'type' => MENU_CALLBACK,
    );

    return $items;
}

function _my_auto_path($string) {
  $string = array(':s' => $string . '%');

  if ($string) {
    $results = db_query("SELECT name FROM {users} WHERE name LIKE :s", $string);

    $items = array();
    foreach ($results as $result) {
        $items[$result->name] = $result->name;
    }
    print drupal_json_encode($items);
  }
}

function my_ajax_callback(&$form, &$form_state) {
    if (user_load_by_name($form_state['values']['triggering_field_id'][LANGUAGE_NONE][0]['value']) != FALSE) {
        $user_obj = user_load_by_name($form_state['values']['triggering_field_id'][LANGUAGE_NONE][0]['value']);
        $user_id = $user_obj->uid;
        //let's get another field from user's object:
        //$user_whatever_userfield = $user_obj->whatever;

        $form['dependant_field1'][LANGUAGE_NONE][0]['value']['#value'] = $user_id;
        //Do the same for the 2nd field but need to return both fields at the same time...
        //$form['dependant_field2'][LANGUAGE_NONE][0]['value']['#value'] = $user_whatever_userfield;
        return $form['dependant_field1'];

        //another way, with ajax commands:
        //but I can only replace the whole <input> instead of just the val() of each field.
        //$commands = array();
        //$commands[] = ajax_command_replace("#dependant_field1_id", $user_id);
        //$commands[] = ajax_command_replace("#dependant_field2_id", $user_whatever_userfield);
        //return array('#type' => 'ajax', '#commands' => $commands);
    }
}
  • You would need a jQuery script that will watch the autocomplete field for changes, and then run script to fetch the rest of the user data from user object (via a AJAX call) and then fill in the values of the other fields. – Quentin Campbell Nov 21 '13 at 13:52
  • That's the logic behind what I want to do. But I want to do it the Drupal way and I need more information on that exact path. – webmaniac Nov 21 '13 at 14:32
  • That is the Drupal way using custom scripts :). I doubt it you will find a module that will do what you need, but somebody could prove me wrong. – Quentin Campbell Nov 21 '13 at 15:20
  • Why do you need fields to be filled in? You can user user reference field (part of the reference module) then you can build display with Views to show fields from the node as well as the referenced user's fields. – Quentin Campbell Nov 21 '13 at 15:22
  • I need these fields to be filled in and stored when the form is submitted. There is no big explanation, the project I'm working on requires that. What do you mean build a view to show fields? I need these values being inserted live & automatically to the appropriate fields whenever a user is selected in the autocomplete field. – webmaniac Nov 21 '13 at 15:52
1

I just found the solution to my problem: Every AJAX command runs and replaces the defined element. The trick is to predefine the values for all fields I need to update, within the callback. Then, these values remain in tact within the array of the newly rendered fields using the AJAX commands. Here is my updated callback:

function my_ajax_callback(&$form, &$form_state) {
    if (user_load_by_name($form_state['values']['triggering_field_id'][LANGUAGE_NONE][0]['value']) != FALSE) {
        $user_obj = user_load_by_name($form_state['values']['triggering_field_id'][LANGUAGE_NONE][0]['value']);
        $user_id = $user_obj->uid;
        // and another user attribute:
        $user_whatever_userfield = $user_obj->whatever;

        $form['dependant_field1'][LANGUAGE_NONE][0]['value']['#value'] = $user_id;
        $form['dependant_field2'][LANGUAGE_NONE][0]['value']['#value'] = $user_whatever_userfield;

        $commands = array();
        $commands[] = ajax_command_replace("#dependant_field1_wrapper", render($form['dependant_field1']));
        $commands[] = ajax_command_replace("#dependant_field2_wrapper", render($form['dependant_field2']));
        return array('#type' => 'ajax', '#commands' => $commands);
    }
}

Also, I changed the position of my wrapper to have a wider range, in order to include all the fields I want to ajax-update. As every AJAX command will be recreating each form element, if the form element lives within a wrapper (added in form_alter), the wrapper will also be rendered and that causes an HTML mess. So having one hidden field above & another hidden field below my fields makes life easy. The new wrapper encloses these hidden fields and leaves all other fields clean when regenerated from the callback.

| improve this answer | |
0

As @Quentin Campbell said, "you would need a jQuery script that will watch the autocomplete field for changes, and then run script to fetch the rest of the user data from user object (via a AJAX call) and then fill in the values of the other fields."

The correct Drupal way to do it is to use the Drupal AJAX Framework. This framework will allow you to send a command to Drupal, receive the fields values and then in your JS you will fill the form fields.

| improve this answer | |
  • I tried to add '#ajax' parameters to the first field so it can trigger a callback that affects a following field. My thought is that it should be possible to load the user object within this callback and then place the elements I need to the corresponding following fields. But nothing seems to happen when the event that is supposed to trigger the callback is triggered. I added the above to my question, any piece of advice would be extremely helpful, thank you. – webmaniac Nov 29 '13 at 16:50
  • Updated the code, now cleaner & partially working. – webmaniac Dec 3 '13 at 12:52

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.