Please have a look at these 2 code snippets:
(1)
<apex:page id="pageId" standardcontroller="My_Object__c">
<apex:form id="formId">
<apex:pageblock id="pbId">
<apex:pageblocksection columns="1" id="pbsIs">
<apex:repeat value="{!$ObjectType.My_Object__c.FieldSets.MyFieldSet}" var="f">
<apex:inputfield value="{!My_Object__c[f]}">
</apex:inputfield></apex:repeat>
</apex:pageblocksection>
</apex:pageblock>
</apex:form>
</apex:page>
(2)
<apex:pageBlockSection title="Dimensions">
<apex:repeat value="{!fields}" var="f">
<apex:inputField value="{!merch[f.fieldPath]}" required="
{!OR(f.required, f.dbrequired)}"/>
</apex:repeat>
</apex:pageBlockSection>
I have following doubts about it:
- In (1)
<apex:repeat var="f"
is an object that is holding reference of current object
then what is the meaning of writingvalue="{!My_Object__c[f]}"
? what will
!My_Object__c[f]
return? - In (2) what is the meaning of
"{!merch[f.fieldPath]}"
statement?
I would be very grateful if someone can explain better how this fieldset works in salesforce.
Attribution to: Pramod Kumar
Possible Suggestion/Solution #1
Well they are both same. Have you tried doing {!f}
in the visualforce page?
This will give you the API name of the field in the fieldset i.e. the fieldpath.
And also when you are doing this {!$ObjectType.My_Object__c.FieldSets.MyFieldSet}
you are actually describing the fieldset and is equivalent to something like this in apex :
List<Schema.FieldSetMember> fields =
Schema.SObjectType.My_Object__c.fieldSets.getMap().get('MyFieldSet').getFields();
By doing {!My_Object__c[f]}
this you are actually passing the fieldtoken to the sobject.
Attribution to: Avidev9
Possible Suggestion/Solution #2
Long introduction talk
This would probably be much easier for you if you have ever played with "Dynamic Apex" and "Dynamic SOQL". Sometimes we need to work on the level of generic sObjects rather than concrete Account, User or Custom_Object__c
records.
Maybe running this in Execute Anonymous will help:
Map<String, Schema.SObjectField> M = Schema.SObjectType.Account.fields.getMap();
List<String> allFieldNames = new List<String>();
allFieldNames.addAll(m.keyset());
System.debug(allFieldNames);
SObject obj = Database.query('SELECT ' + String.join(allFieldNames,',') + ' FROM Account LIMIT 1');
for(String fieldName : allFieldNames){
System.debug('Account.' + fieldName + ' = ' + obj.get(fieldName));
}
So there are ways to refer dynamically, acc.get('AccountNumber')
instead of acc.AccountNumber
(but then it's up to you to use info from describe() and cast it properly to a number, string or date field for example). Scenarios when this might be needed vary (managed packages code that has to dynamically check if fields are present on the object and standard way won't compile; letting user select the fields he'd like to see etc).
Back to fieldsets
In (1) f
will be a Schema.FieldSetMember
variable holding the field name that can be used in dynamic getter like in the Apex example above. We just benefit from the fact that their toString()
method returns String with the field name, same as getFieldPath()
does.
So {!f}
gives you the field API name, same as {!f.fieldPath}
(the "get" word is omitted because that's the convention of visualforce getters/setters). You can use the info from the link to construct other merge fields like {!f.label}
or {!f.required}
.
I confess I'm lazy and always just use "f" instead of "f.fieldPath" ;) But it can be viewed as kind of against best practices. Code with just "f" all over the place will break as soon as Salesforce decides to change the Schema.FieldSetMember.toString()
.
Attribution to: eyescream
This content is remixed from stackoverflow or stackexchange. Please visit https://salesforce.stackexchange.com/questions/4978