Skip to main content

Creating an AJAX callback for User Reference fields

Front-end Development
Back-end Development
Drupal

Pre-filling form fields

Lets say you want to pre-fill some data on your form or node based off of a user reference field and the data associated with that user. To do this we'll be spending some time with the hook_form_alter callback. In this example we will be addressing the following use case: Node form has a User reference field, and we want to populate shipping fields with data from the user profile that has been referenced in the User Reference field. Doing this turned out a little differently than I had expected initially from just a standard form AJAX callback since the callback won't be upon submission but only when the User Reference field has been populated. We're going to have to add an extra step (the AJAX callback button) that we'll see below for this to work.

Setup

function mymodule_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'id_of_our_form') {
    $form['user_replace'] = array(
      '#title' => t("User Information"),
      '#prefix' => '<div id="node_name_form_group_cs">',
      //name of the node form (already existing, if you're modifying an existing node form)
      #suffix' =>'</div>',

    $form['user_replace']['user_copy'] = array(
      '#type' => 'button',
      '#value' => 'refresh',
      '#ajax' => array(
        'event'=>'click',
        'callback' =>'vip_proof_ajax_callback',
        'wrapper' => 'node_name_form_group_cs',
      ),
    );

Here we've setup the basic components of our form, defining the limits of our form, as well as creating our ajax callback button. To be very clear

$form['user_replace']['user_copy']

is used because it places our user_copy (ajax callback) button within the ['user_replace'] form element that we'll be using to group elements together for our AJAX callback to work.

Modifying an existing form

Since we're modifying an existing node form in this example, we'll need to unset the current fields and replace them within our own custom grouping ['user_replace'] for our ajax callback:

//redefine existing form elements since the exist on the node already
  $form['user_replace']['field_customer'] = $form['field_customer'];
  unset($form['field_customer']);
  $form['user_replace']['field_user_firstname'] = $form['field_user_firstname'];
  unset($form['field_user_firstname']);
  $form['user_replace']['field_last_name_shipping'] = $form['field_last_name_shipping'];
  unset($form['field_last_name_shipping']);
  $form['user_replace']['field_user_phone'] = $form['field_user_phone'];
  unset($form['field_user_phone']);
  $form['user_replace']['field_email_address'] = $form['field_email_address'];
  unset($form['field_email_address']);

Grabbing the UID from the User Reference field

We're going to want to grab the UID from the user reference field before the form is submitted, so we will use $form_state instead of $form. We will check to see if our User Reference field (field_customer) has been filled, if so we will grab the UID in order to load our user.

//check if UID has been autofilled
if(isset($form_state['input']['field_customer'][LANGUAGE_NONE][0]['uid'])) {
//grabs the UID from the field
  $uid = isset($form_state['values']['field_customer'][LANGUAGE_NONE][0]['uid']) ? $form_state['values']['field_customer'][LANGUAGE_NONE][0]['uid'] : '';
  //load the user
  $user = user_load($uid);

Note: We used a ternary for our $uid variable so that if the $uid is not set we won't have any undefined index warnings.

Set our variables

Now we'll set our variables so that if they're set on the user profile, we'll grab them and then place them into our node form:

//what we'll replace the fields with
$first = isset($user->field_user_firstname[LANGUAGE_NONE][0]['value']) ? $user->field_user_firstname[LANGUAGE_NONE][0]['value'] : '';
$last = isset($user->field_user_lastname[LANGUAGE_NONE][0]['value']) ? $user->field_user_lastname[LANGUAGE_NONE][0]['value'] : '';
$phone = isset($user->field_user_phone[LANGUAGE_NONE][0]['value']) ? $user->field_user_phone[LANGUAGE_NONE][0]['value'] : '';
$email = isset($user->mail) ? $user->mail : '';

Replacing the form inputs with our new variables

//replaces the old values if they've been set already
if (!empty($form_state['values']['field_user_firstname'])) {
  unset($form_state['input']['field_user_firstname'][LANGUAGE_NONE][0]['value']);
  $form_state['input']['field_user_firstname'][LANGUAGE_NONE][0]['value'] = $first;
  }
if (!empty($form_state['values']['field_last_name_shipping'])) {
  unset($form_state['input']['field_last_name_shipping'][LANGUAGE_NONE][0]['value']);
  $form_state['input']['field_last_name_shipping'][LANGUAGE_NONE][0]['value'] = $last;
  }
if (!empty($form_state['values']['field_user_phone'])) {
  unset($form_state['input']['field_user_phone'][LANGUAGE_NONE][0]['value']);
  $form_state['input']['field_user_phone'][LANGUAGE_NONE][0]['value'] = $phone;
  }
if (!empty($form_state['values']['field_email_address'])) {
  unset($form_state['input']['field_email_address'][LANGUAGE_NONE][0]['value']);
  $form_state['input']['field_email_address'][LANGUAGE_NONE][0]['value'] = $email;
  }
 return $form;
}

Here we're going to unset whatever may have been input already in the field, then place our new value into the field. This is done so that any existing values will be replaced if they've already been pre filled, for example if you called in the wrong user and need to make some modifications, it'll replace those old values with our new values that match the user.

AJAX

Now that we have our logic aside, we'll have to implement our ajax callback, to do so we'll define our ajax to match what we have already input in our form above:

function user_replace_ajax_callback($form, &$form_state) {
  return $form['user_replace'];
}

If you test this on your form you should see a button. If you fill out the user reference field and press the button, it should fill in all of that information into your form. Great! But what if you want that all to be done automatically? We'll run some javascript that will do this for us, first create a new file 'mymodule.js' and place the following into it:

(function($) {

  Drupal.behaviors.userReplaceBinding = {
    attach : function(context, settings) {
      $('#edit-user-copy').hide();
      $('input#edit-field-customer-und-0-uid', context).blur(invokeRefresh);
    }
  };

  function invokeRefresh() {
    $('#edit-user-copy').click();
  }
})(jQuery);

Here we've hidden our button, and then attached a behavior so when the UID field has been filled in, our invokeRefresh function will be called which will click our ajax button and populate our form fields.

Next hide the button with a

#edit-user-copy {display: none;}

in your form CSS.

Note that there may be differences in your div ID's depending on how you've setup your node field names, so be sure to check to make sure your field names match the fields in your drupal configuration as the will likely be different then what I've included here in this example.