Error on Visual Force iteration with Set

A new job means it’s time for learning new stuff. Great, let’s start learning Salesforce.

The first article on salesforce I will dedicate to an error which might amaze all the newbies for Salesforce.

You will get an error whenever you try save the page with a Set binded to a iterable VisualForce (refering as VF later) element. E.g. apex:pageBlockTable or apex:repeat

Consider the following example:

VF page:
<apex:page controller="QuickTest" showHeader="false" sidebar="false">
    <apex:pageBlock>
        <apex:pageBlockTable value="{! dataSet}" var="ds">
            <apex:column title="Values">
                <apex:outputText value="{! ds.data1 }" />
            </apex:column>
        </apex:pageBlockTable>
    </apex:pageBlock>
</apex:page>
    
Apex controller:
public class QuickTest {
    public Set<InnerClass> dataSet { get; set; }
    
    public QuickTest() {
        this.init();
    }
    
    public void init() {
        this.dataSet = new Set<InnerClass>{
            new InnerClass(),
            new InnerClass(),
            new InnerClass()
        };
    }
    
    private class InnerClass {
        public Integer data1 { get; set; }
        
        public InnerClass() {
            data1 =  (Integer) (Math.random() * 100);
        }
    }
}
    

The page should display three random numbers that are below 100 in theory.
But instead, I got an error upon saving the VF page: Unknown property ‘SetValue.data1’

Alright, let’s give another try with a set of sObjects.

1. Replace <apex:outputText value=”{! ds.data1 }”/> on the VF page with element:
<apex:outputField value=”{! ds.Name }” />

2. Adjust the corresponding controller:

    // ... more code here
    public Set<Contact> dataSet { get; set; }
    
    public QuickTest() {
        this.init();
    }
    
    public void init() {
        List<Contact> myContacts = [SELECT Name FROM Contact LIMIT 10];
        System.debug('No. of contacts retrieved: ' + myContacts.size());
        this.dataSet = new Set<Contact>(myContacts);
    }
    // ... more code here
    

Note: Variable ‘ds’ is a sObject which is a type of Contact now.

Side note for beginners: apex:outputField is for sObjects and apex:outputText is for pimitives.

This time, I got another error: Could not resolve the entity from apex:outputField value binding ‘{!ds.Name}’. apex:outputField can only be used with SObjects, or objects that are Visualforce field component resolvable.

Therefore, the apex:pageBlockTable (possibly will happen on apex:Repeat as well) iteration does not get along with a Set<>.

Solution:

1. The quickest and easiest way to fix this problem, is that you can use List instead of using a Set.

2. But if you want to maintain the uniqueness of values in a collection, you might need to consider using the Map.

Example of using a Map to resolve the issue:

VF page:
<apex:page controller="QuickTest" showHeader="false" sidebar="false">
    <apex:pageBlock >
        <apex:pageBlockTable value="{! dataMap }" var="key">
            <apex:column title="Values">
                <apex:outputText value="{! dataMap[key].data1 }" />
            </apex:column>
        </apex:pageBlockTable>
    </apex:pageBlock>
</apex:page>
    
Apex controller:
    // ... more code here
    public Map<string, InnerClass> dataMap { get; set; }
    
    public QuickTest() {
        this.init();
    }
    
    public void init() {
        dataMap = new Map<string, InnerClass>();
        dataMap.put('1', new InnerClass());
        dataMap.put('2', new InnerClass());
    }
    // ... more code here
    

Leave a Reply

Your email address will not be published. Required fields are marked *