Showing posts with label Dynamic Binding. Show all posts
Showing posts with label Dynamic Binding. Show all posts

Wednesday, 15 June 2011

Dynamic Binding : Use Action Functions on Field Set's Fields


Hi,

Earlier we have talked about how to use dynamic binding with or without field set and dynamic binding when object is also dynamic. Now its time to go one level ahead. 

My first question : Why we use dynamic binding ?
Ans : So that VFP Design can be configured on production org without any code change.

Mostly when we use field set or dynamic binding we can change our UI at any time but how to handle onclick event of any field if we have such requirement. We have only one inputField control in Repeat then how to call a javascript or actionFunction. We can not have dynamic UI at the cost of any business logic. So lets try to do it now


Requirement : We have a custom picklist field in the Field Set fields that we are displaying,  "Is Active" having value "Yes" , "No" , “None” , if user select s yes then “No Of Employee” fields should become mandatory and if he changes it to other then “Yes” then it should be non mandatory. And also set No Of Employe = 5 whenever "Is Active" fields changes its value.


Step 1: First I Created a Field Set On Account , With Five Fields in the Field Set






Step 2: Create the Controller Class like this

//Controller class
public class actionFunction_FieldSet {

    
    public Account account {get;set;}
    public boolean noOfEmpReq {get;set;}
    public String IsActive {get;set;}
    
    public actionFunction_FieldSet()
        {
            noOfEmpReq  = false;
            account = new Account();
        }
    //action function to be called
    public void actionFunctionM()
        {
            if(IsActive == 'Yes')
                noOfEmpReq = true;
            else
                noOfEmpReq = false;    
        }    
}

Step 3: Create a VFP like this
<apex:page controller="actionFunction_FieldSet" title="Field Set Use">
   <apex:form >
       <!-- Action function to determine required status for No of employee field -->
       <apex:actionFunction name="jsSetNoOfEmpReq" oncomplete="alert('action completed');" action="{!actionFunctionM}" immediate="true" reRender="pbsFS">
           <apex:param assignTo="{!IsActive}" value="IsActive" id="IsActive" name="noEmpR"/>
       </apex:actionFunction>
       <script>
           
           var numberofemployeesID;
           function setNoOfEmpReq(ctrlIsActive)
               {
                    
                    //Assign value to the no of employee field
                    if(document.getElementById(numberofemployeesID) != null)
                        document.getElementById(numberofemployeesID).value = 5;
                    //action function call 
                    jsSetNoOfEmpReq(ctrlIsActive.value);
               }
       </script>
       <apex:pageBlock title="Field Set Use">
       <apex:pageBlockSection title="Field Set Use" id="pbsFS">
           <apex:repeat value="{!$ObjectType.Account.FieldSets.DemoFieldSet}" id="ctrlRepeat" var="fieldAPIName">
               <!-- 
                    1. We have cretaed there input fields one will only if active__c field comes trough field set
                    2. second when numberofemployees comes
                    3. For other field
                    
                    Using such design we can have the dynamic design as well we can use onclick or onchange events on fields
                -->
               <apex:inputField value="{!account[fieldAPIName]}" onchange="setNoOfEmpReq(this);" rendered="{!IF(CONTAINS(LOWER(fieldAPIName), 'active__c') , true , false)}"/>
               <apex:inputField value="{!account[fieldAPIName]}" required="{!noOfEmpReq}" rendered="{!IF(CONTAINS(LOWER(fieldAPIName), 'numberofemployees') , true , false)}" id="NoOfEmp" />
               <apex:inputField value="{!account[fieldAPIName]}" rendered="{!IF(OR(CONTAINS(LOWER(fieldAPIName), 'active__c') , CONTAINS(LOWER(fieldAPIName), 'numberofemployees')) , false , true)}" /> 
               
               <script>
               /*
                   Set the id for numberofemployeesID field can be used in java script
               */
               if({!CONTAINS(LOWER(fieldAPIName), 'numberofemployees')})
                   {
                       numberofemployeesID = '{!$Component.ctrlRepeat}:NoOfEmp';
                   }
               </script>
           </apex:repeat>
       </apex:pageBlockSection>
       </apex:pageBlock>
   </apex:form>>
</apex:page>

So that was a very basic requirement when we need to use action function on any event of field from field set. Using similar approach we can solve big problems as well. We can also achieved it using only a single inputField and using onclick and passing  field api name and performing actions only to valid fields otherwise return false.

<apex:page controller="actionFunction_FieldSet" title="Field Set Use">
   <apex:form >
       <!-- Action function to determine required status for No of employee field -->
       <apex:actionFunction name="jsSetNoOfEmpReq" oncomplete="alert('action completed');" action="{!actionFunctionM}" immediate="true" reRender="pbsFS">
           <apex:param assignTo="{!IsActive}" value="IsActive" id="IsActive" name="noEmpR"/>
       </apex:actionFunction>
       <script>
           
           var numberofemployeesID;
           function setNoOfEmpReq(ctrl , isctrlIsActive)
               {
                    if(isctrlIsActive)
                        {
                            //Assign value to the no of employee field
                            if(document.getElementById(numberofemployeesID) != null)
                                document.getElementById(numberofemployeesID).value = 5;
                            //action function call 
                            jsSetNoOfEmpReq(ctrl.value);
                        }
                    else
                        return false;    
               }
       </script>
       <apex:pageBlock title="Field Set Use">
       <apex:pageBlockSection title="Field Set Use" id="pbsFS">
           <apex:repeat value="{!$ObjectType.Account.FieldSets.DemoFieldSet}" id="ctrlRepeat" var="fieldAPIName">
                <!-- 
                    1. Used only one input field 
                -->
                
               <apex:inputField value="{!account[fieldAPIName]}" onchange="setNoOfEmpReq(this , {!CONTAINS(LOWER(fieldAPIName), 'active__c')});" required="{!IF(CONTAINS(LOWER(fieldAPIName), 'numberofemployees') , noOfEmpReq , false)}" id="fieldId" />
               
               
               <script>
               /*
                   Set the id for numberofemployeesID field can be used in java script
               */
               if({!CONTAINS(LOWER(fieldAPIName), 'numberofemployees')})
                   {
                       numberofemployeesID = '{!$Component.ctrlRepeat}:fieldId';
                   }
               </script>
           </apex:repeat>
       </apex:pageBlockSection>
       </apex:pageBlock>
   </apex:form>>
</apex:page>


Other Related Posts : Dynamic Binding : When Object Name is Dynamic Also


         Regards
Shashikant Sharma




Sunday, 5 June 2011

Dynamic Binding : When Object Name is Dynamic Also

Hi,

In earlier post we talked about dynamic binding with field set in this object name was static and fields were coming dynamically from Field Sets.Now we will talk about other way when both Object and Fields are dynamic.

Now we will take examples where object name and fields both are dynamic and fields are not coming from Field Sets either.

Controller Class
public class DynamicBinding {
    
    public sObject sObjectToBind {get;set;}
    public List<String> listObjectFields {get;set;}
        
    public DynamicBinding()
    {
        listObjectFields =  new List<String>();
        Map<String , Schema.SObjectType> globalDescription = Schema.getGlobalDescribe();
        //In this example I have hard coded the object name
        Schema.sObjectType sObjType = globalDescription.get('Account');
        
        sObjectToBind = sObjType.newSObject();
        Schema.DescribeSObjectResult r1 = sObjType.getDescribe();
        
        Map<String , Schema.SObjectField> mapFieldList = r1.fields.getMap();
        Integer i = 0;
        for(Schema.SObjectField field : mapFieldList.values())
            {
                Schema.DescribeFieldResult fieldResult = field.getDescribe();
                if(fieldResult.isAccessible() && fieldResult.isUpdateable())
                    {
                        listObjectFields.add(fieldResult.getName());
                    }
                if(i == 5)
                    break;
                
                i++;
            }
                        
    }
}

Visulaforce Page

<apex:page controller="DynamicBinding">
  
   <apex:form>
       <apex:pageBlock title="Without Field Set Use">
       <apex:pageBlockSection title="Dynamic Object">
           <apex:repeat value="{!listObjectFields}" var="fieldAPIName">
               <apex:inputField value="{!sObjectToBind[fieldAPIName]}"/>
           </apex:repeat>
       </apex:pageBlockSection>
       </apex:pageBlock>
   </apex:form>


</apex:page>


So in above example I used an sObject instance and showed 5 fields only of that Object type. In above example I used Account object you can decide any object pass the name from any parameter or get as input from User using Picklist.

Related Post : http://forceschool.blogspot.com/2011/06/dynamic-binding-using-field-sets.html

Regards




Saturday, 4 June 2011

Dynamic Binding : Using Field Sets

Hi,

Dynamic binding has been an amazing feture released in Spring 11. Earlier in visualforce page means that the apex controls that used to be binded like {!sObjectAPIName.FieldAPIName} , where you have to provide object API Name and field API Name at compile time ( at the time you develope a page and save it), it was static binding. Now we can provide both of these at run time thats why it is dynamic binding.

Variations of Dynamic Binding :

1) Dynamic Field API Name : It can be sub divided in two parts
    A) Using Field Sets
    B) Without Using Field Sets where Field to be displayed are maintained in any List in apex class, we can save these list using any custom object in which we will save both object API Name and Field API Name.

2) Dynamic Object API Name and Field API Name both

We will start here by first

1) Dynamic Field API Name Using Field Set :

First we will create a field set on Account Object : Go to -> Customize -> Account -> Field Sets and create a new field set.

Here you will see three boxes for field selection
1)Account(This is Object Name) Object Fields : This box is only available on developer org. This is not visible on production org after managed packaged is installed there.
2)Available For the Field Set : These are the fields that are available to move to the "In the Field Set". This is available on production org after managed packaged is installed there.
3) In the Field Set : These are the fields that are actually rendered on Visualforce Page when Field Set is used.

Now I will add some fields see the below image


Now Save this field set.

Note : In summer 11 release layout for field set editor has been changed and made like page layout in the object. See this for more http://forceschool.blogspot.com/2011/05/summer-11-field-sets.html

Using field Set on Visulaforce Page

<apex:page standardController="Account" title="Field Set Use">
   <apex:form>
       <apex:pageBlock title="Field Set Use">
       <apex:pageBlockSection title="Field Set Use">
           <apex:repeat value="{!$ObjectType.Account.FieldSets.DemoFieldSet}" var="fieldAPIName">
               <apex:inputField value="{!Account[fieldAPIName]}"/>
           </apex:repeat>
       </apex:pageBlockSection>
       </apex:pageBlock>
   </apex:form>>
</apex:page>
In above example we used Account as standard controller, and used it for Field binding in Input Field. We can also use any account instance of account object from controller class also if we want. All fields of field set renders in order you save them in "In the Field Set" column. If any field is Hidden for any profile then field set will not render that field for that user.

You can also show field set of any related object which has a reference to parent object using relationship name.

Often it is asked whether we can create new fields and fields in the field set on production orgs. Answer to this is "Yes". As soon you create any field on the object on production org it comes in "Available Fileds" box and you can add them in the field set and render them on your VFP.

Related Post : http://forceschool.blogspot.com/2011/06/dynamic-binding-when-object-name-is.html

Tweet