Category Archives: Salesforce

Lightning Icons in Visualforce Page

Salesforce provides 5 different kind of Icons (Standart, Custom, Utility, Doctype, Action) which can be used in Lightning component and Visualforce page. Find SLDS Icons here.

Example:
Instead of uploading the Lightning Design System as a static resource, we can include apex:slds inside the head tag of Visualforce page to use Lightning Design System stylesheets in the page.

Visualforce Page:

<apex:page showHeader="false" standardStylesheets="false" sidebar="false" docType="html-5.0" >
    
    <head>
        <apex:slds/> 
    </head>
    
    <body class="slds-scope">
        <div class="slds-m-around--xx-large">
            <article class="slds-card">
                <div class="slds-card__body">
                    <table class="slds-table slds-table_bordered">
                        <thead>
                            <tr class="slds-text-heading--label">
                                <th scope="col">NAME</th>
                                <th scope="col">CATEGORIES</th>
                                <th scope="col">ICON</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td scope="row">Account</td>
                                <td scope="row">Standard</td>
                                <td scope="row">
                                    <span class="slds-icon_container slds-icon-standard-account" >
                                        <svg aria-hidden="true" class="slds-icon slds-icon--small">
                                            <use xmlns:xlink="http://www.w3.org/2000/xlink" 
                                                 xlink:href="/apexpages/slds/latest/assets/icons/standard-sprite/svg/symbols.svg#account">
                                            </use>
                                        </svg>
                                        <span class="slds-assistive-text">Account</span>
                                    </span>
                                </td>
                            </tr>
                            <tr>
                                <td scope="row">Custom1</td>
                                <td scope="row">Custom</td>
                                <td scope="row">
                                    <span class="slds-icon_container slds-icon-custom-custom1" >
                                        <svg aria-hidden="true" class="slds-icon slds-icon--small">
                                            <use xmlns:xlink="http://www.w3.org/2000/xlink" 
                                                 xlink:href="/apexpages/slds/latest/assets/icons/custom-sprite/svg/symbols.svg#custom1">
                                            </use>
                                        </svg>
                                        <span class="slds-assistive-text">Custom1</span>
                                    </span>
                                </td>
                            </tr>
                            <tr>
                                <td scope="row">Email</td>
                                <td scope="row">Utility</td>
                                <td scope="row">
                                    
                                    <span class="slds-icon_container slds-icon-utility-email" >
                                        <svg aria-hidden="true" class="slds-icon slds-icon-text-default">
                                            <use xmlns:xlink="http://www.w3.org/1999/xlink" 
                                                 xlink:href="/apexpages/slds/latest/assets/icons/utility-sprite/svg/symbols.svg#email">
                                            </use>
                                        </svg>
                                        <span class="slds-assistive-text">Email</span>
                                    </span>
                                    
                                </td>
                            </tr>
                            <tr>
                                <td scope="row">Priority</td>
                                <td scope="row">Action</td>
                                <td scope="row">
                                    <span class="slds-icon_container slds-icon-action-priority" >
                                        <svg aria-hidden="true" class="slds-icon  slds-icon--x-small">
                                            <use xmlns:xlink="http://www.w3.org/1999/xlink" 
                                                 xlink:href="/apexpages/slds/latest/assets/icons/action-sprite/svg/symbols.svg#priority">
                                            </use>
                                        </svg>
                                        <span class="slds-assistive-text">Priority</span>
                                    </span>
                                    
                                </td>
                            </tr>
                            <tr>
                                <td scope="row">CSV</td>
                                <td scope="row">Doctype</td>
                                <td scope="row">
                                    <span class="slds-icon_container slds-icon-doctype-csv" >
                                        <svg aria-hidden="true" class="slds-icon ">
                                            <use xmlns:xlink="http://www.w3.org/1999/xlink" 
                                                 xlink:href="/apexpages/slds/latest/assets/icons/doctype-sprite/svg/symbols.svg#csv">
                                            </use>
                                        </svg>
                                        <span class="slds-assistive-text">CSV</span>
                                    </span>
                                    
                                </td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </article>
        </div>
    </body>
</apex:page>

Output:

Invoke Batch Apex From Another Batch Apex

Only in batch class finish method, We can call another batch class. If you will call another batch class from batch class execute and start method, then Salesforce will throw below runtime error.

 
System.AsyncException: Database.executeBatch cannot be called from a batch start, batch execute, or future method.

Here in below example there are two batch classes “Batch1” and “Batch2“.
I want to execute “Batch2” after finish the “Batch1“.
So, I’m calling “Batch2” class in “Batch1” finish method.

Batch1:

global class Batch1 implements Database.Batchable<Sobject>{

	//Method to get the data to be proceesed  
	global database.Querylocator Start(Database.BatchableContext bc){
		String query = 'Select Id, Name From Account Limit 1000';
		return Database.getQueryLocator(query);
	}


	//Method to execute the batch
	global void execute(Database.BatchableContext bc, Sobject[] scope){
		for(Sobject s : scope){ 
		Account a = (Account)s;
			// TO DO
			// add your logic 
		}
	}

	//Method to be called after the excute
	global void finish(Database.BatchableContext bc){
		//Add your start code for the other batch job here
		Database.executeBatch(new Batch2());
	}
}

Batch2:

global class Batch2 implements Database.Batchable<Sobject>{

	//Method to get the data to be proceesed  
	global database.Querylocator start(Database.BatchableContext bc){
		string query = 'Select Id, Name From Contact Limit 1000';
		return Database.getQueryLocator(query);
	}


	//Method to execute the batch
	global void execute(Database.BatchableContext bc, Sobject[] scope){
		for(Sobject s : scope){ 
		Contact c = (Contact)s;
			// TO DO
			// add your logic 
		}
	}

	//Method to be called after the excute
	global void finish(Database.BatchableContext bc){

	}
}

Marquee Text In Salesforce Lightning Component

Lightning Component (Sample.cmp):

<!--Sample.cmp--> 
<aura:component implements="flexipage:availableForAllPageTypes">
    <div class="marquee">
        <p>
            <a title="Welcome to Biswajeet Samal's Blog" href="http://biswajeetsamal.com/blog" target="_blank">Welcome to Biswajeet Samal's Blog</a>
        </p>
    </div>
</aura:component>

Lightning Component Style (Sample.css):

.marquee.THIS {
    width: 100%;
    line-height: 50px;
    color: white;
    white-space: nowrap;
    overflow: hidden;
    box-sizing: border-box;
    background-color: red;
}

.marquee.THIS p {
    display: inline-block;
    padding-left: 100%;
    animation: marquee 20s linear infinite;
    font-size:30px;
}

@keyframes marquee {
    0%   { transform: translate(0, 0); }
    100% { transform: translate(-100%, 0); }
}

Output:

Custom Validation For Lightning Field Value in Lightning

Component :

<aura:component>    
    <div class="slds-m-around--xx-large">
        <div class="slds-form--stacked">
            <div class="slds-form-element">  
                <div class="slds-form-element__control">
                    <ui:inputNumber aura:id="inputAge" label="Enter your age" class="slds-input"/>
                </div>
            </div>
            <div class="slds-m-around--medium">
                <button class="slds-button slds-button--brand" onclick="{!c.validateAge}">Validate Age</button>
            </div>
        </div>
    </div>  
</aura:component>

Component JS Controller :

({
    validateAge : function(component, event, helper) {
        var inputAge = component.find('inputAge');
        var ageValue = inputAge.get('v.value');
        if(parseInt(ageValue) < 18){
            inputAge.set("v.errors", [{message:"Age should be more than 18...!!"}]);
            return;
        }
    }
})

Output :

Lightning Component Client Side Pagination

Pagination Component:
Create a new Lightning Component Pagination.cmp.

<!--Pagination.cmp-->
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" 
                controller='PaginationController'
                access="global" >
    
    <!-- Attribute Declration For Pagination -->
    <aura:attribute name="ContactData" type="Object"/>
    <aura:attribute name="columns" type="List"/>
    
    <aura:attribute name="isSending" type="boolean" />
    
    <!-- Attribute Declration For Pagination -->
    <aura:attribute name="PaginationList" type="Contact"/>
    <aura:attribute name="startPage" type="Integer" />
    <aura:attribute name="endPage" type="Integer"/>
    <aura:attribute name="totalRecords" type="Integer"/>
    <aura:attribute name="pageSize" type="Integer" default="10"/>
    <!-- Attribute Declration For Pagination End-->
    
    <aura:handler name="init" value="{! this }" action="{! c.doInit }"/>
    
    <!-- Spinner Start, show the loading screen while 
   Client side controller(JS) is communicating with Server Side(APEX) controller -->
    <aura:if isTrue="{!v.isSending}">
        <div class="slds-spinner_container">
            <div class="slds-spinner--brand slds-spinner slds-spinner--large" role="alert">
                <span class="slds-assistive-text">Loading</span>
                <div class="slds-spinner__dot-a"></div>
                <div class="slds-spinner__dot-b"></div>
            </div>
        </div>
    </aura:if>
    <!-- Spinner End -->
    
    <div class="slds-page-header">
        <div class="slds-media">
            <div class="slds-media__figure">
                <span class="slds-icon_container slds-icon-standard-opportunity" 
                      title="Description of icon when needed">
                    
                </span>
            </div>
        </div>
    </div>
    
    <div class="slds-m-top_medium" >
        <lightning:datatable data="{! v.PaginationList }" class="slds-m-top_medium"
                             columns="{! v.columns }" 
                             keyField="id"
                             onrowselection="{! c.getSelectedName }"/>	
        <br/>
        <lightning:buttonGroup >
            <lightning:button label="Previous" disabled="{!v.startPage == 0}"  
                              onclick="{!c.previous}" variant="brand"
                              iconName='utility:back'/>
            &nbsp; &nbsp; &nbsp;
            <lightning:button label="Next" disabled="{!v.endPage >= v.totalRecords}" 
                              onclick="{!c.next}" variant="brand"
                              iconName='utility:forward' iconPosition='right'/>
        </lightning:buttonGroup>
    </div>
</aura:component>

Pagination JavaScript Controller:
Now create below JavaScript PaginationController.js controller for above Pagination.cmp component.

({
    doInit: function (component, event, helper) {
        // Set the columns of the Table 
        component.set('v.isSending',true);
        component.set('v.columns', [
            {label: 'Name', fieldName: 'Name', type: 'text', sortable : true},
            {label: 'Email', fieldName: 'Email', type: 'email', sortable : true},
            {label: 'Phone', fieldName: 'Phone', type: 'phone', sortable : true}]);
        helper.doFetchContact(component);
    },
    getSelectedName: function (component, event) {
        var selectedRows = event.getParam('selectedRows');
        // Display that fieldName of the selected rows
        for (var i = 0; i < selectedRows.length; i++){
            alert("You selected: " + selectedRows[i].Name);
        }
    },
    next: function (component, event, helper) {
        helper.next(component, event);
    },
    previous: function (component, event, helper) {
        helper.previous(component, event);
    }
})

Pagination JavaScript Controller Helper:
Now create below JavaScript PaginationHelper.js helper for above PaginationController.js component.

({
    /*
     * Initially this Method will be called and will fetch the records from the Salesforce Org 
     * Then we will hold all the records into the attribute of Lightning Component
     */
    doFetchContact : function(component) {
        var action = component.get('c.getContacts');
        action.setCallback(this, function(response){
            var state = response.getState();
            if(state === 'SUCCESS' && component.isValid()){
                var pageSize = component.get("v.pageSize");
                // hold all the records into an attribute named "ContactData"
                component.set('v.ContactData', response.getReturnValue());
                // get size of all the records and then hold into an attribute "totalRecords"
                component.set("v.totalRecords", component.get("v.ContactData").length);
                // set star as 0
                component.set("v.startPage",0);
                
                component.set("v.endPage",pageSize-1);
                var PaginationList = [];
                for(var i=0; i< pageSize; i++){
                    if(component.get("v.ContactData").length> i)
                        PaginationList.push(response.getReturnValue()[i]);    
                }
                component.set('v.PaginationList', PaginationList);
                component.set('v.isSending',false);
            }else{
                alert('ERROR');
            }
        });
        $A.enqueueAction(action);
    },
    /*
     * Method will be called when use clicks on next button and performs the 
     * calculation to show the next set of records
     */
    next : function(component, event){
        var sObjectList = component.get("v.ContactData");
        var end = component.get("v.endPage");
        var start = component.get("v.startPage");
        var pageSize = component.get("v.pageSize");
        var Paginationlist = [];
        var counter = 0;
        for(var i=end+1; i<end+pageSize+1; i++){
            if(sObjectList.length > i){
                Paginationlist.push(sObjectList[i]);
            }
            counter ++ ;
        }
        start = start + counter;
        end = end + counter;
        component.set("v.startPage",start);
        component.set("v.endPage",end);
        component.set('v.PaginationList', Paginationlist);
    },
    /*
     * Method will be called when use clicks on previous button and performs the 
     * calculation to show the previous set of records
     */
    previous : function(component, event){
        var sObjectList = component.get("v.ContactData");
        var end = component.get("v.endPage");
        var start = component.get("v.startPage");
        var pageSize = component.get("v.pageSize");
        var Paginationlist = [];
        var counter = 0;
        for(var i= start-pageSize; i < start ; i++){
            if(i > -1){
                Paginationlist.push(sObjectList[i]);
                counter ++;
            }else{
                start++;
            }
        }
        start = start - counter;
        end = end - counter;
        component.set("v.startPage",start);
        component.set("v.endPage",end);
        component.set('v.PaginationList', Paginationlist);
    }
})

Pagination Apex Controller:
Create below apex controller to use it in Pagination.cmp component.

public class PaginationController {
    @AuraEnabled
    public static List<Contact> getContacts(){
        List<Contact> contactList = new List<Contact>();
        contactList = [SELECT Id, Name, Email, Phone From Contact LIMIT 50];
        return contactList;
    }
}

Pagination App:

<!--PaginationApp.app-->
<aura:application extends="force:slds">
    <c:Pagination />    
</aura:application>

Output: