Using Dynamic Component in VisualForce Page

For some cases it might be useful to build component for visualforce page dynamically inside the code.

Take a look at the following code example of generating PageBlockTable inside the code.


public class vf_DynamicComponentExmp {  

 transient public Component.Apex.PageBlockTable table {get;set;}  

 //list of record to display  
 public list<Case> caseLst {get; set;}  

 //fields and labels to display in the page block table  
 public list<String> displayFieldLst= new list<String>{'CaseNumber', 'Subject', 'Priority', 'Status', 'ContactID'};  
 public list<String> labelFieldLst= new list<String>{'Case Number', 'Subject', 'Priority', 'Status', 'Contact'};  

 public vf_DynamicComponentExmp() {  
  String dynamicSQL='SELECT id ';  
  for(String field : displayFieldLst) {
   dynamicSQL+=', ' + field;  
  }

  dynamicSQL+=' FROM Case';  

  caseLst=Database.query(dynamicSQL);  

  table = new Component.Apex.PageBlockTable(var='rec');  
  table.expressions.value='{!caseLst}';  
    
  //add the field  
  Component.Apex.Column column;  
  Component.Apex.InputField inputField;  

  for(Integer index=0;index<displayFieldLst.size();index++) {  
   column = new Component.Apex.Column(headerValue= '' + labelFieldLst.get(index) + '');  
   inputField = new Component.Apex.InputField();  
   inputField.expressions.value = '{!rec.' + displayFieldLst.get(index) + '}';  
   column.childComponents.add(inputField);  
   table.childComponents.add(column);  
  }  
 }  

 public PageReference saveData() {  
  try {   
   update caseLst;   
  }   
  catch(Exception e) {   
   ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Error while saving ' + e));   
  }   
  return ApexPages.currentPage();   
 }  
}  

In the page we reference it by:
<apex:dynamicComponent componentValue="{!table}"/>


<apex:page controller="vf_DynamicComponentExmp">  
 <apex:pageMessages id="errors" escape="false" />   
 <apex:form >  
  <apex:pageBlock >  
   <apex:pageBlockButtons location="top" id="buttons">   
    <apex:commandButton id="Save" value="Save" action="{!saveData}" />   
   </apex:pageBlockButtons>  

   <apex:dynamicComponent componentValue="{!table}"/>   
  </apex:pageBlock>   
 </apex:form>  
</apex:page>  



The result:




Link to Approval Process Screen

When using approval process you may not specify email template.
In this case SF will use the default template for approval processes with the following structure:
http://login.salesforce.com/help/doc/en/wf_approval_settings.htm

In case you want a customise email template you need to create it.
Sometimes, even when you do create your own email template you want to have the link to the approval screen.

I'll demonstrate how it add it with approval process on Case object.

1.Create email template on Case object.
After desinging the template as needed, at the end add component:
<c:CmpApprovalURL objID="{!relatedTo.id}"/>



<messaging:emailTemplate subject="Case onHold Request" recipientType="User" relatedToType="Case">  
 <messaging:htmlEmailBody >  
  You have been requested to approve or reject this case:<br/>  
  {!relatedTo.Subject}<br/>  
  Contact: {!relatedTo.Contact.Name}<br/>  
  Priority: {!relatedTo.Priority}<br/><br/>  

  <c:CmpApprovalURL objID="{!relatedTo.id}"/>  
 </messaging:htmlEmailBody>  
</messaging:emailTemplate>  

2.Component:CmpApprovalURL.
Using String urlStr at class cls_CmpApprovalUrl


<apex:component controller="cls_CmpApprovalURL" access="global">  
 <apex:attribute name="objID" description="Obj ID" type="Id" assignTo="{!caseID}"/>  
 <a href="{!urlStr}">Log-in to approve or reject</a>  
</apex:component> 

3.Class:cls_CmpApprovalURL.
Need 2 variable :
1.Input for the CaseID
2.Output URL


public class cls_CmpApprovalURL  {  
 
 public String caseID {get; set;}  

 public String urlStr{  
  get  {  
   return cls_createApprovalURL.generateApprovalURL(caseID);  
  }}  
}  


4.Class cls_createApprovalURL
I create the function generateApprovalURL in this seperate class since it can be used for any object for any approval process.
It receive object ID, and return the correct URL for it's approval screen.


public class cls_createApprovalURL  {  
   
 public static String generateApprovalURL(String recordID)  {  
  String url='';  
  
  List<ProcessInstanceWorkitem> workItemLst =   
   [  SELECT id  FROM ProcessInstanceWorkitem  
    WHERE processInstance.TargetObjectId=:recordID];   

  if(workItemLst.size() > 0)  {  

   url='https://'+ System.URL.getSalesforceBaseUrl().getHost() +   
    '/p/process/ProcessInstanceWorkitemWizardStageManager?id=' + workItemLst[0].id;      
  }  
  return url;  
 }  
}


5.The result:

In the email received:

The link from the email:


Retire of Permission on Profiles

If you are working as a Salesforce admin/developer you've probably heard somewhere that Salesforce is planning to make a significant cha...