Take the 2-minute tour ×
Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It's 100% free, no registration required.

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.

share|improve this question
    
Did you try to save with a set property + vf repeater as older api versions ? –  Samuel De Rycke Feb 24 at 19:49
    
see updated question, but both version 28 and 29 wont work with sets/apex:repeat –  SalesForceGirl Feb 24 at 19:55
    
How about displaying just {!itm}, this also caused problems? –  Artur Kępczyński Feb 24 at 20:05
    
no, that allows the save to happen, and on the page, it shows the item Id.. but this only works if i dont use apex:outputfield, apex:outputtext works and using no tags works –  SalesForceGirl Feb 24 at 20:15
    
Though I can see using a list and using list.addall(set) as workaround, I confirm the same behavior with my developer account too. Lists are working fine, but sets are not with apex:repeat tag –  rao Feb 24 at 20:16
show 1 more comment

2 Answers

up vote 6 down vote accepted

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>
share|improve this answer
2  
yeah I ended up using maps instead :-P but I still feel sets should work with sobjects.. –  SalesForceGirl Feb 25 at 1:38
    
From Ideas : Allow Visual Force apex:repeat to work with Maps it appears things weren't always so great with Maps either. You will probably need to go down the ideas path to get it resolved for Sets :/ –  Daniel Ballinger Feb 25 at 21:00
add comment

I will try to confirm this but I think tis is caused because set is non-ordered collection of data and you just can't get element number [i] and ask it for values like repeat block try to do - and thats why it work with list

For now lets be patient and wait for one of MVP to speak :)

share|improve this answer
    
You can use a Set as the value in a repeat. See Apex Repeat Using Set Collection. It might be a special Case for sObjects. –  Daniel Ballinger Feb 24 at 23:38
    
Here is a 2011 comment from MVP @bob-buzzard: "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." –  Daniel Ballinger Feb 24 at 23:52
    
Thats kinda what I suspected... Thanks for finding this! :) –  Artur Kępczyński Feb 25 at 4:34
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.