I think it would be very important to allow sorting of items.
When creating field_collection content in a node, you're only allowed to add content at the end of the list. What if you want to put some new item anywhere in the list?

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

RobW’s picture

If you need it now, the subform widget allows drag and drop sorting in the node edit form: http://drupal.org/node/977890.

robertofusco’s picture

Hi RobW,

didn't mean the sorting of collected fields. I meant when I add field_collection to a content type, I'm only allowed to add instances of my Field_collection group on the content editing page and there I can only append one other field collection group to the others. I'd like to move "groups" and sort them.

RobW’s picture

I think we may be talking about the same thing. If I misunderstand you, I apologize, and disregard the rest of this comment.

If I hear you correctly, you would like to be able to sort and re-order field collections with multiple instances (>1 or unlimited), instead of attaching them in order of creation. For example, in a node type with a field collection that contains artist, song title, and genre, you would like to add multiple instances of this field collection like so:

Node 1
-field collection field
--artist 1, song 1, genre 1
--artist 2, song 2, genre 2
--artist 3, song 3, genre 3

and then be able to add a new collection out of order, or re-order existing collections, like so:

Node 1
-field collection field
--artist 4, song 4, genre 4
--artist 1, song 1, genre 1
--artist 3, song 3, genre 3
--artist 2, song 2, genre 2

If you're looking to do that, check out the subform widget. It changes the way you add field collections, from the node view page to the node edit page, and allows you to drag and drop entire field collections to sort and re-order.

robertofusco’s picture

You're perfectly right.
It works exactly as you say.
I didn't figure out this after applying the subform patch because I've created one node before activating locale module in order to have multilanguage, and you know what? Content created before was hidden.
Now i've set language to neutral and it all works.

Thanks a lot.

RobW’s picture

Category: feature » support
Priority: Major » Normal
Status: Active » Closed (fixed)

No problem, glad to help.

dalin’s picture

Status: Closed (fixed) » Needs review
FileSize
2.82 KB

I disagree with the suggestion to use the subform widget. If your field collection has either a text area or several fields the subform widget is very unwieldly. A better way is to have a separate page for sorting just like there's a separate page for adding a new field collection item.

Attached is a proof-of-concept module that does this. If this technique works and is architecturally sound it could be rolled into field_collection module.

dalin’s picture

Version: 7.x-1.0-beta1 » 7.x-1.x-dev
Category: support » feature
ocularinvasion’s picture

I really like this. It's really clean and conforms to the design of the original module a little better.

I know you said it's a proof of concept, but is there any chance you're going to put a little more work into it? It works fine on nodes with field collections, but doesn't work on nodes with nested field collections—a field collection in a field collection.

dalin’s picture

any chance you're going to put a little more work into it? It works fine on nodes with field collections, but doesn't work on nodes with nested field collections

Well the first requirement for that would be a better bug report. "Doesn't work" does not qualify. ;-)

ocularinvasion’s picture

Sorry about that.

Here's the error message
Notice: Undefined property: FieldCollectionItemEntity::$nid in fieldcollectionsort_field_attach_view_alter() (line 38 of /home4/ameliajo/public_html/admin7/sites/all/modules/fieldcollectionsort/fieldcollectionsort.module).

webankit’s picture

+1

webankit’s picture

+1

Fidelix’s picture

Subscribing...

kenianbei’s picture

+1

pacome’s picture

Subscribing too
I'm using the last dev version (july 5) with the widget "embedded" activated.
It allows to sort the field-collections 1a, 1b, 1c like 1b, 1a, 1c within the create/edit page, but it doesn't apply yet those changes to the post itself..

Thanks a lot for this module by the way :)

-P-

WilliamB’s picture

Subscribe, i've the same issue as pacome.
Backoffice sorting collection with drag and drop works, but the change are not saved.

WilliamB’s picture

Status: Needs review » Active
dalin’s picture

Status: Active » Needs review

@WilliamB I suggest not changing the status if you don't know what it means.

WilliamB’s picture

Hum sure ok.
Sorting order of repetable fields with drag and drop is a core feature though.
And it's not working with collection, so i'd think it's an active bug instead of a requested feature but your call.

Fidelix’s picture

dalin, I have to agree with him. IMHO this is a core feature so it makes sense to support it.

WilliamB, then you should have marked it as "Needs work".

byung’s picture

Can someone please upload the patch module file? I'm having issues trying to patch it myself. Thanks for your help.

kruser’s picture

I can confirm that with the embedded collection, any sort changes do not get saved. Looking at the database, the rows are getting reordered, but delta and value columns remain the same.

tim.plunkett’s picture

Status: Needs review » Active

Not needs work/review until there's a patch.

swirt’s picture

Confirming this. Changing the sort arrangement of a several instances of a field_collection on a node has no lasting effect upon save. The sort arrangement is back to its original upon editing the node.

Makes no difference if drag and drop sorting is used, or changing the actual weight numbers. Neither change is saved upon saving the node.

tim.plunkett’s picture

Title: Sorting of items » Sorting of items with embedded widget
Category: feature » bug
Priority: Normal » Major
SolInvictus’s picture

Well I've two strikes against me. I'm new to PHP and Drupal, but in studying this problem it looks like either entity API's entity_save() should handle the translation of the form param _weight to delta or this should be handled by field_collection.module::save(). I can find nothing in the code path that would otherwise handle this. Am I headed in the right direction or into the weeds?

somanyfish’s picture

+1

adf1969’s picture

WARNING: I'm very new to Drupal 7.
Okay, that out of the way, here is what I did to allow my version of field_collection (2011-08-18) to sort:
1) Save the weight somewhere. I chose to do this in the field_collection_field_widget_embed_validate($element, &$form_state, $complete_form) since that is where the $entity got saved to the field_collection Items list.

function field_collection_field_widget_embed_validate($element, &$form_state, $complete_form) {
...
// Only if the form is being submitted, finish the collection entity and
  // prepare it for saving.
  if ($form_state['submitted'] && !form_get_errors()) {

    field_attach_submit('field_collection_item', $field_collection_item, $element, $form_state);
    //ADFMOD: Ensure that the _weight is set in the $field_collection_item
    $field_collection_item->_weight = $element['_weight'];

2) Ensure that the weight set, is saved in the correct order (technically in D7, this is supposed to be done in the hook_field_attach_submit, but it has been done historically in D6 in hook_field_presave, so that is where I put it since there was already work being done there to yank the $entity BACK out of the $items list, and plug the 'value' => item_id val into it)

function field_collection_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
  $item_weights = array();
  foreach ($items as &$item) {
    // In case the entity has been loaded / created, save it and set the id.
    if (isset($item['entity'])) {
      if (!empty($item['entity']->is_new)) {
        $item['entity']->setHostEntity($entity_type, $entity, LANGUAGE_NONE, FALSE);
      }
      $item['entity']->save(TRUE);
      $item_weights[$item['entity']->item_id] = $item['entity']->_weight['#value'];
      $item = array('value' => $item['entity']->item_id);
    }
  }
  // Re-Sort Items by Weight
  asort($item_weights);
  $delta = 0;
  foreach ($item_weights as $item_id => $weight) {
    $items[$delta] = array('value' => $item_id);
    $delta+=1;
  }
}

That's it.

I could also have saved just the weight "value" instead of the *entire* _weight array...might be a bit cleaner...but it seemed at the time the easiest option to just save the whole thing (just in case I ended up needing some *other* value from _weight)

If someone who knows Drupal 7 better than me can let me know a better way, I'm all ears, but this works and hopefully pushes this ball along the road a bit further.

Next up....ability to "delete" values from field_collection (since there doesn't appear to be a "delete" button to delete a row like there normally is in multi-row table with drag-handles)

Andrew.

WilliamB’s picture

Thanks adf1969 !
I applied your patch, it works but i get an error message:

Notice : Undefined index: _weight in field_collection_field_widget_embed_validate() (line 979 in D:\projects\MySite\sites\all\modules\field_collection\field_collection.module).

It's because my content type has several collection fields:
- Paragraph which can have an unlimited number of value (repeatable)
- Prat which can have two values (repeated twice)
- Actuality which can only have one value (not repeated).

The Paragraphs and Prats values all have _weight attribut but Actuality doesn't since it's a single value field.
So you need to add a check, because otherwise you will get an error for single value collection field!

EDIT: Bellow i just edited your code adding the control:

function field_collection_field_widget_embed_validate($element, &$form_state, $complete_form) {
...
// Only if the form is being submitted, finish the collection entity and
  // prepare it for saving.
  if ($form_state['submitted'] && !form_get_errors()) {

    field_attach_submit('field_collection_item', $field_collection_item, $element, $form_state);
    //Loading the Field to get its cardinality
    $field = field_widget_field($element, $form_state);
    //Check its cardinality to see if it's a repeatable field and thus if it has a _weight attribut
    if ($field['cardinality'] > 1 || $field['cardinality'] == -1) {
        //ADFMOD: Ensure that the _weight is set in the $field_collection_item
        $field_collection_item->_weight = $element['_weight'];
    }
function field_collection_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
  $item_weights = array();
  foreach ($items as &$item) {
    // In case the entity has been loaded / created, save it and set the id.
    if (isset($item['entity'])) {
      if (!empty($item['entity']->is_new)) {
        $item['entity']->setHostEntity($entity_type, $entity, LANGUAGE_NONE, FALSE);
      }
      $item['entity']->save(TRUE);
      //Check the field cardinality 
      if ($field['cardinality'] > 1 || $field['cardinality'] == -1) {
            $item_weights[$item['entity']->item_id] = $item['entity']->_weight['#value'];
      }
      $item = array('value' => $item['entity']->item_id);
    }
  }
  // Re-Sort Items by Weight
  asort($item_weights);
  $delta = 0;
  foreach ($item_weights as $item_id => $weight) {
    $items[$delta] = array('value' => $item_id);
    $delta+=1;
  }
}
achilles085’s picture

#29 works for me..thanks @WilliamB

tim.plunkett’s picture

Status: Active » Needs review
FileSize
1.17 KB

All of that is not necessary, there is already field_sort_items() which will take care of the sorting if the key is present.

Also, this uses the constant FIELD_CARDINALITY_UNLIMITED instead of -1.

szantog’s picture

Status: Needs review » Reviewed & tested by the community

#31 great patch!
After applied, the rearrange worked with embed widget

OnkelTem’s picture

Have just applied sucessfuly againt beta-2. Works fine, weights are saved.

tim.plunkett’s picture

Status: Reviewed & tested by the community » Fixed

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

rogical’s picture

Users like me would like always using the release version than the dev version of the module.

Can you release a new beta version when some bugs are fixed? Especially, such a big improvement.

charlie-s’s picture

I found dalin's module very usable. Might I suggest adding this function so that the admin theme is respected when sorting field_collection items:

<?php
/**
 * Implements hook_admin_paths().
 */
function fieldcollectionsort_admin_paths() {
  if (variable_get('node_admin_theme')) {
    return array(
      'field-collection/*/sort/*/*' => TRUE,
    );
  }
}
?>
charlie-s’s picture

Actually, it looks like the order that I'm setting is being ignored for items further down the list. Dalin, any ideas on this?

p4trizio’s picture

I applied manually the pacth at #31 and it works.