Import form values from one form to another via AJAX

Drupal 7's new and improved Form API makes using AJAX a breeze. It enables you to add, replace, or remove form elements via AJAX without ever really having to get your hands dirty.

I recently had the opportunity to give it a whirl. Here's a the deal:
I have content type Resume and Profile2 type Job Seeker Profile. I'd like my users to be able to create up to 5 resumes, and I'd like them to have the option of importing information from their profile into their brand-spanking new resume. So, I'm going to create an 'Import from profile' button that will populate the resume fields with profile field values via AJAX.

Note: It is possible to accomplish something like this by setting default values via a token. However, in this case, I'd like to be able to import things like field collections, addresses, and fields with unlimited cardinality. Here's the code that accomplished it!

/**
* Implements hook_form_FORM_ID_alter().
* Resume node form.
*/
function grasmash_form_resume_node_form_alter(&$form, &$form_state, $form_id) {
// Load user's current profile.
$uid = $form['uid']['#value'];
$author = user_load($uid );
$profile = profile2_load_by_user($author, 'seeker_profile');

// Add button permitting users to import Work Experience from their Profile.
if (array_key_exists('und', $profile->field_work_experience)) { // It's good to first check that there's actually something to import.
// Wrapping the element with HTML lets us easily define the scope of the AJAX replacement later.
$form['field_work_experience']['#prefix'] = '

';
$form['field_work_experience']['#suffix'] = '

';

$form['field_work_experience']['import_work_experience'] = array(
'#type' => 'submit',
'#value' => 'Import work experience from your profile',
'#description' => t('This will overwrite anything you have entered into the Work Experience field!'),
'#weight' => -20,
'#attributes' => array('class' => array('field-add-more-submit')),
'#limit_validation_errors' => array(), // Don't validate when the button is clicked!
'#ajax' => array(
'callback' => 'grasmash_js_import_work_experience',
'wrapper' => 'field-work-experience-wrapper',
'effect' => 'fade',
'method' => 'replace',
),
);
}
}

/*
* Define AJAX return functions for Work Experience field.
*/
function grasmash_js_import_work_experience($form, $form_state) {
$field_collection = 'field_work_experience';
// Load the correct field collection using another function. This approach allows us to easily repeat this process with another field collection if desired.
$element = grasmash_js_import_field_collection($field_collection, $form, $form_state);
return $element;
}

/*
* Import pre-populated field_collection form element from a user's job seeker profile.
*/
function grasmash_js_import_field_collection($field_collection, &$form, &$form_state) {

// Load author profile if necessary.
$uid = $form['uid']['#value'];
$author = user_load($uid);

//module_load_include('inc', 'profile2_page', 'profile2_page'); // loading with hook_init instead
$profile2 = profile2_by_uid_load($uid, 'seeker_profile');
$profile2_form = entity_ui_get_form('profile2', $profile2, 'edit');

if (isset($profile2_form)) {
// Pull in corresponding form element from profile form.
$element = $profile2_form['profile_seeker_profile'][$field_collection];

// Process the imported element.
$element = grasmash_process_ajax_import($element);

return $element;
}

}

/**
* Recursively removes profile2 field prefixes from each array row.
* This ensures that all input names on the destination form are correct.
*/
function grasmash_process_ajax_import($element){
foreach ($element as $key => $value){
if (is_string($element[$key]) && !is_numeric($element[$key])){
$element[$key] = preg_replace('@(profile_seeker_profile){1}(\[){1}([^\]]+){1}(\]){1}@','$3$5', $element[$key]);
$element[$key] = str_replace('profile-seeker-profile-','', $element[$key]);
$element[$key] = str_replace('profile_seeker_profile_','', $element[$key]);
if ($element[$key] == 'profile_seeker_profile') {
unset($element[$key]);
}
}
elseif (is_array($element[$key])){
$element[$key] = grasmash_process_ajax_import($element[$key]);
}
}
return $element;
}
?>

Thanks for sharing!

Maybe you could achieve the same result with field_attach_form and filter out those that you don't need.

Pedro, I think that field_attach_form would work. Deciding to use it would probably depend on how many fields you'd like to import at once, and how closely the source and target forms match.

I haven't used field_attach_form yet, what happens when you attach a form from a source that contains fields which aren't present in the target? Do they get added or ignored?

Add new comment

Plain text

  • No HTML tags allowed.
  • Lines and paragraphs break automatically.