The problem occurs when you use field collections with the hidden widget (you don't want to embed the form on the edit page). But that means that users cannot change the ordering of items in a multiple field collection field. So one solution would be to introduce a new widget that provides a listing on the edit page with the usual drag & drop table order mechanism. It could display the field collection items as usual with edit/delete links.

Original report by Adam S

A resume will have the most resent education or job experience listed first or at the top. When a new educational experience is added to eRecruiter it is added to the bottom. Even then the user might want to insert an edited education experience. So there needs to be a way to control the delta of items.

CommentFileSizeAuthor
#20 resume.png62.95 KBkaizerking
#17 rearrange-field-collections.png22.63 KBAdam S
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Adam S’s picture

Perhaps letting the users determine the order of the field collection item list isn't necessary. It would be better to render the fields based on the date stamp time with the large date number being listed first. Also, what about people who need to put present as a date meaning that they still work at a place?

Adam S’s picture

Priority: Major » Critical

I'm marking this critical because every resume puts the most recent education or job experience in decending order by date. This problem is preventing me from lunching the website.

Adam S’s picture

After a day of using Google and StackExchange to find out how to sort arrays with PHP, I came up with this code. I know it needs refactoring. I'm sure it probably isn't the best way to handle this problem but it seems to do the job.

function helper_entity_presave($entity, $type) {
  if ($type == 'profile2' && $entity->type == 'resume'){
    if (!empty($entity->field_resume_education)){
      $field_collection_items = array();
      foreach ($entity->field_resume_education as $lang => $value){
        foreach ($value as $delta => $value2){
          $field_collection_id = $value2['value'];
          $field_collection_items[$delta] = field_collection_item_load($field_collection_id);
          $field_collection_items[$delta]->lang = $lang;
        }
      }
      // If the current entity has less items than the orginal then something has been deleted. Lets not mess with it.
      if (count($entity->field_resume_education[$lang]) >= count($entity->original->field_resume_education[$lang])){
        $sorted = usort($field_collection_items, 'helper_sort_by_time');
        foreach ($field_collection_items as $delta => $value3){
          $entity->field_resume_education[$lang][$delta]['value'] = $field_collection_items[$delta]->item_id; 
        }
      }  
    }  
    if (!empty($entity->field_resume_xp)){
      $field_collection_items = array();
      foreach ($entity->field_resume_xp as $lang => $value){
        foreach ($value as $delta => $value2){
          $field_collection_id = $value2['value'];
          $field_collection_items[$delta] = field_collection_item_load($field_collection_id);
          $field_collection_items[$delta]->lang = $lang;
        }
      }
      // If the current entity has less items than the orginal then something has been deleted. Lets not mess with it.
      if (count($entity->field_resume_xp[$lang]) >= count($entity->original->field_resume_xp[$lang])){
        $sorted = usort($field_collection_items, 'helper_sort_by_time');
        foreach ($field_collection_items as $delta => $value3){
          $entity->field_resume_xp[$lang][$delta]['value'] = $field_collection_items[$delta]->item_id; 
        }
      }  
    }  
  }
}

function helper_sort_by_time($a, $b) {
    return $b->field_resume_time_period[$b->lang][0]['value2'] - $a->field_resume_time_period[$a->lang][0]['value2'];
}
kaizerking’s picture

Issue tags: +sort order

Hi Adams , I have been searching for this feature, Where to put this code please, I am new bee, dumb like a rock

Adam S’s picture

This isn't tested and I don't really know PHP -- I was just making a guess and it seems to work. I placed it in a module called helper.module that I use to host misc code that I don't put in template.php. To make a module you need a folder in sites/all/modules called helper. In that there needs to be two files, helper.info and helper.module.

helper.info should have these three lines of code:

name = Helper
description = Misc. functions for eRecruiter
core = 7.x

Then place the above function inside of helper.module (that is all the code placed in it). The info file shouldn't have <?php tag but the helper.module file should start with an opening <?php but not close with one.

kaizerking’s picture

Thanks Adams ,

I have checked your site , it is amazingly wonderful, Wish I could make a site like yours, especially I like the theme, simple and sober and no nonsense
am also not a coder.just trying to attach bits and pieces and make site
I have created a module called "date range overlap" with the given code, It isn't working
What I am expecting is , each time I add an experience,
1.It should prevent me from adding a conflicting date range,
2.It should re order the view according to descending sort order

Any suggestion or idea please?

Adam S’s picture

1.It should prevent me from adding a conflicting date range,
2.It should re order the view according to descending sort order

The first one will require quite a bit of custom code perhaps you might want to hire someone to do that. Keep in mind that for almost all application this wouldn't work as people can work two jobs are go to summer school or overseas study while still enrolled in a school.

We will need a developer to implement the code for the distribution.

kaizerking’s picture

You are right, I am thinking too perfectionist and idealistic way, and not taking in to consideration the practical scenario.

klausi’s picture

Project: Recruiter » Field collection

clearly a field collection issue.

tim.plunkett’s picture

Priority: Critical » Normal
Status: Active » Postponed (maintainer needs more info)
Issue tags: -sort order

There is no such thing as a critical feature request.

Can you update the title and the issue summary? It is eRecruiter specific, which means absolutely nothing to me. Please mark back to active when you do.

kaizerking’s picture

The issue has been in general demand for a long time pl refer:http://drupal.org/node/135711
I feel it is supposed to be Date module feature, who wants to take ownership depends on requirement.
Because the trigger should be the "collect end date" and "required",and if it is "multi value field" which should call function form alter( i don't know if that's what done to get new options), make form - new options-
Dates overlap
1. "Allow Dates over lap" (with a warning to user"),-Default
2. "Prevent dates overlap" and
Sort order or Order by:
1." do not sort"
2. "Ascending
3. "Descending".
Implementing "current status": this is very tricky thing because many users may not be working currently to say "current", Obviously if he is working he wont visit a job site, it may look a silly logic, but true.

Also logically, a duration calculation also can be part of this

1. duration for single value field
2. Multi value field (sum of single value durations)
3. field collection fields
Settings:Duration in years,months,weeks, days, Hours , Minutes, Seconds

Adam S’s picture

There is no such thing as a critical feature request.

This feature request was made in context of a distribution profile that I could not put online because field collections could not be sorted. I'm still not sure why this issue was moved as it is specific to listing order of job or education history of a job board website.

Of course, being able to sort field collections is a wider issue but my experience is that it is solved using a drag and drop mechanism on the edit form.

Adam S’s picture

How about adding a configuration setting to the field collection item being added to the parent enitity that allows of using another field to use as the sort?

klausi’s picture

Title: Users need to be able to order the delta of field-collection items in education and job experience. » Order the delta of field-collection items when using the hidden widget
Status: Postponed (maintainer needs more info) » Active

Sorry for the confusion. As far as I can see the problem occurs when you use field collections with the hidden widget (you don't want to embed the form on the edit page). But that means that users cannot change the ordering of items in a multiple field collection field. So one solution would be to introduce a new widget that provides a listing on the edit page with the usual drag & drop table order mechanism. It could display the field collection items as usual with edit/delete links.

klausi’s picture

Issue summary: View changes

added field collection specific problem description

kaizerking’s picture

Adam, this code worked for me, how ever, on first creation of an experience I am getting this"Notice: Undefined index: und in helper_entity_presave() (line 31 of /hsphere/local/home/......./sites/all/modules/helper/helper.module)."

Adam S’s picture

So one solution would be to introduce a new widget that provides a listing on the edit page with the usual drag & drop table order mechanism.

Since users in the case of eRecruiter do not have the option to use the edit page, perhaps, another more elegant version of this idea is to include a 'rearrange' link on each field-collection group next to the 'add' link which doesn't load the entire node edit form but a form that allows the user to drag 'n drop each field-collection within the group.

Adam S’s picture

Here is a screen caption of what the widget link for a rearrange form would look like.

Adam S’s picture

@kaizerking

We should open this issue again in the eRecruiter queue.

However, the problem here is that if there isn't an original entity because the first one was just created there isn't any reason to sort it. So line 31 should be something like if (!empty($entity->field_resume_education) && !empty($entity->original->field_resume_education)){ or if (!empty($entity->field_resume_xp) && !empty($entity->original->field_resume_xp)){ .

kaizerking’s picture

Ok, But as of now the code is working , i think we should suppress message, any idea on how to ?

kaizerking’s picture

FileSize
62.95 KB

calculating the duration worked out using the computed field
I have requirement to
1.sum up all the durations in a work experience field collection in resume,
help me please pl.
2. Calculate the duration from the oldest start date to Date Now()
help please
have look at screen shot

Adam S’s picture

@kaizerking

This is a very esoteric problem and has little to do with Field collection so I'm not sure if it belongs here. This is more appropriately asked in drupal.org forums or on drupal.stackexchange.com. This issue thread is now about how to order Field collections in general.

g089h515r806’s picture

i have created a module "Field Collection Views Formatter", http://drupal.org/project/field_collection_views
which provide a replace solution for this issue.
Test it.

tim.plunkett’s picture

Status: Active » Closed (won't fix)

If you want to edit the field_collection on the edit form, use the Embedded widget.

I guess you can just hook_form_alter and set the inputs to disabled if you really wanted to.

tim.plunkett’s picture

Issue summary: View changes

fixed username

rogical’s picture

Issue summary: View changes

I have many field collection fields in a node, about 8 field collection(within 5 fields each).

It's tooo heavy to edit those field collection fields together in a node form, so I use the hidden widget, add field collection items on the node view.

But too sad can't order the field collection item, I think this feature is quite useful and need to sort the item in a standalone page for a field collection field.

8bitplateau’s picture

I think this would be better handled as a separate module that gives you options in the Fields UI for the field collection for how you want to handle the Sorting, eg, Choose a Field to sort by and order ( ASC etc ). That would be great and isn't really this modules problem.

However, I also wanted to sort a Field Collections delta according to a time field within it for a task schedule app, and here is the code I used.


/*==============================================================================
 *
 *  Implements Hook Entity Preseave
 *
 *============================================================================*/


function village_entity_presave($entity, $type) {
  // Do we have the right entity ?
  if (isset($entity->type) && $entity->type == 'production_schedule'){
  // Is there at least one FC ?
    if (isset($entity->field_production_schedule[LANGUAGE_NONE][0])){
      // Get the FCs
      $tasks = $entity->field_production_schedule[LANGUAGE_NONE];
      // Get a count number
      $tasks_count = count($tasks);
      // Prepare empty array
      $times = array();
      // Simpley loop
      foreach ($tasks as $delta => $task){
        // Simple time value check
        if(isset($task['field_time']['und'][0]['value'])){
          // Get numeric time stamp
          $timestamp = strtotime( $task['field_time']['und'][0]['value'] );
          // Add delta to array keyed by timestamp
          array_push($times, array( 'd'=>$delta, 't' => $timestamp));
        }
      }
      // Sort the array by its key ( timestamp ) - we now have
      usort($times, "task_sorter_tcmp");
      // Loop over the sorted times and delta
      foreach ($times as $delta => $time){
        // Add back in the FCs according to the time delta at new delta postion
        $entity->field_production_schedule[LANGUAGE_NONE][$delta] = $tasks[$time['d']];
      }
    }
  }
}

/*==============================================================================
 *  UASORT - Helper for the above
 *============================================================================*/

function task_sorter_tcmp($a, $b){
  if ($a == $b){
      return 0;
  }
  return ($a['t'] < $b['t']) ? -1 : 1;
}
drupix’s picture

#25 worked like a charm.

Thanks.