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




11 comments:

  1. Hello there!

    I hope this message finds you well. I have been reading all your post in dev board and here in this wonderful blog and thought you might be the person who can help me with my problem.

    I want to update a custom field in account "GBS__c" with another custom field from a custom object "Table__c" i have a look up from Table__c to Account which I named Account__c.

    I have a trigger that looks like this


    trigger UpdateEscalatorsInAccounts on Question__c(before insert, before update)
    {

    for(Table__c t : Trigger.new)
    {
    Account a = [select Name from Account where Id = :t.Account__c];

    a.GBS__c = t.GBS__c;
    }

    }


    It does not update anything.

    I will greatly appreciate your feedback. Thank you in advanced!

    ReplyDelete
  2. oh, nvm I figured out what I am missing. :)

    the line that says update a;

    Thank you anyway, you have a really wonderful blog!

    ReplyDelete
  3. Hi Shashikant Sharma ,
    your displayed all fields dynamically in an visualforce page without using fieldset.Please tell me how to save these fields related in formation in database?

    I want immediatly help me...

    Note:Here I saved dynamically comming object related records in that related object (Using schema methods)but i gave some information in a fields these fields related information is not saved in that object related Record.

    help me........

    ReplyDelete
  4. Its a very helpful post. Thanks for sharing.
    Cheers

    ReplyDelete
  5. Thanks for this blog. provided great information. All the details are explained clearly with the great explanation. Thanks for this wonderful blog. Step by step processes execution are given clearly.Know the details about different thing.
    Hadoop Training in Chennai

    ReplyDelete
  6. Wow amazing i saw the article with execution models you had posted. It was such informative. Really its a wonderful article. Thank you for sharing and please keep update like this type of article because i want to learn more relevant to this topic.

    Digital Marketing Company in Chennnai

    ReplyDelete
  7. Thank you for sharing such a nice and interesting blog with us. Hope it might be much useful for us. keep on updating...!!
    seo company in india
    digital marketing company in india
    seo company in chennai
    digital marketing company in chennai

    ReplyDelete
  8. Superb. I really enjoyed very much with this article here. Really it is an amazing article I had ever read. I hope it will help a lot for all. Thank you so much for this amazing posts and please keep update like this excellent article.thank you for sharing such a great blog with us. expecting for your.
    Digital Marketing Company in India

    ReplyDelete
  9. This post is really nice and informative. The explanation given is really comprehensive and informative.. Android App Development Company in Chennai

    ReplyDelete

  10. Wonderful blog.. Thanks for sharing informative Post. Its very useful to me.

    Installment loans
    Payday loans
    Title loans

    ReplyDelete

Tweet