Sunday, October 13, 2019

Export to csv in lightning component

Today in this blog post we will see how to export data to csv in lightning component.

Object in Consideration: CASE
Filter on Field: Status

We will be displaying Case Status filter to user and we will be allowing user to select the Case Status value. Based on the value selected in Case Status filter we will be displaying data to user. User can now navigate across the displayed data. User can select record which user wants to export from the same or the different page while navigating from one page to another page as shown in the below image. User can select all the record at once as well if user wants to export all records being displayed.

Export to csv in lightning component



CaseExtractComp.cmp

<aura:component controller="caseExtractCompController" implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,force:lightningQuickAction" access="global" >
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <aura:attribute name="navigateParameter" type="string" default="initialLoad"/>
    <aura:attribute name="pageNumber" type="integer" />
    <aura:attribute name="CaseList" type="list" />
    <aura:attribute name="caseListPaginateWise" type="list" />
    <aura:attribute name="totalRecords" type="integer" />
    <aura:attribute name="lastPageNumber" type="integer" />
    <aura:attribute name="finalListToAdd" type="list" />
    <aura:attribute name="statusValueSelected" type="String" default="Working"/>
    <div class="slds-box slds-theme_shade slds-theme_alert-texture">
        <lightning:select name="select" label="Select Case Status" onchange="{!c.handleStatusChange}" value="{!v.statusValueSelected}">
        <option value="Working">Working</option>
        <option value="Escalated">Escalated</option>
        <option value="Closed">Closed</option>
    </lightning:select>
    </div>
    <div class="slds-box slds-theme_shade">
    <div >
        <strong>Showing Results for status :</strong><b>{!v.statusValueSelected}</b>
    </div>
    </div>
    <div class="slds-box slds-theme_shade">
 <table class="slds-table slds-table_cell-buffer slds-table_bordered">
  <thead>
    <tr >
      <div class="slds-form-element">
          <div class="slds-form-element_control">
            <label class="slds-checkbox">
                <ui:inputCheckbox change="{!c.selectAllORDeselectAll}"/>
              <span class="slds-checkbox_faux"/>
              <span class="slds-form-element_label"/>
              </label>
          </div>
        </div>
      <th class="" scope="col">
        <div class="slds-truncate" title="Case Number">Case Number</div>
      </th>
      <th class="" scope="col">
        <div class="slds-truncate" title="Status">Status</div>
      </th>
      <th class="" scope="col">
        <div class="slds-truncate" title="OwnerName">Owner Name</div>
      </th>
        <th class="" scope="col">
        <div class="slds-truncate" title="AccountName">Account Name</div>
      </th>
        <th class="" scope="col">
        <div class="slds-truncate" title="Origin">Origin</div>
      </th>
        <th class="" scope="col">
        <div class="slds-truncate" title="Priority">Priority</div>
      </th>
         <th class="" scope="col">
        <div class="slds-truncate" title="Related object Field in Report">Related object Field</div>
      </th>
    </tr>
  </thead>
  <tbody>
      <aura:iteration items="{!v.caseListPaginateWise}" var="a">
    <tr >
      <th  scope="row">
       <div class="slds-form-element">
          <div class="slds-form-element_control">
            <label class="slds-checkbox">
                <ui:inputCheckbox value="{!a.check}"/>
                <span class="slds-checkbox_faux"/>
              <span class="slds-form-element_label"/>
            </label>
          </div>
        </div>
      </th>
     <th  scope="row">
        {!a.obj.CaseNumber}
      </th>
        <th  scope="row">
        {!a.obj.Status}
      </th>
        <th  scope="row">
        {!a.obj.Owner.Name}
      </th>
        <th  scope="row">
        {!a.obj.Account.Name}
      </th>
        <th  scope="row">
        {!a.obj.Origin}
      </th>
        <th  scope="row">
        {!a.obj.Priority}
      </th>
        <th  scope="row">
        {!a.obj.Testobject1__r.Status__c}
      </th>
    </tr>
     </aura:iteration> 
  </tbody>
</table>
    <aura:if isTrue="{!(v.pageNumber!=v.lastPageNumber)}">
     <lightning:button label="Next" onclick="{!c.goToNext}" class="slds-button slds-button_brand"/>
    </aura:if>
     <aura:if isTrue="{!v.pageNumber!=1}">
     <lightning:button label="Previous" onclick="{!c.goToPrevious}" class="slds-button slds-button_brand"/>
     </aura:if>
    <lightning:button label="Download Cases" onclick="{!c.downloadSelectedCase}" class="slds-button slds-button_brand"/>
     <div class="slds-align_absolute-center">
         <b>Displaying Page {!v.pageNumber} of {!v.lastPageNumber}</b>
     </div>
   
</div>

</aura:component>

CaseExtractCompController.js

({
doInit : function (component, event, helper) {
        var np=component.get("v.navigateParameter");
        component.set("v.pageNumber",1);
        helper.helperMethod(component,np);
     
    },
    handleStatusChange : function (component, event, helper) {
        component.set("v.pageNumber",1);
        helper.helperMethod(component,'initialLoad');
     
    },
 goToNext: function(component, event, helper) {
        var pgNumber=component.get("v.pageNumber");
        pgNumber=pgNumber+1;
        component.set("v.pageNumber",pgNumber);
        component.set("v.navigateParameter",'next');
        var ntType=component.get("v.navigateParameter");
        helper.helperMethod(component,ntType);
    },
    goToPrevious: function(component, event, helper) {
        var pgNumber=component.get("v.pageNumber");
        pgNumber=pgNumber-1;
        component.set("v.pageNumber",pgNumber);
        component.set("v.navigateParameter",'previous');
        var ntType=component.get("v.navigateParameter");
        helper.helperMethod(component,ntType);
    },
    selectAllORDeselectAll: function(component, event, helper){
        var trueFalseCheck=event.getSource().get("v.value");
        var csList=component.get("v.CaseList");
        var pagnitaList=component.get("v.caseListPaginateWise");
        var caseListUpd=[];
        var pagnitaListUpd=[];
        for(var i=0;i<csList.length;i++)
            {
                if(trueFalseCheck==true)
                {
                    csList[i].check=true;
                }
                else
                {
                    csList[i].check=false;
                }
                caseListUpd.push(csList[i]);
            }
        component.set("v.CaseList",caseListUpd);
        for(var i=0;i<pagnitaList.length;i++)
            {
                if(trueFalseCheck==true)
                {
                    pagnitaList[i].check=true;
                }
                else
                {
                    pagnitaList[i].check=false;
                }
                pagnitaListUpd.push(pagnitaList[i]);
            }
             component.set("v.caseListPaginateWise",pagnitaListUpd);
   
    },downloadSelectedCase :function(component, event, helper){
        var allSelectedCase=component.get("v.CaseList");
        var caseListAdd=[];
        for(var i=0;i < allSelectedCase.length;i++)
            {
                if(allSelectedCase[i].check==true)
                {
                 
                    caseListAdd.push(allSelectedCase[i].obj);
                }
             
            }
        component.set("v.finalListToAdd",caseListAdd);
        var finalListToDownload=component.get("v.finalListToAdd");
        var csv=helper.convertArrayOfObjectsToCSV(component,finalListToDownload); 
        if(csv==null)
        {
          return ;
        }                         
        var elementLink=document.createElement('a');
        elementLink.href='data:text/csv;charset=utf-8,'+encodeURI(csv);
        elementLink.target='_self';
        elementLink.download='CaseExportData.csv';
        document.body.appendChild(elementLink);
        elementLink.click();
        $A.get('e.force:refreshView').fire();
     
    }
})


CaseExtractCompHelper.js

({
 helperMethod : function(component,type) {
        if(type=='initialLoad')
        {
        var statusValueSelected=component.get("v.statusValueSelected");
            //alert('statusValueSelected'+statusValueSelected);
        var action=component.get('c.getAllCase');
            action.setParams({
                StatusValue:statusValueSelected
            });
       action.setCallback(this,function(response){   
            var state=response.getState();
            var resultData=response.getReturnValue();
            var recordLength=response.getReturnValue().length;
            component.set("v.totalRecords",recordLength);
            var paginateData=[];
            if(state==="SUCCESS")
            {
              component.set("v.CaseList",resultData);
              for(var i=0;i<5;i++)
                  {
                    if(recordLength > i)
                    {
                        paginateData.push(resultData[i]);
                   
                    }                 
                  }
                  component.set("v.caseListPaginateWise",paginateData);
                  component.set("v.lastPageNumber",Math.ceil(recordLength/5));

            }
     
        });
        $A.enqueueAction(action);
 }
        if(type=='next')
        {
            var pgNumber=component.get("v.pageNumber");
            var limit=5*pgNumber;
            var start=limit-5;
            var paginateData=[];
            var RequestList=[];
            RequestList=component.get("v.CaseList");
            var recordLength=component.get("v.totalRecords");
             for(var i=start;i<limit;i++)
                  {
                    if(recordLength > i)
                    {
                        paginateData.push(RequestList[i]);
                   
                    }                 
                  }
             component.set("v.caseListPaginateWise",paginateData);
        }
        if(type=='previous')
        {
            var pgNumber=component.get("v.pageNumber");
            var limit=5*pgNumber;
            var start=limit-5;
           // alert('limit'+limit);
            var paginateData=[];
            var RequestList=[];
            RequestList=component.get("v.CaseList");
            var recordLength=component.get("v.totalRecords");
             for(var i=start;i<limit;i++)
                  {
                    if(recordLength > i)
                    {
                        paginateData.push(RequestList[i]);
                   
                    }                 
                  }
             component.set("v.caseListPaginateWise",paginateData);
        }
    },
    convertArrayOfObjectsToCSV : function(component,objRecords) {
        var csvStringResult,counter,keys,lineDivider,columnDivider;
        if(objRecords==null || !objRecords.length)
        {
return null;         
        }
        columnDivider=',';
        lineDivider='\n';
        keys=['CaseNumber','Status','Owner','Account','Origin','Priority','Subject','Testobject1__r'];
        csvStringResult='';
        csvStringResult+=keys.join(columnDivider);
        csvStringResult+=lineDivider;
        for(var i=0;i<objRecords.length;i++)
            {
                counter=0;
                for(var tempKey in keys)
                    {
                        var skey=keys[tempKey];
                         if(counter>0)
                        {
                            csvStringResult+=columnDivider;
                        }
                        // Querying standard related object field
                        if(typeof objRecords[i][skey]==='object' && (skey==='Owner' || skey==='Account')){
                            csvStringResult+='"'+objRecords[i][skey].Name+'"';
                            counter ++;
                        }
                        // Querying custom related object field
                        else if(typeof objRecords[i][skey]==='object' &&  skey==='Testobject1__r'){
                            csvStringResult+='"'+objRecords[i][skey].Status__c+'"';
                            counter ++;
                        }
                        // Querying same object field
                        else{
                            csvStringResult+='"'+objRecords[i][skey]+'"';
                            counter ++;
                        }
                     
                    }
                csvStringResult+=lineDivider;
             
            }
     
        return csvStringResult
    }

})

caseExtractCompController.apxc

public class caseExtractCompController {
 @AuraEnabled
    public static list<wrapperClass> getAllCase(String StatusValue) {
        string caseStatus=StatusValue;
        list<wrapperClass> wrapperList=new list<wrapperClass>();
          for(Case req:[Select id, CaseNumber, Status,Account.Name,Origin,Priority,Subject,Owner.Name,Testobject1__r.Status__c from Case where Status=:caseStatus ])
            {
              wrapperList.add(new wrapperClass(false,req));
            }
        //wrapperClass wObj = new wrapperClass(false, conList);
        return wrapperList;
    }
 
    public class wrapperClass {
        @AuraEnabled
        public boolean check {
            get;
            set;
        }
        @AuraEnabled
        public Case obj{
            get;
            set;
        }
        public wrapperClass(boolean check, Case obj) {
            this.check = check;
            this.obj = obj;

        }


    }

}


Downloaded excel:


lightning component export to excel


Sunday, October 6, 2019

Authorize an org using sfdx authorize dev hub

Step 1: Create a project.

Step 2: Press Ctrl+Shift+P, Enter "SFDX: Authorize a Dev Hub" as shown below. This will take us to login page.

sfdx authorize dev hub


STEP 3:  Enter the login id and password.

sfdx authorize sandbox

Step 4: Go back to Visual Code Studio where we can see the status of authorization as shown below.

Authorize an org using sfdx authorize dev hub

Step 5: To create a scratch org we need to enable a dev hub as shown in the below images.

How to sfdx authorize dev hub

How to sfdx authorize dev hub

Step 6: These are the two new objects which are created after we enabled dev hub in our org as shown below.

sfdx authorize dev hub

Saturday, September 14, 2019

Reduce method in lightning/ Validation on lightning input field

Today in this blog post we will learn how to setup validation on lightning input field in Lightning component.

Basic syntax of Lightning input field.

<lightning-input type="" name=""/>

Mainly below are the methods which we use for setting up the custom validation on lightning input fields.

1) showHelpMessageIfInvalid

Shows the help message if the form control is in an invalid state.

2) checkValidity

Returns the valid property value (Boolean) on the ValidityState object to indicate whether the input has any validity errors.

3) setCustomValidity

Sets a custom error message to be displayed when the input value is submitted.

4) reportValidity

Display error messages if the input is invalid.

The error message depends on conditions like.

  1. when a bad input is detected.
  2. when a pattern mismatch is detected.
  3. when a type mismatch is detected.
  4. when the value is missing.
  5. when the value is too long.
  6. when the value is too short
Every Input element has a "validity" attribute which is of type object.
Reduce is a Javascript array function. It takes function as an input and applies it on the array and return the output.

To understand the concept we will be going to create a Lightning Component for creating contact and we will be placing this component on Account record detail page for creating contact related to the Account.

Reduce method in lightning/Custom validation on lightning input field


Contactinformation.cmp

<aura:component controller="ContactInsertClass" implements="flexipage:availableForAllPageTypes,force:hasRecordId">
    <aura:attribute name="firstName" type="string"/>
    <aura:attribute name="lastName" type="string"/>
    <aura:attribute name="email" type="string"/>

    <lightning:input label="Enter First Name" aura:id="contactField" value="{!v.firstName}"/>

    <lightning:input label="Enter Last Name" messageWhenValueMissing="Last Name is required" aura:id="contactField" value="{!v.lastName}" required="true"/>

    <lightning:input label="Enter Email" type="Email" aura:id="contactField" messageWhenTypeMismatch="Enter valid email" value="{!v.email}" />

    <lightning:button label="Add contact" onclick="{!c.addContact}"/>
</aura:component>


ContactinformationController.js

({
    addContact: function(component, event, helper) {
        //alert('1111');
        var fName = component.get("v.firstName");
        var lName = component.get("v.lastName");
        var action = component.get('c.insertContact');
        var recordID=component.get("v.recordId");
        var allValid = component.find("contactField").reduce(function (validFields,inputCmp) {
        inputCmp.reportValidity();
        //inputCmp.set('v.validity',{valid:false,badInput:true});    
        return validFields && inputCmp.checkValidity();
        }, true);
        action.setParams({
            parentAccountId:recordID,
            firstName1:component.get("v.firstName"),
            lastName1:component.get("v.lastName"),
            email:component.get("v.email")
        });
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                alert('Contact inserted successfully');
            } else if (state === "INCOMPLETE") {
                
            } else if (state === "ERROR") {
               
            }
        });
        $A.enqueueAction(action);
    }
})

ContactInsertClass.apxc


public class ContactInsertClass {
@AuraEnabled
public static contact insertContact(string parentAccountId,string firstName1,string lastName1,string email)
{
    system.debug('Test');
    contact con=new contact();
    con.firstName=firstName1;
    con.lastName=lastName1;
    con.email=email;
    con.accountid=parentAccountId;
    insert con;
    return con;
    
}
}

Error handling in lightning component

Today in this blog post we will be going to see how we can handle page errors and field errors based on input from user.

For this we will be going to create a Lightning Component for creating contact and we will be placing this component on Account record detail page for creating contact related to the Account.




ContactInformation.cmp


<aura:component controller="ContactInsertClass" implements="flexipage:availableForAllPageTypes,force:hasRecordId">
    <aura:attribute name="firstName" type="string"/>
    <aura:attribute name="lastName" type="string"/>
    <aura:attribute name="email" type="string"/>
    <lightning:input label="Enter First Name" value="{!v.firstName}"/>
    <lightning:input label="Enter Last Name" value="{!v.lastName}"/>
    <lightning:input label="Enter Email" value="{!v.email}"/>
    <lightning:button label="Add contact" onclick="{!c.addContact}"/>
</aura:component>


ContactInformationController.js



({
    addContact: function(component, event, helper) {
        //alert('1111');
        var fName = component.get("v.firstName");
        var lName = component.get("v.lastName");
        var action = component.get('c.insertContact');
        var recordID=component.get("v.recordId");
        action.setParams({
            parentAccountId:recordID,
            firstName1:component.get("v.firstName"),
            lastName1:component.get("v.lastName"),
            email:component.get("v.email")
        });
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                alert('Contact inserted successfully');
            } else if (state === "INCOMPLETE") {
                alert("Server Error, check you internet connection");
            } else if (state === "ERROR") {
                var toastEvent = $A.get("e.force:showToast");
                var errorMessageToDisplay = '';
                var errors = response.getError();
                if (errors) {
                   
                    for (var j = 0; j < errors.length; j++) {
                        if (errors[j].pageErrors) {
                            for (var i = 0; i < errors[j].pageErrors.length; i++) {
                                errorMessageToDisplay += (errorMessageToDisplay.length > 0 ? '\n' : '') + errors[j].pageErrors[i].message;
                            }
                        }
                        if (errors[j].fieldErrors) {
                            for (var fieldError in errors[j].fieldErrors) {
                                var thisFieldError = errors[j].fieldErrors[fieldError];
                                for (var k = 0; k < thisFieldError.length; k++) {
                                    errorMessageToDisplay += (errorMessageToDisplay.length > 0 ? '\n' : '') + thisFieldError[k].message;
                                }
                            }
                        }
                    }
                    toastEvent.setParams({
                        title: 'Error',
                        type: 'error',
                        message: errorMessageToDisplay
                    });
                    toastEvent.fire();
                }
            }
        });
        $A.enqueueAction(action);
    }
})


ContactInsertClass.apxc


public class ContactInsertClass {
@AuraEnabled
public static contact insertContact(string parentAccountId,string firstName1,string lastName1,string email)
{
    system.debug('Test');
    contact con=new contact();
    con.firstName=firstName1;
    con.lastName=lastName1;
    con.email=email;
    con.accountid=parentAccountId;
    insert con;
    return con;
   
}
}

Sunday, September 8, 2019

How to set up visual studio code for Salesforce?

Topics to covered:

What is LWC(Lightning Web Components)?
How to set up visual studio code for Salesforce?
What is Scratch org?


What is LWC(Lightning Web Components)?

As of now we have built lightning component using the "Aura Components model" we can also built
lightning component using the "Lightning Web Components model". Lightning Web Components are custom HTML elements build using the HTML Elements and modern Javascript. We can built components using any of the model and can place these components on the same lightning page.

For developing LWC we require  "Salesforce Extensions for Visual Studio Code" and for deploying LWC from an org we require "Salesforce CLI".

Aura Components make use of own custom component model, custom templates,custom components etc while LWC is built on web standards and it make use of web components,templates,custom elements which we have in web standards. Both Aura component,LWC make use of Security,LDS and Base lightning components.

Important points to note:

1) Aura component and LWC can exist on Same lightning page.
2) Aura component can include LWC


How to set up visual studio code for Salesforce?

Setting up the Salesforce DX Environment:

1) Download Visual code studio from https://code.visualstudio.com

2) After downloading open the Visual code studio you will see something like these.

Lightning Web Components


3) Click on the symbol shown in the below image.

Lightning Web Components

4) Type "Salesforce extension pack" in search box and click install as shown in below image.

how to set up visual studio code for salesforce

5) Now open google chrome and search for "install Salesforce cli" and open the link as shown in below image.

Lightning Web Components

6) Click download in the below image.

Salesforce CLI

7) To check if it is downloaded properly open Command Prompt and type sfdx and press enter.

Lightning Web Components

8) Now to install the latest plugin type "sfdx plugins:install salesforcedx@latest" and wait till the installation is completed.

9) Now we need to set the path and environment variable on our desktop.

Go to This PC > Right click on This PC > Properties > Advanced system settings > Environment variables > Double click on Path and check if the Path has the "C:\Program Files\Salesforce CLI\bin". Also the under the System variable check if the Path has "C:\Program Files\Salesforce CLI\bin". If this is missing under Path in "User variables for home" or "System variables" section create the same using the new button.

Lightning Web Components

10) Now to check if everything is setup properly go to Visual Studio and Press CTRL+SHIFT+P.
Enter SFDX: Create Project with Manifest > Enter the project name > Select the folder. It will create a Project for us after running as shown below.

If you get this error: Error: Salesforce CLI is not installed.

Just close the visual code studio and start again.

LWC

Now, we will see how to Authorize a dev hub?

11) Press CTRL+SHIFT+P,

Type sfdx:Authorize a Dev Hub as shown in below image and click it, It will take you to the login page.



12) Login to your Salesforce org and now check Visual Code studio. It will show us the success message as shown below.

how to use visual studio code for salesforce

13) Now the next step is to create a Scratch org.

What is Scratch org?

Scratch org is disposable Salesforce org used for development and testing.
Scratch org can be created for a maximum of 30 days after which scratch org gets deactivated. Default duration for Scratch org is 7 days.
config file as shown in the below image contains the Scratch org definition.


What is Scratch org in Salesforce?



Now press CTRL+SHIFT+P and search for "Create a Default Scratch org.." and click it and select the file available as shown in the below images.

visual studio code salesforce setup


how to use visual studio code for salesforce

14) Specify the name and the days after which the Scratch org will expire. Now we can see that the Scratch org is getting created as shown in below image.

how to use visual studio code for salesforce


15) After the Scratch org is created successfully press CTRL+SHIFT+P  and type "SFDX:Open Default Org ". It will open the Scratch org in new console as shown below.

Scratch org in Salesforce using Visual Code Studio