Pages

Friday, March 31, 2017

How to pass inner wrapper class to lightning components

Creating a inner wrapper class is common practice to create new custom data type which can be used in VF page to display information. Lightning components can not access the inner class. The reason is that apex class cannot be marked as @AuraEnabled. You can only specify @AuraEnabled annotations to methods or member variables of class.

So now if you have to pass inner wrapper class to lightning then you can convert wrapper variable into JSON and return as string to lightning component.

Below is apex class performing this operation:

public with sharing class SkRecordTypeSelectionController {
@AuraEnabled
    public static string findRecordTypes(string objName){
        string returnString='';
        string queryString='Select id, name from RecordType where sobjectType =: objName and IsActive=true';
        List<sobject> recordList= Database.query(queryString);
        List<RecordTypeWrapper> wrapperList=new List<RecordTypeWrapper>();
        for(sobject sb : recordList)  {
            RecordTypeWrapper rw=new RecordTypeWrapper();
            rw.recordTypeLabel=string.valueof(sb.get('name'));
            rw.recordTypeId=string.valueof(sb.get('id'));
            wrapperList.add(rw);
        } 
        returnString= JSON.serialize(wrapperList);
        return returnString;
    }
    public class RecordTypeWrapper{
        public string recordTypeLabel{get;set;}
        public string recordTypeId{get;set;}
    }
}

In above code, you can see that we have created List of wrapper class and store all recordType information in that. After that we are converting it into JSON and returning it as string to lightning component.

Create an attribute to store this information:

<aura:attribute name="recordTypeList" type="Object[]"/>

In lightning component, you can convert back response into JSON by using below code:

var jsonObject=JSON.parse(response.getReturnValue());

Now you set attribute value by using below code:

component.set('v.recordTypeList',jsonObject); 


Another approach


You can create separate class as wrapper and then refer it in component controller as mentioned below:

public class RecordTypeWrapper{
        @AuraEnabled
public string recordTypeLabel{get;set;}
        @AuraEnabled
public string recordTypeId{get;set;}
}

Then you can create seperate apex class to refer this wrapper:

public with sharing class SkRecordTypeSelectionController {
@AuraEnabled
    public static List<RecordTypeWrapper> findRecordTypes(string objName){
        string queryString='Select id, name from RecordType where sobjectType =: objName and IsActive=true';
        List<sobject> recordList= Database.query(queryString);
        List<RecordTypeWrapper> wrapperList=new List<RecordTypeWrapper>();
        for(sobject sb : recordList)  {
            RecordTypeWrapper rw=new RecordTypeWrapper();
            rw.recordTypeLabel=string.valueof(sb.get('name'));
            rw.recordTypeId=string.valueof(sb.get('id'));
            wrapperList.add(rw);
        } 
        return wrapperList;
    }
    
}

Now you can create an attribute in lightning component as mentioned below:

<aura:attribute name="recs" type="RecordTypeWrapper[]"/>

For sample code example explaing above approach, please refer my next blog "Lightning Component for RecordType Selection for any Sobject"

Hope this will help!!!



More Blogs>>: 
DYNAMICALLY CREATING AND DESTROYING LIGHTNING COMPONENTS    
RAISING AND HANDLING CUSTOM EVENTS IN sALESFORCE lIGHTNING    
WHY TO USE DESIGN RESOURCE AND HOW TO ADD DYNAMIC OPTION TO DATASOURCE    
FETCHING FILE FROM EXTERNAL/PUBLIC URL AND STORING IT IN SALESFORCE    

Tuesday, March 28, 2017

Different ways of testing HTTP callout in apex

As we all know that test methods do not support HTTP callout, so all test method performing callout will fail.


In order to avoid the test class failure, we mainly use Test.IsRunningTest method in apex class. By using this method, we make sure that particular block of code performing HTTP callout should not run when called by test class methods.

if(!Test.isRunningTest()){
// apex code for HTTP callout
}
but this approach will reduce your code coverage. As per salesforce, you need to have atleast 75% coverage for all your apex code.

We will now go through different options through which we can test HTTP callout and increase our code coverage.

  • Using static resource
You can store the response of your HTTP callout in text file and upload it static resource. Now you can use built in apex class StaticResourceCalloutMock or MultiStaticResourceCalloutMock to build mock response and get response from static resource.

First create an instance of StaticResourceCalloutMock:

StaticResourceCalloutMock mockCallout = new StaticResourceCalloutMock();
mockCallout.setStaticResource('StaticResourceForCallout');
mockCallout.setStatusCode(200);
mockCallout.setHeader('Content-Type', 'application/json');

Now set mock callout mode in test method by using below method:

Test.setMock(HttpCalloutMock.class, mockCallout );

After this call method which perform callout. As we have set mock test callout, apex will not perform callout and will return response from static resource.

Note: MultiStaticResourceCalloutMock helps you test different HTTP callout with different endpoint URL. you can create instance of this class and specify callout response in different static resource for different endpoints and then set this as mock callout in test method.

  • Generating mock response in test by implementing the HttpCalloutMock Interface 
Create a apex class which implements HttpCalloutMock interface. In this interface, you can specify response which will be returned if test method perform callout.

@isTest
global class HTTPMockCallout implements HttpCalloutMock {
    global HTTPResponse respond(HTTPRequest req) {
        // specify the response here
        // return response.
    }

Note:
       1. Class should be public or global which implements HttpCalloutMock
       2. You can use @IsTest on this class as this will be used only through test class. In this way it                   will not count against organization code size limit.

Now you can set mock response in test method before calling method which perform HTTP callout.

Test.setMock(HttpCalloutMock.class, new HTTPMockCallout());

Below is sample code to provide code coverage to "CalloutUtility" apex class using both approaches mentioned above


Hope this will help!!!!


More Blogs>>: 
DYNAMIC APEX IN SALESFORCE
FETCHING FILE FROM EXTERNAL/PUBLIC URL AND STORING IT IN SALESFORCE
SOQL INJECTION IN SOQL
CUSTOM METADATA AND CUSTOM SETTINGS IMPLEMENTATION TRICKS
SMART TABLE USING ANGULARJS IN VISUALFORCE PAGE
VISUALFORCE COMPONENT FOR RECORD STATUS BAR

Tuesday, March 14, 2017

Localizing Content in Salesforce Lightning

Localizing plays important role when you enable multiple languages, currency and uses different date formats in salesforce.

Below are different options which you can use to localize your contents in Lightning.
  • Using Custom Label which can be translated into multiple languages.
  • Format number and date using <lightning:formattedDateTime> and <lightning:formattedNumber> components.
  • Using $Locale environment variable along with lightning localization service to format number and date formats in string expressions.


Using Custom Labels


As we know that custom labels can be translated in any language supported by salesforce. Custom label helps in displaying message to users in different languages. Remember, labels can contain only 1000 characters.

In order to use custom labels for multiple languages, you have to enable translation workbench. After this you can different translation text for labels.

Using labels in markup

You can access labels in lightning mark up by using below syntax:
{!$Label.namespace.labelName}

You can use "c" as namespace if your org uses default namespace.

Using labels in javascript function

You can use labels in controller/helper function by using the $A.get() function as mentioned below:

$A.get("$Label.namespace.labelName");

Formating Date, Time and Numbers


Localizing Dates in Markup

In <ui:outputDateTime>, you can specify the langLocale attribute and format to display datatime in required format. Below is an example:

<ui:outputDateTime value="2017-02-10T00:17:10:10.00Z" langLocale="us" format="M-d-y"/>

This will return "2-10-2017"

<ui:outputDateTime value="2017-02-10T00:17:10:10.00Z" langLocale="us" />

This will return "Feb 10, 2017 5:10:10 PM"

Using javascript to localize the dates

you can use localization service to format datetime values. Below is sample code:

var localDateFormat = $A.get("$Locale.dateFormat");
var userLocalLang = $A.get("Locale.langLocale");
var actualDtae = $A.localizationService.formatDateTime(new date(),localDateFormat);
//Now format datetime value
var requiredformat = "MMMM d, yyyy";
var formattedDate = $A.localizationService.formatDate(
actualDtae, 
requiredformat,
userLocalLang
);  
//Now you use formattedDate to set value in controller

Localizing Numbers in Markup

<ui:outputNumber> automatically reads user's SFDC locale setting on user detail page and formats number automatically.


For example:
<ui:outputNumber value="100002"/>

Output (if locale in user details page is English(United States))= 100,002
Output (if locale in user details page is German(Germany))= 100.002

You can also use format attribute to format numbers. Below is example:

<ui:outputNumber value="100002" format="0,000.00"/>
output will be = 100.002,00

Using javascript to localize the numbers

You can use different functions of localizationService to format numbers. Below are few exmaples:

$A.localizationSerevice.formatCurrency(100.10);
//dispaly output as $100.10

$A.localizationSerevice.formatNumber(1000.10,'0,000.00');
//dispaly output as 1,000.10

$A.localizationSerevice.formatPercent(.56);
//dispaly output as 56%



Using Locale Global Variable


$Locale global variable return information about user's locale. Below are few example:

{!locale.language}   
//returns language  code like "en', "fr" etc

{!locale.timezone}
//return time zone Id like America/New_York

{!locale.langLocale}
//return users locale id like "en_US", "en_GB" etc

In javascript, you can access this global variable by using $A.get() methods. Below is example to get user language:

var localelang= $A.get("$Locale.language");
//this will return language code like "en', "fr" etc

Hope this will help!!


More Blogs>>: 
DYNAMICALLY CREATING AND DESTROYING LIGHTNING COMPONENTS    
RAISING AND HANDLING CUSTOM EVENTS IN sALESFORCE lIGHTNING    
WHY TO USE DESIGN RESOURCE AND HOW TO ADD DYNAMIC OPTION TO DATASOURCE    
FETCHING FILE FROM EXTERNAL/PUBLIC URL AND STORING IT IN SALESFORCE    

Friday, March 10, 2017

Generating random number between two numbers and finding string value from list of values randomly

As we know in apex, math.random() function gives random number greater than or equal to zero and less than 1. This function can be used to generate random number in apex.

I have created a apex class which can be used to find a random between 2 numbers and this can be extended later to find random string from list of strings values or to select random picklist value for picklist field while creating test data in test class.

Below is apex class code:


In order to find random picklist value, use apex describe to store all picklist values in List and then pass that list to "findRandomStringFromList" method in RandomUtility apex class.


Hope this will help!!!


More Blogs>>: 
DYNAMIC APEX IN SALESFORCE
FETCHING FILE FROM EXTERNAL/PUBLIC URL AND STORING IN SALESFORCE
SOQL INJECTION IN SOQL
CUSTOM METADATA AND CUSTOM SETTINGS IMPLEMENTATION TRICKS
SMART TABLE USING ANGULARJS IN VISUALFORCE PAGE
VISUALFORCE COMPONENT FOR RECORD STATUS BAR

Monday, March 6, 2017

Why to use design resource in Lightning bundle and how to add dynamic Options in datasource for Design Component

In Lightning Bundle, design resource helps in displaying components attributes in lightning app builder so that user can select attribute values and component behaves accordingly.

When to use design resource in lightning?


If you create a component which will be used in standalone lightning app, then you can pass attributes values for component and component will work accordingly but what if you component will be used in Lightning app builder while creating a lightning page. In this case how you will pass attributes values apart from default values.
So design resource helps you to specify some values to attributes which can be selected by Admin in lightning app builder. Below are 2 scenarios in which you should specify attributes in design resource otherwise they will not appear for users in Lightning App Builder.
  1. Required attributes which have default values
  2. Attributes which are not marked as required in component definition.
Let me explain this with an example.

I have created a component which display records from different objects. As of now for, I am going to display only record Id and name fields in table.

GenericListView.cmp

<aura:component controller="GenericListViewController"  implements="flexipage:availableForAllPageTypes" access="global" >
<aura:attribute name="objectName" type="String" default="Contact" required="true"/>
    <aura:attribute name="recList" type="List" />
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    
    <aura:if isTrue="{!v.recList.length > 0}">
        <table class="slds-table slds-table--bordered slds-table--cell-buffer">
        <thead>
            <tr class="slds-text-title--caps">
            <th scope="col">RecordId</th>
            <th scope="col">Name</th>
            </tr>
        </thead>
        <aura:iteration items="{!v.recList}" var="item">
        <tr>
        <td> {!item.Id}</td>
            <td> {!item.Name}</td>
        </tr>
        </aura:iteration>
    </table>
    </aura:if>
</aura:component>

GenericListViewController.js

({
doInit : function(component, event, helper){
        var objname=component.get("v.objectName");
        //alert('objname:'+objname);
        var params ={}
        helper.callServer(
            component,
            "c.findRecords",
            function(response){
                //alert('Response from controller for opportunities:'+JSON.stringify(response));
                component.set("v.recList",response);
            },
            {objectName: objname}
        );
    }
})

GenericListViewHelper.js

({
callServer : function(component, method, callback, params) {
        //alert('Calling helper callServer function');
var action = component.get(method);
        if(params){
            action.setParams(params);
        }
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                callback.call(this,response.getReturnValue());
            }else if(state === "ERROR"){
                alert('Problem with connection. Please try again.');
            }
        });
$A.enqueueAction(action);
    }
})

GenericListViewController apex class

Global class GenericListViewController{
@auraEnabled
    public static List<sobject> findRecords(string objectName){
        string queryString ='';
        List<sobject> returnList=new List<sobject>();
        if(objectName !=null ){
    queryString='select Id, name from '+ objectName + '  Order by lastmodifiedDate DESC Limit 10';
        }else{
            queryString='select Id, name from Contact   Order by lastmodifiedDate DESC Limit 10';  
        }
        system.debug('**queryString:'+queryString);
        returnList=database.query(queryString);
    return returnList;
    }
}

Now if you use this component in Lightning app builder, then you will not get any option to specify "ObjectName" attribute value and component will take default value which is "Contact" as specified in component definition.

Now if you want that admin will get option to select ObjectName so that component will display records from that object, then add attribute in design resource. Below is sample code:

GenericListView.design

<design:component >
<design:attribute name="objectName" datasource="Contact,Account,Opportunity" />
</design:component>

After saving this file you will get option to select object name in app builder.

Note:
  1. What ever you specify in datasource seperated by comma will appear as dropdown in Lightning app builder.
  2. Design resource supports only text, boolean and int.

How to add dynamic options to datasource in design components?


You have to follow below steps to implement this:
  • Create a Apex class which will be used to provide dynamic values. Apex class must extend the VisualEditor.DynamicPickList abstract class.
  • Specify datasource as this apex class while creating attribute in design resorce.

GenericListViewController apex class

Global class GenericListViewController extends VisualEditor.DynamicPickList{
@auraEnabled
    public static List<sobject> findRecords(string objectName){
        string queryString ='';
        List<sobject> returnList=new List<sobject>();
        if(objectName !=null ){
    queryString='select Id, name from '+ objectName + '  Order by lastmodifiedDate DESC Limit 10';
        }else{
            queryString='select Id, name from Contact   Order by lastmodifiedDate DESC Limit 10';  
        }
        system.debug('**queryString:'+queryString);
        returnList=database.query(queryString);
    return returnList;
    }
    global override VisualEditor.DataRow getDefaultValue(){
        VisualEditor.DataRow defaultValue = new VisualEditor.DataRow('contact', 'Contact');
        return defaultValue;
    }
    global override VisualEditor.DynamicPickListRows getValues() {
        Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
        VisualEditor.DynamicPickListRows  myValues = new VisualEditor.DynamicPickListRows();
        VisualEditor.DataRow value1 = new VisualEditor.DataRow('Contact', 'Contact');
        myValues.addRow(value1);
        VisualEditor.DataRow value2 = new VisualEditor.DataRow('Account', 'Account');
        myValues.addRow(value2);
        VisualEditor.DataRow value3 = new VisualEditor.DataRow('Lead', 'Lead');
        myValues.addRow(value3);
        //Or you use object describe ti find all object details
        /*for(String ss1: schemaMap.keyset()){
            Schema.SObjectType objToken=schemaMap.get(ss1);
            Schema.DescribeSObjectResult objDescribe=objToken.getdescribe();
            VisualEditor.DataRow value11 = new VisualEditor.DataRow(objDescribe.getLabel(), objDescribe.getName());
            myValues.addRow(value11);
        }
*/
        return myValues;
    }
}

In this class, I am specifying Contact, Account and Lead object. You can use object describe if you want to display all object name from your org or you can add any values.

Modify you GenericListView.design code as shown below:

<design:component >
<design:attribute name="objectName" datasource="apex://GenericListViewController"/>
</design:component>

Now if you use this component in Lightning app builder then, you will get Contact, Account and Lead as Object name attribute options;



In this way you can pass values from apex class to datasource in design attributes.

Hope this will help!!!

Looking forward for everyone feedback..


More Blogs>>: 
DYNAMICALLY CREATING AND DESTROYING LIGHTNING COMPONENTS    
RAISING AND HANDLING CUSTOM EVENTS IN sALESFORCE lIGHTNING    
DYNAMIC APEX IN SALESFORCE    
FETCHING FILE FROM EXTERNAL/PUBLIC URL AND STORING IT IN SALESFORCE    

Friday, March 3, 2017

Raising and Handling Custom Events in Salesforce Lightning

Events in Lightning plays very important role when we have to communicate between different components. Suppose a component is present inside another component and we want to change behavior of parent component based on actions on inner/child components.

I will try to explain this concept with real life example.

Suppose you are driving and suddenly you witness an accident and you need to notify the nearest hospital about this accident so that they can send ambulance for help.



In this scenario, car accident is an event which happened. You are notifier who witness this event (register this event). After witnessing this event, you are going to fire an event through which you will send some message to near by hospital (other component) so that it will perform some action by sending ambulance for help.

Now if we need to understand in Lightning terms, then we create different events which will be used by components to interact between them. Below are different steps for this event handling:
  • Create a Lightning event and create different attributes in it which can be used to pass information between components.
  • Component which want to fire an event needs to first register for an event by using <aura:registerEvent>. Then only it can fire an event and other component can receive it.
  • Component which wants to receive information will handle the event using <aura:handler> and type as Ligthning Event which we create.
Below image will help you to understand custom events using lightning code:



Below is complete code:


If you preview your app, then you will see below output:


Hope this will help you to understand the custom event handling...


More Blogs>>: 
DYNAMICALLY CREATING AND DESTROYING LIGHTNING COMPONENTS    
BOX AND SALESFORCE INTEGRATION    
INTEGRATING BOX FILE PICKER WITH SALESFORCE    
FETCHING FILE FROM EXTERNAL/PUBLIC URL AND STORING IT IN SALESFORCE