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!

<?php /** * 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.