Blog Categories

Posted by on Sep 14, 2016 in Blog Series, Featured Blogs, Learn Salesforce Lightning with Examples, Tutorials | 6 comments

Learn Salesforce Lightning with Examples – Part 3 (Display and Select list of records using Wrapper Class in Lightning Component)

Learn Salesforce Lightning with Examples – Part 3 (Display and Select list of records using Wrapper Class in Lightning Component)

Learn Salesforce Lightning with Examples – Part 3 ( Display and Select list of records using Wrapper Class in Lightning Component) is the third part of the series – “Learn Salesforce Lightning with Examples” where We would share the key practical examples and experience with lightning.We are focusing on Lightning Components for now.

Background,Blog Contributors and Pre-Requisites

To get started for this blog you need to fulfill all the Pre-requisites mentioned here.In this link,you will also get to know the background and blog contributors for this series.

Display and Select list of records using Wrapper Class in Lightning Component

Business Case:

Adam is working as a Senior Application Developer in Universal Containers. Company wants to move their traditional (classic version )recruitment app to lighting. Adam needs to do a Proof of Concept by building a custom lighting component for creating the Candidate’s record into Salesforce. Now that he has created the first and second part which is explained here,He would like to showcase even users know how to display a list of records and select couple of them and bring them into  Apex and perform any action they want.

Solution:

Adam decides to show position records and decided to create the flow in such a way that the wrapper is used to display the list of positions and wrapper is used again to perform apex operations for selected records.Adam just add a debug log in Apex for demonstrate purposes however he can do any apex operation there as per the client requirements later.

Before getting started,Adam makes sure that he doesn’t miss any pre-requisites mentioned here.Below are the steps Adam takes for creating the solution after completing the pre-requisites.If you have followed my previous blogs,then you just need to update the components and follow these steps(Please note that if you just copy paste the complete code then you need not follow my previous blog,but I would insist you to do so if you want to learn in details):

  1. Create 3-4 dummy records for position object for demo purpose.
  2. Create New Lightning Component to display and select the list of position records.
  3. Create a common wrapper class to define the wrapper.Also,We would add all the wrapper classes here in future.
  4. Create new apex class to add the apex logic for this newly created lightning component.
  5. Send data into JSON format and deserialize the JSON in apex class.
  6. Test and host lightning component in app(ManageCandidate.app) and debug logs.

Create dummy position records

You need to set up the data to display ,so make sure you have set up some dummy data for the same.

Create lightning component,its controller and helper

You have to create a lightning component which will be used to display the list of position records and select the records to perform apex action.You have to add different code for the Here is the code for lightning component,its controller and its helper:

Lightning component code

<!--
DISCLAIMER:
THIS CODE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<!--
          ** Component Details***
         Name: DisplayPositions
         Type: Lightning Component 
         Purpose: Component to display position records
-->
<aura:component controller="DisplayPosition" implements="force:appHostable,
														 flexipage:availableForAllPageTypes,
														 flexipage:availableForRecordHome,
														 force:hasRecordId,forceCommunity:availableForAllPageTypes" 
				access="global" >
    <ltng:require styles="/resource/bootstrap/css/bootstrap.min.css" 
				  scripts="/resource/bootstrap/js/jquery-2.js,/resource/bootstrap/js/bootstrap.min.js" />
    <aura:attribute name="lstPositions" 
					type="CommonWrapperClass.DisplayPositionRecords[]" />	
    
    <!--- on initialization of component init event will fire and doInit action will execute-->
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    
    
    <div class="container">
        <h2>Postions</h2>
        <table class="table table-striped">
            <thead>
                <tr>
                    <th></th>
                    <th>Position</th>
                    <th>Status</th>
                </tr>
            </thead>
            <tbody>
                <!-- TO Check if list is not empty-->
                <aura:if isTrue="{!!empty(v.lstPositions)}">
                    <aura:iteration var="position" items="{!v.lstPositions}" >
                        <tr>
                            <td><ui:inputCheckbox value="{!position.isSelected}"/></td>
                            <td><ui:outputText value="{!position.positionTitle}"/></td>
                            <td><ui:outputText value="{!position.status}"/></td>
                        </tr>
                    </aura:iteration>
                </aura:if>
            </tbody>
        </table>
        
        <ui:button class="btn btn-default" press="{!c.doSomething}">Perform Action</ui:button>
        
    </div>
    
</aura:component>
 

Lightning component controller code

/*
 * DISCLAIMER:
THIS CODE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * */
/************************************************************
 Lightning Controller  Details
 Name: DisplayPositionsController.js
 Type: Lightning Controller 
 Purpose: Controller for  lightning component 
		  DisplayPositions.cmp
 ***********************************************************/
({
    doInit : function(component, event, helper) {
        helper.getPosition(component);
    },
    
    doSomething : function(component, event, helper) {
        
        var lstPositions = component.get("v.lstPositions");
        
        //To check if list is not empty or null
        if(!$A.util.isEmpty(lstPositions) && !$A.util.isUndefined(lstPositions)){
            
            //Calling the Apex Function
            var action = component.get("c.performAction");
                                  
            //Json Encode to send the data to Apex Class
            var positionRecords = JSON.stringify(lstPositions);
            //Setting the Apex Parameter
            action.setParams({
                positionRecords : positionRecords
            });
            
            //Setting the Callback
            action.setCallback(this,function(a){
                //get the response state
                var state = a.getState();
                
                //check if result is successfull
                if(state == "SUCCESS"){
                    
                    //Perform Action after the result
                    alert('Success in calling server side action');
                    
                } else if(state == "ERROR"){
                    alert('Error in calling server side action');
                }
            });
            
            //adds the server-side action to the queue        
            $A.enqueueAction(action);
            
        }
        
        
    }
})
 

Lightning component helper code

({
	getPosition : function(component) {
		
        var action = component.get("c.getPositionRecords");
        
        //Setting the Callback
            action.setCallback(this,function(a){
                //get the response state
                var state = a.getState();
                
                //check if result is successfull
                if(state == "SUCCESS"){
                    var result = a.getReturnValue();
                    if(!$A.util.isEmpty(result) && !$A.util.isUndefined(result))
                    	component.set("v.lstPositions",result);
                } else if(state == "ERROR"){
                    alert('Error in calling server side action');
                }
            });
            
            //adds the server-side action to the queue        
            $A.enqueueAction(action);
	}
})
 

Create a common wrapper class

Create a wrapper class where you can store all relevant wrapper classes for this series.For now,add a wrapper class to hold position record data.A boolean variable isSelected is added which is used for referring the selected records from lightning screen.Here is code snippet:

public class CommonWrapperClass {


    /*******************************************/
    /* Wrapper class to display Position      */
    /*****************************************/
    
    public class DisplayPositionRecords {
        
        @AuraEnabled public boolean isSelected;
        @AuraEnabled public string positionTitle;
        @AuraEnabled public string status;
        @AuraEnabled public string positionId;
        
        public DisplayPositionRecords(){
            isSelected = false;
            positionTitle = '';
            status = '';
        }
    }
}
 

Create apex class

Create new apex class to add the apex logic for this newly created lightning component.The apex logic will :

  • fetch position records and set them into wrapper
  • deserialize the data received in JSON format from lightning controller.
  •  set up debug logs to display/test the requirements.

/************************************************************
 Name: DisplayPosition
 Type: Apex Class  
 Purpose: Apex Class  for  lightning component 
		  DisplayPosition.cmp
 ***********************************************************/
public class DisplayPosition {
    
     @AuraEnabled
    public static List<CommonWrapperClass.DisplayPositionRecords> getPositionRecords() {
        
        List<CommonWrapperClass.DisplayPositionRecords> lstPositionRecords = 
		new List<CommonWrapperClass.DisplayPositionRecords>();
        
        List<Position__c> lstPositions =  [SELECT Id, Name, Status__c FROM Position__c];
        
        if(lstPositions != null && lstPositions.size() > 0){
            
            for(Position__c position : lstPositions){
                
                CommonWrapperClass.DisplayPositionRecords positionRecord = 
				new CommonWrapperClass.DisplayPositionRecords();
                positionRecord.positionId = position.Id;
                positionRecord.positionTitle = position.Name;
                positionRecord.status = position.Status__c;
                
                lstPositionRecords.add(positionRecord);
            }
            
        }
        
        
        return lstPositionRecords;

    }    
    @AuraEnabled
    public static void performAction(string positionRecords) {
        
        if(!string.isBlank(positionRecords)){
            
            List<CommonWrapperClass.DisplayPositionRecords> lstPositionRecords = 
			(List<CommonWrapperClass.DisplayPositionRecords>)
			System.JSON.deserialize(positionRecords,List<CommonWrapperClass.
			DisplayPositionRecords>.class);
            system.debug('Debug for Dsiplaying all the records
			: lstPositionRecords'+lstPositionRecords);    
            //Perform Operation with records 
            for(CommonWrapperClass.DisplayPositionRecords objPositionRecords:lstPositionRecords)
            {
                if(objPositionRecords.isSelected)
                {
                    //Play with selected Records here                   
                    system.debug('Selected Record :'+objPositionRecords);
                }
            }
                
        }
        
    }


}
 

Host and test the application

You need to host the component into the application : managecandidate.app

<!--
          ** Application Details***
         Name: ManageCandidate
         Type: Lightning Application 
         Purpose: Aplciation to host the lightning components
-->
<aura:application >

    <!--
    <aura:dependency resource="c:CreateCandidateRecord" />
    <c:CreateCandidateRecord />
	-->
    <aura:dependency resource="c:DisplayPositions" />
    <c:DisplayPositions />
    
</aura:application>

Now just access the app by using the URL in this format : https://{Domain Name}.lightning.force.com/c/{App Name}.app

display-and-select 1

Now select any number of records and then hit the Perform Action button:

2

Now go to debug log and check the debug log used in apex class for showing the list of all records and the selected records:

 

3-debug-log-1

Just search for the debug statement for the list of position records in wrapper:

4-debug-log-2

Now just search for the debug statement used in apex for selected records and you will find that selected records are ready to be used for apex logic by just differentiating them with a Boolean value:

5-debug-log-3

You can also download the code from the github repository here.

Hope you enjoyed the blog!If you have missed any,then you can go and check here for complete series. Stay tuned and there will be more examples to come ..