function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Ankit AroraAnkit Arora 

Error: OutputField can only be used with SObject fields.

Strange problem :

 

Scenario is I have a Map (MyMap) in my controller class : Map<String , List<Account>>

 

Am trying to display this map values using visualforce page like this :

 

<apex:repeat value="{!MyMap}" var="M">
	<apex:repeat value="{!MyMap[M]}" var="temp">
		<apex:outputLabel value="{!temp.Test_Curr__c}"/><br/>
	</apex:repeat>
</apex:repeat>

 

Test_Curr__c is currency field and it is displaying value like this 1234.0 using above code . But I want to display this as $1,234. Outputfield resolves my problem here.

 

If I take a simple list of account and display on visualforce using outputField then it displays the desired format ($1,234) :

 

<apex:repeat value="{!accLst}" var="acc">
       <apex:outputField value="{!acc.Test_Curr__c}"/>
</apex:repeat>

 

But when I modify my logic using Map it says "Error: Could not resolve the entity from <apex:outputField> value binding '{!temp.Test_Curr__c}'. outputField can only be used with SObject fields."

 

<apex:repeat value="{!MyMap}" var="M">
<apex:repeat value="{!MyMap[M]}" var="temp">
        <apex:outputField value="{!temp.Test_Curr__c}"/><br/>
</apex:repeat>
</apex:repeat>

 

Just wondering when am fetching the list of account from Map why it is giving me error?? I know the error very well as it is at compile time but want to know the reason behind the screen.

 

Thanks

Ankit Arora

Blog | Facebook | Blog Page

Best Answer chosen by Admin (Salesforce Developers) 
bob_buzzardbob_buzzard

Good question Ankit.

 

I've been playing around with this, I can't come up with a mechanism that allows me to bind a property from the value retrieved from the Map to an input or output field.

 

However, if I use it inside an apex:column tag as the value attribute, I get the sobject field behaviour, in that the field label is used for the column header, so it does seem to work under some circumstances.  So, the following fails as the value can't be resolved to an sobject field:

 

<apex:column>
   <apex:outputField value="{!acc.name}"/>
</apex:column>

 but the following works and behaves like an sobject field:

 

<apex:column value="{!acc.name}"/>

It seems to be the fact that the map value is a list of accounts that is confuses things, as I can retrieve a single instance from a Map and that works fine with input/output values.

 

Outputting the account object itself on the page for maps containing both lists and single instances of accounts simply produces the account id, so that doesn't give any clues either.

 

I realise that none of this helps, but at least we are both seeing the same behaviour.  Sounds like one to raise with Salesforce.

All Answers

bob_buzzardbob_buzzard

Good question Ankit.

 

I've been playing around with this, I can't come up with a mechanism that allows me to bind a property from the value retrieved from the Map to an input or output field.

 

However, if I use it inside an apex:column tag as the value attribute, I get the sobject field behaviour, in that the field label is used for the column header, so it does seem to work under some circumstances.  So, the following fails as the value can't be resolved to an sobject field:

 

<apex:column>
   <apex:outputField value="{!acc.name}"/>
</apex:column>

 but the following works and behaves like an sobject field:

 

<apex:column value="{!acc.name}"/>

It seems to be the fact that the map value is a list of accounts that is confuses things, as I can retrieve a single instance from a Map and that works fine with input/output values.

 

Outputting the account object itself on the page for maps containing both lists and single instances of accounts simply produces the account id, so that doesn't give any clues either.

 

I realise that none of this helps, but at least we are both seeing the same behaviour.  Sounds like one to raise with Salesforce.

This was selected as the best answer
Ankit AroraAnkit Arora

Thanks a lot Bob, this worked for me. I have blogged this and please find your name in it as I can not find other best way to say thank you.

 

http://forceguru.blogspot.com/2011/07/binding-values-of-map-on-visualforce.html

 

Thanks

Ankit Arora

Blog | Facebook | Blog Page

bob_buzzardbob_buzzard

Thanks for the shoutout - I see that it was tweeted earlier today also.  Good stuff.

goabhigogoabhigo

Hi Bob/Ankit,

 

Is there any reason why VF removes any code after __r while written inside <apex:column> ??

My code is below:

 

VF:

<apex:pageBlockTable border="1" value="{!lstKey}" var="key">
    <apex:column headerValue="Opportunity">
        <apex:outputText value="{!key.Opportunity__r}"/>
    </apex:column>
</apex:pageBlockTable> 

 

Controller:

public class MaintenanceKeyController {
    public List<Key__c> lstKey {get; set;}
    
    public MaintenanceKeyController(ApexPages.StandardController controller) {
        lstKey = [select Opportunity__r.Account.Name from Key__c];
    }

}

 

I tried writing <apex:outputText value="{!key.Opportunity__r.Account.Name}"/>, when I save it is wrapped to <apex:outputText value="{!key.Opportunity__r}"/> !!! And it shows opportunity ID !!

 

goabhigogoabhigo

Some more strange things happening:

 

<apex:repeat value="{!lstKey}" var="key">
 <tr>
       <!-- Some text here -->
       <td>
           {!key.Opportunity__r.Account.Name}
       </td>
 </tr>
</apex:repeat>
</table>

Works perfect - shows the Account Name.

 

<apex:repeat value="{!lstKey}" var="key">
 <tr>
       <td>
             {!key.Opportunity__r.Account.Name}
       </td>
 </tr>
</apex:repeat>
</table>

Automatically changes to:

<apex:repeat value="{!lstKey}" var="key">
 <tr>
       <td> 
             {!key.Opportunity__r.} 
       </td>
 </tr>
</apex:repeat>
</table>

 

!!!! What is happening?