[SalesForce] Spring’14 (bug?) with apex:repeat and sets

I think I may have found a bug with iterating over a set in spring'14.

So I have some code that creates a set (using set so it will be unique) and then on the page it iterates over the set using an apex:repeat. The problem is that it wont save. If I change the set to a list it saves and works fine. I know (or am pretty sure) I have been able to use sets in the past with apex:repeat but now I cannot. Here is the code (simplified) and the errors:

public class CreateOrders {

  public Set<Item__c> selectedItems {get; set;}

  public CreateOrders() {
    selectedItems = new Set<Item__c>();
    for (Item__c i : findItems()) {
      selectedItems.add(i);
    }
  }
}

then on the page:

<apex:repeat value="{!selectedItems}" var="itm">
  <apex:outputfield value="{!itm.Name}" />
</apex:repeat>

and the resulting error is: Save error: Could not resolve the entity from apex:outputField value binding '{!itm.Name}'. apex:outputField can only be used with SObjects, or objects that are Visualforce field component resolvable.

and when I try removing the apex:outputfield by using apex:outputtext or nothing like so:

<apex:repeat value="{!selectedItems}" var="itm">
  <apex:outputtext value="{!itm.Name}" />
</apex:repeat>

OR

<apex:repeat value="{!selectedItems}" var="itm">
  {!itm.Name}
</apex:repeat>

I get this error: Save error: Unknown property 'SetValue.Name'

and its the same with any field/object. But when I switch the Set over to a List it works without any issues…

UPDATE

So on a hunch I checked the version, and it was on 28. When I upgraded it to 29, it allowed me to save with apex:outputfield only, but on refresh of the page I still got the same errors:

Could not resolve the entity from apex:outputField value binding '{!itm.Name}'. apex:outputField can only be used with SObjects, or objects that are Visualforce field component resolvable.

and it still wouldnt let me save if I changed the apex:outputfield to apex:outputtext or used no apex tags it would still not save and give me the error:

Save error: Unknown property 'SetValue.Name'

On versions older than 29 (20-28 that I have tested) they all error like 28, 29 is the only one with a slightly different behavior.

When saving with just {!itm} it allows the save to happen, and the page just shows the Id of the Item.

Best Answer

I don't think this is a new behaviour in Spring 14.

In the discussion forums - Table rows repeating for each Child Record present in Parent to Child Query there is a comment from @bob-buzzard in 2011:

It seems to be a problem when the set contains sobjects - I've just checked back on mine and they've been primitives. It smacks that the "SetValue" in the page (sounds low-level possibly a java class) can convert to a string for display if its a primitive, but not when a complex object.

There is an example of using a primitive Set with an apex:repeat in the answer Peter Knolle provided to another question.


As an alternative to using a Set you could instead use a Map (assuming your records have been inserted and have an Id). Then use the syntax from Referencing Apex Maps and Lists to drive the repeat over the maps keys and lookup the corresponding value.

Controller:

public class CreateOrders {
    public Map<Id, Item__c> selectedItems {get; set;}

    public CreateOrders() {
        selectedItems = new Map<Id, Item__c>();
        for (Item__c i : findItems()) {
            selectedItems.put(i.Id, i);
        }
    }
}

Visualforce page:

<apex:repeat value="{!selectedItems}" var="itm">
    <apex:outputfield value="{!selectedItems[itm].Name}" />
</apex:repeat>
Related Topic