There is a "Add another item" bottom below the field collection embedded widget. To add multiple items you have to hit the button again and again. Would it be possible to

a) add an option in the settings of the field collection to not only add one item but to specify a number to add with one click,

or

b) show a field near the button where the user can enter a number of items to add and then click the button

?

Comments

thomas_rendleman Go to Django for a better experience.’s picture

That would be a nice feature especially when working with large amounts of data.
Not sure how that would work..?

ndeschildre’s picture

This is outside of this project (field collection), but I figured out this bit of code may help.
You can use that to add your own #submit function in the "Add another item" button && add/remove as many widgets as you want.

/**
* Implements hook_field_attach_form()
* We are looking at our t2imageclient widget after the "Add another item" has been added.
* We are going to alter the behavior of this button, to let us add as many new entries as
* we want.
*/
function YOURMODULE_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode)
{
  $options = array('language' => field_valid_language($langcode));

  // Merge default options.
  $default_options = array(
    'default' => FALSE,
    'deleted' => FALSE,
    'language' => NULL,
  );
  $options += $default_options;

  list(, , $bundle) = entity_extract_ids($entity_type, $entity);
  $instances = _field_invoke_get_instances($entity_type, $bundle, $options);

  // Iterate through the instances.
  $return = array();
  foreach ($instances as $instance) {
    // field_info_field() is not available for deleted fields, so use
    // field_info_field_by_id().
    $field = field_info_field_by_id($instance['field_id']);
    $field_name = $field['field_name'];

    //If we are looking at our field type and specific widget type, and we are multiple entries
    if($field['type'] == 'TODO_PUT_YOUR_FIELD_TYPE' &&
      $instance['widget']['type'] == 'TODO_PUT_YOUR_WIDGET_TYPE' &&
      $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED)
    {
      //Check just in case the button is here, and add another #submit function
      if(isset($form[$field['field_name']]['und']['add_more']))
      {
        $form[$field['field_name']]['und']['add_more']['#submit'][] =
          'YOURMODULE_field_add_more_submit';
      }
    }
  }
}

/**
* Our extra "Add another item" #submit handler. Copy pasted the field_add_more_submit
* function, altered to change the nb of widgets based on our conditions.
*/
function YOURMODULE_field_add_more_submit($form, &$form_state)
{
  //Put here the condition for altering the nb of widgets, e.g. it could be based on a
  //POST value
  if(true /** TODO */)
  {
    $button = $form_state['triggering_element'];

    // Go one level up in the form, to the widgets container.
    $element = drupal_array_get_nested_value($form, array_slice($button['#array_parents'], 0, -1));
    $field_name = $element['#field_name'];
    $langcode = $element['#language'];
    $parents = $element['#field_parents'];

    // Alter the number of widgets to show. items_count = 0 means 1.
    $field_state = field_form_get_state($parents, $field_name, $langcode, $form_state);
    //Here as an example, I am adding 10
    $field_state['items_count'] += 10;
    //But you can just fix the nb of items, like 5
    $field_state['items_count'] = 5;
    field_form_set_state($parents, $field_name, $langcode, $form_state, $field_state);

    $form_state['rebuild'] = TRUE;
  }
}

Enjoy!

cola’s picture

Hi all

any other ideas? because the variable $form[$field['field_name']]['und']['add_more'] is not set on my form

regards and thx

cola’s picture

solution: use the form_alter to add the submit function

digitisation’s picture

building on the excellent reply #2 by ndeschildre.
Just adding a simple select list of numbers to allow adding x number of items

<?php
/**
* Implements hook_field_attach_form()
*/

function village_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode){
 
$options = array('language' => field_valid_language($langcode));
 
// Merge default options.
 
$default_options = array(
   
'default' => FALSE,
   
'deleted' => FALSE,
   
'language' => NULL,
  );
 
$options += $default_options;
  list(, ,
$bundle) = entity_extract_ids($entity_type, $entity);
 
$instances = _field_invoke_get_instances($entity_type, $bundle, $options);
 
// Iterate through the instances.
 
$return = array();
  foreach (
$instances as $instance) {
   
// field_info_field() is not available for deleted fields, so use
    // field_info_field_by_id().
   
$field = field_info_field_by_id($instance['field_id']);
   
$field_name = $field['field_name'];
   
//If we are looking at our field type and specific widget type, and we are multiple entries
   
if($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED){
     
//Check just in case the button is here, and add another #submit function
     
if(isset($form[$field['field_name']]['und']['add_more'])){
       
// add a simple select list, this defaults to numb 3
       
$form[$field['field_name']]['add_more_number'] = array(
         
'#type' => 'select',
         
'#title' => t('Add more no.'),
         
'#options' => drupal_map_assoc(range(0, 50)),
         
'#default_value' => 2,
        );
       
$form[$field['field_name']]['und']['add_more']['#submit'][] = 'village_field_add_more_submit';
       
$form[$field['field_name']]['und']['add_more']['#value'] = 'Add more rows';
      }
    }
  }
}

function
village_field_add_more_submit($form, &$form_state){
 
$button = $form_state['triggering_element'];
 
// Go one level up in the form, to the widgets container.
 
$element = drupal_array_get_nested_value($form, array_slice($button['#array_parents'], 0, -1));
 
$field_name = $element['#field_name'];
 
$langcode = $element['#language'];
 
$parents = $element['#field_parents'];
 
// Alter the number of widgets to show. items_count = 0 means 1.
 
$field_state = field_form_get_state($parents, $field_name, $langcode, $form_state);
 
//get the number from the select
 
$numbtoadd = $form[$field_name]['add_more_number']['#value'];
  if(
$numbtoadd){
   
$field_state['items_count'] += $numbtoadd;
   
field_form_set_state($parents, $field_name, $langcode, $form_state, $field_state);
   
$form_state['rebuild'] = TRUE;
  }
}
?>

note, village_ is the custom module name in this case.
I think this is great oppertunity for a little module! something like field_add_x.module ? :)

El Alemaño’s picture

Issue summary:View changes

Hi digitisation,

I am trying to use your code, and i will like to do a module with that. But right now is not working right. The Add More button is working just one time, after that you can´t use it anymore. Also will be nice if the select could be together with the submit button. I try to do it like that... but it is not working good. (http://screencast.com/t/kL0PtO5boSlz)

Thanks!
El Alemaño

oryx’s picture

Worked perfectly for me (core 7.31), thank you so much! I actually called the module field_add_x ;)

digitisation’s picture

haha - good name.
I came across and issue with recursive field collection though (not a surprise) but I'm sure you can figure it out.

jmuzz’s picture

Status:Active» Closed (works as designed)

This is controlled by Drupal's handling of unlimited cardinality field items. A solution could be useful for any field but it is by no means a field collection specific issue.

El Alemaño’s picture

Status:Closed (works as designed)» Active

Hi,

I was using the "patch" but right now I can not delete any field_collection, because the save button of the form is gone when I delete on item of the field collection.
Any idea how I can fix that?

Thanks!

jmuzz’s picture

Project:Field collection» Core 7
Version:7.x-1.x-dev»