0

I have some custom objects in Salesforce that I want to iterate over in a given order.

Right now, they are in a map, so I have added a certain field 'Priority__c' which will contain the relative order I want them in.

If I am using an apex:repeat to render in VF, is there some way to have these iterated over, based on their relative order, via the Priority__c field?

1
  • You're querying for them? Just add an ORDER BY clause to your soql. If you're using a Map, though...Please edit your post to include what you have so far.
    – Adrian Larson
    Aug 28, 2016 at 17:11

1 Answer 1

1

Values in a map have a undetermined order. The only thing that is guaranteed to be the same is the iteration order of the map. Note that it does not say the iteration will be the order in which the elements were added, rather, the iteration will happen in the same order every time.

the iteration order in maps and sets is always the same

https://releasenotes.docs.salesforce.com/en-us/summer15/release-notes/rn_apex_maps_and_sets_iteration_order.htm

The above assumes your API is at the right version as prior to this release the iteration could be different each time.

If you truly need to control the order adjust your code to use a query with an order by clause or for more complex operation use a wrapper class that implements comparable and then use that in the vf page

Take for example the following:

public Map<ID,Account> accountMap{
    get{
      return New Map<ID,Account>([Select ID, Name From Account]);
    }
     set;
}

VF Page:

<apex:repeat value="{!accountMap}" var="a">
    <apex:outPutText value="{!a.name}"/>
</apex:repeat>

This could be modified as follows:

public class outerClass{

    public Map<ID,Account> accountMap{
        get{
          return New Map<ID,Account>([Select ID, Name From Account ]);
        }
         set;
    }

    public Account[] accountList{
        get{
          return [Select ID, Name From Account Order by Name ASC]);
        }
         set;
    }


    public accountWrapper[] accountWrapper{

      get{
        if(accountWrapper = null){  
          accountWrapper = new AccountWrapper[]{};
          for(Account a : accountMap.values()){
              accountWrapper.add(New accountWrapper(a));
          }
          accountWrapper.sort();
        }
          return accountWrapper;

      }

      set;

    }

    public class accountWrapper implements comparable{
       public account acct {get;set;}

       public accountWrapper(Account a){
           acct = a;
       }

        public Integer compareTo(Object compareTo) {
            accountWrapper compareToAW = (accountWrapper) compareTo;
            if (acct.name == compareToAW.acct.name) return 0;
            if (acct.name > compareToAW.acct.name) return 1;
            return -1;
        }

    }

}

VF Page with List:

 <apex:repeat value="{!accountList}" var="a">
     <apex:outPutText value="{!a.name}"/>
 </apex:repeat>

VF Page with Wrapper:

 <apex:repeat value="{!accountWrapper}" var="a">
     <apex:outPutText value="{!a.acct.name}"/>
 </apex:repeat>

List is great for maps in this example, wrapper is great for sorting that may be more complex or where the Map keys are not from the same object or are a property such as integer, etc

2
  • You hardly need a wrapper if you're already querying for the records. Just use ORDER BY.
    – Adrian Larson
    Aug 28, 2016 at 17:59
  • Good point, you are correct in this situation, but may not be the case for all depending on what the map holds. Will add that to the answer though
    – Eric
    Aug 28, 2016 at 18:02

Not the answer you're looking for? Browse other questions tagged .