Tuesday, November 8, 2016

Lightning Component Framework - Approval History Lightning Component


What is Lightning Component Framework?
Simply put Lightning Components is a UI framework for developing dynamic and responsive web apps for mobile and desktop device. Like any other app framework Lightning Components is also collection of codes and services at both client side and server side.




What consists of Lightning Components?
Lightning component bundle mainly consists of the below resources



Is Lightning going to replace Visualforce?
As far as we know, Visualforce is not going away (Atleast not in the near future). Visualforce provides the mechanism for delivering template-driven web pages and email messages. In addition, developers wishing to simply utilize a basic container and maintain more control over the lifecycle of the request may still choose visualforce.

For more detailed comparison click here 

Lets see some example 
Use Case: Record page component to display approval history 

Apex Class: ApprovalComponentController

 public class ApprovalComponentController {  
       /*  
       * This method will be called by the helper function  
       * Parameter: recordId  
       * Returns: instance of wrapper class  
       */  
   @AuraEnabled  
   public static ApprovalList getApprovalData(Id recId)  
   {  
     Id recordId = recId;  
     ApprovalList approvalResultForObject = new ApprovalList();  
     List<ApprovalStepWrapper> aSW = new List<ApprovalStepWrapper>();  
     String recallApprovalProcessLink;  
     Boolean isSubmitForApproval = true;  
     for(ProcessInstance pI: getProcessHistory(recordId).values())  
     {  
       Map<Id,List<ProcessInstanceHistory>> mapOfProcessNodeIdAndProcessInstanceHistory = new Map<Id,List<ProcessInstanceHistory>>();  
       Set<Id> processNodeId= new Set<Id>();  
       for(ProcessInstanceHistory sWI:pI.StepsAndWorkitems)  
       {  
         if(processNodeId.size() ==0)  
           processNodeId.add(sWI.ProcessNodeId);  
         else if(processNodeId.size()>0 && processNodeId.contains(sWI.ProcessNodeId)!= NULL)  
           processNodeId.add(sWI.ProcessNodeId);  
       }  
       for(Id pNId: processNodeId)  
       {  
         ApprovalStepWrapper aSWr = new ApprovalStepWrapper();  
         for(ProcessInstanceHistory sWI:pI.StepsAndWorkitems)  
         {  
           if(sWI.processNodeId == pNID)  
           {  
             aSWr.listOfSteps.add(new ApprovalHistoryWrap(sWI.CreatedDate, sWI.OriginalActor.Name, sWI.StepStatus,sWI.Actor.Name));  
           }  
           if(sWI.StepStatus == 'Pending')  
           {  
             isSubmitForApproval = false;  
           }  
         }  
         aSW.add(aSWr);  
       }  
     }  
     approvalResultForObject.approvals = aSW;  
     approvalResultForObject.recordId = recordId;  
     approvalResultForObject.isSubmitForApproval = isSubmitForApproval;  
     system.debug('asw'+aSW);  
     return approvalResultForObject;  
   }  
   /*  
    * This method queries the processinstance and workitem for the record  
    * Parameter: Record ID   
    * Returns: Map of all processinstance related to the record id  
    */  
   @AuraEnabled  
   public static Map<Id,ProcessInstance> getProcessHistory(Id objectId)  
   {  
     return new Map<Id,ProcessInstance>([SELECT Id, (SELECT ID, ProcessNodeId,  
                             StepStatus,Comments,TargetObjectId,ActorId,CreatedById,IsDeleted,IsPending  
                             ,OriginalActorId,ProcessInstanceId,RemindersSent,CreatedDate, Actor.Name,  
                             OriginalActor.Name , ProcessNode.Name FROM StepsAndWorkitems order by CreatedDate DESC )   
                       FROM ProcessInstance where TargetObjectId =:objectId order by CreatedDate DESC]);  
   }  
   /*  
    * Wrapper class  
    */  
   public class ApprovalStepWrapper{  
     @AuraEnabled  
     public List<ApprovalHistoryWrap> listOfSteps {get;set;}  
     public ApprovalStepWrapper(){  
       listOfSteps = new List<ApprovalHistoryWrap>();  
     }  
   }  
        /*  
    * Wrapper class  
    */  
   public class ApprovalHistoryWrap  
   {  
     @AuraEnabled  
     public Date createdDate {get;set;}  
     @AuraEnabled  
     public string actorName {get;set;}  
     @AuraEnabled  
     public string steps {get;set;}  
     @AuraEnabled  
     public string assignedTo {get;set;}  
     public ApprovalHistoryWrap(DateTime crDate, string name, string stp, string actor)  
     {  
       createdDate = crDate.date();  
       actorName = name;  
       steps = stp;  
       assignedTo = actor;  
     }  
   }  
   /*  
    * Wrapper class  
    */  
   public class ApprovalList  
   {   
     @AuraEnabled  
     public List<ApprovalStepWrapper> approvals {get;set;}  
     @AuraEnabled    
     public Boolean isSubmitForApproval {get;set;}  
     @AuraEnabled  
     public Id recordId {get;set;}  
     public ApprovalList(){  
       approvals = new List<ApprovalStepWrapper>();  
       isSubmitForApproval = true;  
     }  
   }  
 }  


Highlights:
@AuraEnabled: The @AuraEnabled annotation enables client- and server-side access to an Apex controller method. Using this annotation makes your method visible to your lightning components.

Access wrapper class in lightning component: To access properties of your Wrapper class in your lightning component using @AuraEnabled annotation.


Lightning component: ApprovalListComp

 <aura:component controller="ApprovalComponentController" implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId" access="global" >  
      <aura:attribute name="recordId" type="Id"/>  
   <aura:handler name="init" value="{!this}" action="{!c.doInit}" />  
   <aura:attribute name="approvalList" type="object"/>  
   <ltng:require styles="{!$Resource.SLDS+'/assets/styles/salesforce-lightning-design-system-ltng.css'}" />  
   <!-- WRAPPER DIV -->  
   <div class="wk_static">  
     <!-- BODY -->  
     <div class="slds-scrollable" style="height: 300px;">  
       <table class="slds-table slds-table--bordered slds-max-medium-table--stacked">  
         <thead>  
           <tr class="slds-text-title--caps">  
             <th scope="col" >  
               <div class="slds-truncate" title="Date">Date</div>  
             </th>  
             <th scope="col" >  
               <div class="slds-truncate" title="Status">Status</div>  
             </th>  
             <th scope="col" >  
               <div class="slds-truncate" title="Assigned To">Assigned To</div>  
             </th>  
             <th scope="col" >  
               <div class="slds-truncate" title="Approver">Approver</div>  
             </th>  
           </tr>  
         </thead>  
         <tbody>  
           <!-- aura equivalent of apex:repeat -->  
           <aura:iteration items="{!v.approvalList.approvals}" var="appRec">   
             <aura:iteration items="{!appRec.listOfSteps}" var="step">  
               <tr >  
                 <td data-label="Date">  
                   <div class="slds-truncate" title="Date">{!step.createdDate}</div>  
                 </td>  
                 <td data-label="Status">  
                   <div class="slds-truncate" title="Status">{!step.steps}</div>  
                 </td>  
                 <td data-label="Assigned To">  
                   <div class="slds-truncate" title="Assigned To">{!step.assignedTo}</div>  
                 </td>  
                 <td data-label="Approver">  
                   <div class="slds-truncate" title="Approver">{!step.actorName}</div>  
                 </td>  
               </tr>  
             </aura:iteration>  
           </aura:iteration>   
         </tbody>  
       </table>  
     </div>  
   </div>  
 </aura:component>  

Highlights:
force:hasRecordId: The interface indicates the current record ID should be injected in the component's recordId attribute

<aura:iteration>: <aura:iteration> iterates over a collection of items and renders the body of the tag for each item. Data changes in the collection are re-rendered automatically on the page. aura:iteration supports iterations containing components that have server-side dependencies or that can be created exclusively on the client-side

JS Controller

 ({  
      doInit : function(component, event, helper) {  
           helper.getApprovalList(component);  
      }  
 })  

Highlights
helper.getApprovalList:  Calls helper function from a client-side controller functionHelper functions are local to a component, improve code reuse, and move the heavy lifting of JavaScript logic away from the client-side controller where possible.


JS Helper

 ({  
      getApprovalList : function(component) {  
     var action = component.get("c.getApprovalData");  
     action.setParams({  
       recId: component.get("v.recordId")  
     });  
     action.setCallback(this, function(a) {  
         component.set("v.approvalList", a.getReturnValue());  
       });  
     $A.enqueueAction(action);  
      }  
 })  


No comments:

Post a Comment