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(&$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' => $user->uid,
'name' => (isset($user->name) ? $user->name : ''),
'type' => $type,
'language' => 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(&$form, &$form_state, $form_id) {
if (isset($form_state['my_module_prepopulate']) && $form_state['my_module_prepopulate']) {
$delta = 0;
$max_delta = $form['--machine-name-of-field--'][LANGUAGE_NONE]['#max_delta'];
while ($delta <= $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...