How to pre-populate multiple "field collection" fields in node form I'm building a multistep node add form where you upload a zip of files on page 1, let the module read file names into an array when the uploader presses the "next" button, and then allows the uploader to enter some meta info for each file on page 2. I have set up the field collection "field_files" to hold info for each file.

However, I can't seem to figure out how to generate the field collection form code for page 2. I would like it to be pre-populated with one field collection entry for each file. I've been reading module source code and huge var_dumps all day without getting anywhere. Does anyone know if this is even possible, and if it is, what would be the best way to do it?
After hours of debugging I found a good working solution to pre populate fields in field collections. (see Drupal forum)

So whats the plan?


  Manually generate a node-add form for the desired bundle.
  Change the form state of the generated form and set the desired number of fields you want to pre-populate.
  Rebuild the node-add form with the new form state values.
  Use hook_form_alter() to pre-populate values.


Ok. So lets assume we have a bundle called bundle_with_unlimited_fc which belongs to the node entity type. Furthermore all our custom code will reside in our module named my_module.

We can use hook_menu_alter() to define a new page callback. Everytime a new bundle_with_unlimited_fc is added Drupal will call now this function.

function my_module_menu_alter(&amp;$items) {
  $items['node/add/bundle_with_unlimited_fc']['page callback'] = 'my_module_build_form';
}


Now definde our form builder function. Notice the function argument which comes from the Drupal implementation of our altered menu item.

function my_module_build_form($type) {
  // get the standard node form;
  // we cannot get it from drupal_get_form() because we need the form_state reference,
  // so we copy a bit of code from node_add() and drupal_get_form()
  global $user;
  $form_id = 'bundle_with_unlimited_fc_node_form';
  $form_state = array();
  $form_state['build_info']['args'][] = (object) array(
    'uid' =&gt; $user-&gt;uid,
    'name' =&gt; (isset($user-&gt;name) ? $user-&gt;name : ''),
    'type' =&gt; $type,
    'language' =&gt; LANGUAGE_NONE
  );
  $form = drupal_build_form($form_id, $form_state);

  // we now have exactly the form which node_add() is returning BUT
  // we also have a reference of the form state array ready to alter;

  // how many items do we want?
  $num_items = 5;
  // this is exactly what the ajax request for the add more button does
  $form_state['field']['--machine-name-of-field--'][LANGUAGE_NONE]['items_count'] = $num_items;

  // now this is important!! set a flag inside the form state so that the hook_form_alter() function
  // is able to know when it should pre-populate (remember: hook_form_alter() will be called twice
  // during this process)
  $form_state['my_module_prepopulate'] = TRUE;

  // reset the html ids so that our new rebuilted form will get nice ids and not form_id--2
  drupal_static_reset('drupal_html_id');

  // rebuild the form and return it;
  // through drupal_rebuild_form() hook_form_alter() will be called again - this time with our
  // prepopulate flag and 5 empty form elements ready to prefill
  return drupal_rebuild_form($form_state['build_info']['form_id'], $form_state, $form);
}


Thats nearly all there is. Just setup your hook_form_alter() and you will be ready.

// hook_form_FORM-ID_alter().
function my_module_form_bundle_with_unlimited_fc_node_form_alter(&amp;$form, &amp;$form_state, $form_id) {
  if (isset($form_state['my_module_prepopulate']) &amp;&amp; $form_state['my_module_prepopulate']) {
    $delta = 0;
    $max_delta = $form['--machine-name-of-field--'][LANGUAGE_NONE]['#max_delta'];
    while ($delta &lt;= $max_delta) {
      // prepopulate whatever you like with help of #default_value'
      $form['--machine-name-of-field--'][LANGUAGE_NONE][$delta]['#default_value'] = 'Value to show';

      $delta++;
    }
  }
}


So thats it basically. Hope that this solution will help some people to save time...