Wednesday, October 12, 2022

PDF Generation in Lightning Web Component (LWC) Salesforce

Hello Guys in this post I'll explain you how to generate PDF using LWC.

So to achieve this I am creating one LWC and putting that LWC on the Contact Record Detail page, In LWC I'm showing some contacts fields using the HTML file of LWC. Please make sure you're not using any slds class for styling because those classes wont create any styling in PDF. You have to use normal CSS for styling. In LWC, I have one button and on the click of that button PDF. would generate. I also need one Visualforce Page that will be used to render the PDF.

Check below example with Code

Lightning Web Component Code

pdfGenerationLWC.html

<template>
    <div class="container" style="background: white; margin: 1px; border:1px solid black;">
        <h1>Contact Detail</h1>
        <div style="margin-bottom: 10px;">
            Title : {contact.Title}            
        </div>
        <div style="margin-bottom: 10px;">
            <div>Phone : {contact.Phone}</div>
        </div> 
        <div style="margin-bottom: 10px;">
            Name : {contact.FirstName} {contact.LastName}
        </div>
        <div style="margin-bottom: 10px;">
            <div>Home Phone: {contact.HomePhone}</div>  
        </div>                       
    </div>
    <lightning-button variant="brand" label="Download PDF" onclick={downloadPDF}></lightning-button>
</template>

In JS part of LWC I have created one public property recordId, that will receive contact Id and using this Id I'm making a server call to fetch the contact details, also there is one method downloadPDF that will be called on the click of the button and in that first I am getting all html code using queryselector and passing as string to the visulforce page and visualforce page will show all the html code as pdf

pdfGenerationLWC.js

import { LightningElement, api } from 'lwc';
import getContact from '@salesforce/apex/PDFGenerationLWCController.getContact';

export default class PdfGenerationLWC extends LightningElement {
    @api recordId;
    contact = {}
    connectedCallback(){
       getContact({
           recordId : this.recordId
       })
       .then(result=>{
            this.contact = result;
       })
       .catch(error=>{
           console.error(error);
       })
   }
    downloadPDF(){
        let htmlContent = this.template.querySelector('.container')    
        window.location = "/apex/PDFGenerationPage?pdfHTML="+htmlContent.outerHTML;  
    }
}
pdfGenerationLWC.js-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>55.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__RecordPage</target>
    </targets>
</LightningComponentBundle>

Apex controller to fetch the contact details


public with sharing class PDFGenerationLWCController {
    @AuraEnabled
    public static Contact getContact(String recordId){
        try {
            return [SELECT Title, FirstName, LastName, Phone, Owner.FirstName, HomePhone FROM CONTACT WHERE Id=:recordId];
        } catch (Exception e) {
            throw new AuraHandledException(e.getMessage());
        }
    }    
}

Visualforce page

<apex:page controller="pdfPageController" renderAs="pdf" applyHtmlTag="false" showHeader="false" cache="true" readOnly="true">
    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
            <style>
                @page {
                    size: a4 portrait;    
                    padding-left: 2px;    
                    padding-right: 2px;
                }            
            </style>
        </head>
        <apex:outputText value="{!pdfHTML}" escape="false"/>
    </html>

</apex:page>
Visualforce Page Controller

public with sharing class PDFPageController {
    public String pdfHTML{get;set;}
    public pdfPageController() {
        pdfHTML = ApexPages.currentPage().getParameters().get('pdfHTML');
    }
}

Output Screen shots

If you guys have any question, please comment below. I'll be happy to help.

Saturday, June 11, 2022

Lightning Modal/Popup Lightning Web Component(LWC)

Hello Guys, In this post I'll create lightning Modal/Popup in Lightning Web component Salesforce(LWC).

Modals are used to display content in a layer above the app. This paradigm is used in cases such as the creation or editing of a record, as well as various types of messaging and wizards.

Check below example

lightningModalLWC.html

<template>
    <!--Lightning Button which will open Modal on the click of it -->
    <lightning-button variant="brand" label="Open Modal" onclick={openModal}></lightning-button>

    <!--isModalOpen property will be used to hide/show for modal -->
    <template if:true={isModalOpen}>
        <!-- lightning modal Starts here -->
        <section role="dialog" tabindex="-1" aria-modal="true" aria-labelledby="modal-heading-01" class="slds-modal slds-fade-in-open">
            <div class="slds-modal__container">
                <lightning-button-icon icon-name="utility:close"
                                              onclick={closeModal}                                              
                                              variant="bare-inverse"
                                              class="slds-modal__close">
                </lightning-button-icon>
                <div class="slds-modal__header">
                    <h1 id="modal-heading-01" class="slds-modal__title slds-hyphenate">Modal/Popup header LWC</h1>
                </div>
                <div class="slds-modal__content slds-p-around_medium" id="modal-content-id-1">
                    <p>Modal Content would come here</p>
                </div>
                <div class="slds-modal__footer">
                    <button class="slds-button slds-button_neutral" aria-label="Cancel and close" onclick={closeModal}>Cancel</button>
                    <button class="slds-button slds-button_brand" onclick={submit}>Submit</button>
                </div>
            </div>
        </section>
        <div class="slds-backdrop slds-backdrop_open" role="presentation"></div>
        <!-- lightning modal Ends here -->
    </template>
</template>
lightningModalLWC.js

import { LightningElement } from 'lwc';

export default class LightningModalLWC extends LightningElement {
    isModalOpen = false;//property that will be use to hide/show of Lightning Modal

    openModal(){
        this.isModalOpen = true;
    }
    closeModal(){
        this.isModalOpen = false;
    }
    submit(){
        //write some logic
        this.isModalOpen = false;
    }
}
lightningModalLWC.js-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__HomePage</target>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
    </targets>
</LightningComponentBundle>
output

Related Post : Lightning Modal/Popup Lightning Aura Component Salesforce

Lightning Modal/Popup Lightning Aura Component Salesforce

Hello Guys, In this post I'll create lightning Modal in Lightning Aura component Salesforce.

Modals are used to display content in a layer above the app. This paradigm is used in cases such as the creation or editing of a record, as well as various types of messaging and wizards.

Check below example

LightningModalAura.cmp

<aura:component implements="flexipage:availableForAllPageTypes" access="global" >
    <!--Attributes -->
    <aura:attribute name="isModalOpen" type="boolean" default="false"></aura:attribute> 
    
    <!--Lightning Button which will open Modal on the click of it -->
    <lightning:button variant="brand" label="Open Modal" onclick="{!c.openModal}"></lightning:button>
    
    <!--isModalOpen Attribute will be used to hide/show for modal -->
    <aura:if isTrue="{!v.isModalOpen}">
        <!-- lightning modal Starts here -->
        <section role="dialog" tabindex="-1" aria-modal="true" aria-labelledby="modal-heading-01" class="slds-modal slds-fade-in-open">
            <div class="slds-modal__container">
                <lightning:buttonIcon iconName="utility:close"
                                              onclick="{!c.closeModal}"
                                              alternativeText="close"
                                              variant="bare-inverse"
                                              class="slds-modal__close"/>
                <div class="slds-modal__header">
                    <h1 id="modal-heading-01" class="slds-modal__title slds-hyphenate">Modal header</h1>
                </div>
                <div class="slds-modal__content slds-p-around_medium" id="modal-content-id-1">
                    <p>Modal Content would come here</p>
                </div>
                <div class="slds-modal__footer">
                    <button class="slds-button slds-button_neutral" aria-label="Cancel and close" onclick="{!c.closeModal}">Cancel</button>
                    <button class="slds-button slds-button_brand" onclick="{!c.submit}">Submit</button>
                </div>
            </div>
        </section>
        <div class="slds-backdrop slds-backdrop_open" role="presentation"></div>
        <!-- lightning modal Ends here -->
    </aura:if>
</aura:component>
LightningModalAuraController.js

({
	openModal : function(component, event, helper) {
		component.set("v.isModalOpen", true);
	},
    closeModal : function(component, event, helper) {
        component.set("v.isModalOpen", false);		
	},
    submit : function(component, event, helper) {
        //write some logic
		component.set("v.isModalOpen", false);	
	},
})
output

Related Post : Lightning Modal/Popup Lightning Web Component(LWC)

Wednesday, June 8, 2022

Lightning combobox to display State and City in LWC also load with Default value

Hello Guys, In this post we would learn how can we populate State values in Lightning Combobox and on the selection of State, Cities should be populated in another combobox.

To Understand this scenario, I have created two master objects in Salesforce 1. State ( having States records) 2. City which has master detail to State object and having cities records. I have created two text field State and City on Contact object to store the values.

Our stateCity component has been placed on Contact Detail page it has one update button so whenever user select States, automatically cities belong to that state would come up in City Combobox and after the selection of City, once user clicks on Update button both State and City values will be saved in Contact object in State and City fields respectivily.

If user comes on the detail page later and State and City fields on the Contact object are already has values so on load of the component the default values would be shown to the user.

See the full code below

Apex Class


public class StateCityController {
    @AuraEnabled
    public static ContactStateCityWrapper getStateCities(String recordId){  
        ContactStateCityWrapper obj = new ContactStateCityWrapper();
        List<State__c> stateList = [select Name, (select Name from cities__r order by Name) from state__c order by Name ];
        Contact con = [SELECT State__c, City__c FROM Contact WHERE Id =: recordId];
        
        obj.stateCityList = stateList;
        obj.contact = con;
        return obj;
    }
    public Class ContactStateCityWrapper{
        @AuraEnabled public Contact contact;
        @AuraEnabled public List<State__c> stateCityList;
    }
    @AuraEnabled
    public static String handleUpdate(String contactDetails){
        Contact conObj = (Contact) JSON.deserialize(contactDetails, Contact.class);
        
        update conObj;
        return conObj.Id;
    }
}

stateCity.html


<template>
    <lightning-card title="Update State and City">
        <div class="slds-grid slds-no-flex slds-var-p-around_medium	">
            <div class="slds-col slds-size_2-of-12">State</div>
            <div class="slds-col slds-size_2-of-12">
                <lightning-combobox variant="label-hidden"
                                name="state"                                                                                
                                placeholder="Select State"
                                options={states}
                                onchange={onStateChange} 
                                data-id="state">
                </lightning-combobox>                   
            </div>
            <div class="slds-col slds-size_1-of-12"></div>
            <div class="slds-col slds-size_2-of-12">City</div>
            <div class="slds-col slds-size_2-of-12">
                <lightning-combobox variant="label-hidden"
                            name="city"                                                                        
                            placeholder="Select City"
                            options={cities}
                            onchange={onCityChange}
                            data-id="city" >
                </lightning-combobox>
            </div>
        </div> 
    
    <div class="slds-grid slds-no-flex slds-var-p-around_medium	">
        <div class="slds-col slds-size_12-of-12 slds-align_absolute-center">
            <lightning-button variant="brand" style="width: 6rem;" label="Update" title="Update" onclick={handleUpdate} class=""></lightning-button>            
        </div>
    </div>
</lightning-card>
</template>

stateCity.js


import { LightningElement, api } from 'lwc';
import getStateCities from '@salesforce/apex/StateCityController.getStateCities';
import handleUpdate from '@salesforce/apex/StateCityController.handleUpdate';

export default class StateCity extends LightningElement {
    @api recordId;
    error;
    states;
    cities;
    stateCityMap = {};
    stateIdNameMap = {};
    cityIdNameMap = {};
    selectedStateName
    selectedCityName
    connectedCallback(){
        console.log('## '+this.recordId)
        getStateCities({
            recordId : this.recordId
        })
        .then(result =>{
            let stateOptions = [];                        
            let cityMapLocal = {}; 
            let stateIdNameMapLocal = {};
            let cityIdNameMapLocal = {};
            
            let stateNameIdMapLocal = {};
            let cityNameIdMapLocal = {};

            console.log('## '+JSON.stringify(result))
            //Population of State and City List
            result.stateCityList.forEach(function(index,value){
                if(index.Cities__r){
                    let cities = index.Cities__r.map(function(data){  
                        cityIdNameMapLocal[data.Id] = data.Name;
                        cityNameIdMapLocal[data.Name] = data.Id;                                              
                        return data;
                    });
                    cityMapLocal[index.Id] = cities;
                }else{
                    cityMapLocal[index.Id] = [];
                } 
                stateIdNameMapLocal[index.Id] = index.Name.toUpperCase(); 
                stateNameIdMapLocal[index.Name.toUpperCase()] = index.Id;              
                stateOptions.push({label:index.Name.toUpperCase(), value:index.Id});                
            }) 
            this.stateIdNameMap = stateIdNameMapLocal;
            this.cityIdNameMap = cityIdNameMapLocal;
            
            this.states = stateOptions;
            this.stateCityMap = cityMapLocal;
            console.log('## 2')
            if(result.contact.State__c != null && result.contact.City__c != null){
                this.template.querySelector('lightning-combobox[data-id="state"]').value = stateNameIdMapLocal[result.contact.State__c];
                this.template.querySelector('lightning-combobox[data-id="city"]').value = cityNameIdMapLocal[result.contact.City__c];
            
                //to populate the City Dropdown based on the State
                let cityOptions = [];
                let stateCityMap = JSON.parse(JSON.stringify(this.stateCityMap));
                let cityList = stateCityMap[stateNameIdMapLocal[result.contact.State__c]];
                if(cityList.length > 0){
                    cityList.forEach(function(index,value){
                        cityOptions.push({label: index.Name, value: index.Id});
                    })
                }
                this.cities = cityOptions;
            }
            console.log('##22')
        })
        .catch(error =>{
            this.error = error;
        })
    }
    onStateChange(event){
        let cityOptions = [];        
        let selectedStateId = event.target.value;
        let stateCityMap = JSON.parse(JSON.stringify(this.stateCityMap));
        let cityList = stateCityMap[selectedStateId];
        if(cityList.length > 0){
            cityList.forEach(function(index,value){
                cityOptions.push({label: index.Name, value: index.Id});
            })
        }
        this.cities = cityOptions;        
        this.selectedStateName = this.stateIdNameMap[selectedStateId];
    }
    onCityChange(event){        
        this.selectedCityName = this.cityIdNameMap[event.target.value];
    }
    handleUpdate(){
        let contact = {
            Id : this.recordId,
            State__c: this.selectedStateName,
            City__c : this.selectedCityName
        }

        handleUpdate({
            contactDetails : JSON.stringify(contact)
        })
        .then(result =>{
            alert('Successfully Updated!')
        })
        .catch(error =>{
            this.error = error
        })
    }
}

stateCity.js-meta.xml


<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__HomePage</target>
        <target>lightning__RecordPage</target>
    </targets>
</LightningComponentBundle>

Output

Below image shows the State and City values populating as default on page load from Contact record.

Please comment below, if you guys have any quesiton. I'll be happy to answer. Thanks!

Monday, May 16, 2022

Lightning Data Table to Show Parent object data along with Count of the child in LWC Salesforce

Hello Guys, in this post we would learn how can we show Parent object data along with no of child in one column in Lightning data table in Lightning Web Component(LWC).

To understand this scenario, I have taken Account as a parent object and contact as a child object and in the Lightning Data table we would display few Account fields along with No of Contacts

Please check the full code below

Apex Class

public class LightningDataExampleController {
	@AuraEnabled
    public static List getAccounts(){
        return [SELECT Id, Name, AccountNumber, Site,
                (SELECT Id FROM Contacts) 
                FROM Account 
                LIMIT 5];
    }
}
lightningDataTableExample.html

<template>
    <lightning-card title="Lightning Data Table">        
        <div class="slds-grid slds-no-flex slds-var-p-around_medium	">
            <div class="slds-col slds-size_12-of-12">
                <lightning-datatable key-field="Id"
                                    data={accounts}
                                    columns={columns}                                    
                                    hide-checkbox-column
                                    >
                </lightning-datatable>                            
            </div>
        </div>
    </lightning-card>    
</template>
lightningDataTableExample.js

import { LightningElement } from 'lwc';
import getAccounts from '@salesforce/apex/LightningDataExampleController.getAccounts';

export default class LightningDataTableExample extends LightningElement {
    columns = [
        {label: 'Name', fieldName: 'Name', type: 'text', sortable: false},
        {label: 'Account Number', fieldName: 'AccountNumber', type: 'text', sortable: false},
        {label: 'Site', fieldName: 'Site', type: 'text', sortable: false},
        {label: 'No of Contacts', fieldName: 'noOfContacts', type: 'text', sortable: false},
    ];

    accounts = [];
    error;

    connectedCallback(){
        this.getAccounts();
    }
    getAccounts(){
        getAccounts()
        .then(result =>{            
            result.forEach(element => {
                let noOfContacts = 0;
                if(element.Contacts){
                    element.Contacts.forEach(con =>{
                        noOfContacts++;
                    })
                }
                element.noOfContacts = noOfContacts;
            });
            this.accounts = result;            
        })
        .catch(error =>{
            this.error = error;
        })
    }
}
lightningDataTableExample.js-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>

Please comment below, if you guys have any quesiton. I'll be happy to answer. Thanks!

Related Posts
Add Delete rows dynamically in Lightning Data Table in LWC Salesforce

Sunday, May 15, 2022

Add Delete rows dynamically in Lightning Data Table in LWC Salesforce

Hello Guys, in this post we'll learn how to add delete rows dynamically in Lightning Data table in Lightning Web Components(LWC) in Salesforce with the proper Example.

Apex Class

public class AddDeleteRowLWCController {

    @AuraEnabled
    public static List getAccounts(){
        return [SELECT Id, Name, AccountNumber, Site FROM Account LIMIT 5];
    }
    @AuraEnabled
    public static Account addAccount(String account){
        Account accObj = (Account) System.JSON.deserialize(account, Account.class);
        insert accObj;
        return accObj;
    }
}
addDeleteRowLWC.html

<template>
    <lightning-card title="">
        <lightning-button variant="brand" label="Add Account" onclick={openAddAccountModal} ></lightning-button>
        <div class="slds-grid slds-no-flex slds-var-p-around_medium	">
            <div class="slds-col slds-size_12-of-12">
                <lightning-datatable key-field="Id"
                                    data={accountData}
                                    columns={columns}
                                    onrowaction={handleRowAction}
                                    hide-checkbox-column
                                    >
                </lightning-datatable>                            
            </div>
        </div>
    </lightning-card>

    <template if:true={isModalOpen}>
        <!-- Modal/Popup Box LWC starts here -->
        <section role="dialog" tabindex="-1" aria-labelledby="modal-heading-01" aria-modal="true" aria-describedby="modal-content-id-1" class="slds-modal slds-fade-in-open">
            <div class="slds-modal__container">
                <!-- Modal/Popup Box LWC header here -->
                <header class="slds-modal__header">
                    <button class="slds-button slds-button_icon slds-modal__close slds-button_icon-inverse" title="Close" onclick={closeModal}>
                        <lightning-icon icon-name="utility:close"
                            alternative-text="close"
                            variant="inverse"
                            size="small" ></lightning-icon>
                        <span class="slds-assistive-text">Close</span>
                    </button>
                    <h2 id="modal-heading-01" class="slds-text-heading_medium slds-hyphenate">Add Account</h2>
                </header>
                <!-- Modal/Popup Box LWC body starts here -->
                <div class="slds-modal__content slds-p-around_medium" id="modal-content-id-1">
                    <lightning-input name="accountName" type="text"  label="Name" value={accountName} onchange={handleChange}></lightning-input>                    
                    <lightning-input name="accountNumber" type="Integer" label="AccountNumber" value={accountNumber} onchange={handleChange}></lightning-input>                    
                    <lightning-input name="accountSite" type="text" label="Site" value={accountSite} onchange={handleChange}></lightning-input>                    

                </div>
                <!-- Modal/Popup Box LWC footer starts here -->
                <footer class="slds-modal__footer">
                    <button class="slds-button slds-button_neutral" onclick={closeModal} title="Cancel">Cancel</button>
                    <button class="slds-button slds-button_brand" onclick={addAccount} title="Add Account">Add Account</button>
                </footer>
            </div>
        </section>
        <div class="slds-backdrop slds-backdrop_open"></div>
    </template>

</template>
addDeleteRowLWC.js

import { LightningElement } from 'lwc';
import getAccounts from '@salesforce/apex/AddDeleteRowLWCController.getAccounts';
import addAccount from '@salesforce/apex/AddDeleteRowLWCController.addAccount';

export default class AddDeleteRowLWC extends LightningElement {
    columns = [
        {label: 'Name', fieldName: 'Name', type: 'text', sortable: true},
        {label: 'Account Number', fieldName: 'AccountNumber', type: 'text', sortable: false},
        {label: 'Site', fieldName: 'Site', type: 'text', sortable: true},
        {type: "button-icon", typeAttributes: {iconName: "utility:delete", name: "delete", iconClass: "slds-icon-text-error"},fixedWidth: 50}     
    ];

    accountData = [];
    isModalOpen = false;
    accountName= '';
    accountNumber = '';
    accountSite = '';

    connectedCallback(){
        this.getAccounts();
    }
    getAccounts(){
        getAccounts()
        .then(result =>{
            this.accountData = result;
        })
        .catch(error =>{

        })
    }

    handleRowAction(event) {
		if (event.detail.action.name === "delete") {
			this.deleteSelectedRow(event.detail.row);
		}
	}
    deleteSelectedRow(deleteRow) {
		let newData = JSON.parse(JSON.stringify(this.accountData));
		newData = newData.filter((row) => row.Id !== deleteRow.Id);
        this.accountData = newData;		
	}
    openAddAccountModal(){
        this.isModalOpen = true;
    }
    closeModal() {        
        this.isModalOpen = false;
    }
    handleChange(event){
        if(event.target.name == 'accountName'){
            this.accountName = event.target.value;
        }else if(event.target.name == 'accountNumber'){
            this.accountNumber = event.target.value;
        }else if(event.target.name == 'accountSite'){
            this.accountSite = event.target.value;
        }
    }
    addAccount(){
        let accountToInsert = {
            Name : this.accountName,
            AccountNumber: this.accountNumber,
            Site : this.accountSite
        }
        addAccount({
            account: JSON.stringify(accountToInsert)
        })
        .then(result =>{            
            this.addAccountToList(result)
        })
        .catch(error =>{
            this.error = error;
        })        
    }
    addAccountToList(account){
        let localList;            
        if(this.accountData.length > 0){                        
            localList =JSON.parse(JSON.stringify(this.accountData));                
        }else{
            localList = [];                
        }
         
        localList.push({
            Id: account.Id,
            Name : account.Name,
            AccountNumber : account.AccountNumber,
            Site : account.Site,            
        })                                        
        this.accountData = localList;
        this.isModalOpen = false;    
    }
}
addDeleteRowLWC.js-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>
Output

If you guys have any question, please comment below, I'll be happy to answer your question.
#LWC, #LightningDataTable, #adddeleterowinlwc #salesforce #salesforcelightning

Related Posts
Lightning Data Table to Show Parent object data along with Count of the child in LWC Salesforce

Friday, May 13, 2022

Subscript is invalid because list is empty | Error in VF Page | Salesforce

Subscript is invalid because list is empty this error is comes on VF page if we are trying to access the list element on VF Page and in the apex the list has no rows.

Below is the example 

Here is my Apex Class

public Class myClass {

    public Account account {get;set;} 

public myClass(){

        recordId = System.currentPageReference().getParameters().get('recordId');

        this.account = [SELECT Id, Name,(select id,LastName FROM Contacts) FROM Account WHERE Id =:recordId];                

    }

}


VF Page

<apex:page renderAs="pdf" applyBodyTag="false" controller="myClass" >

<div class="header">

        <table>         

            <tr>

                <td style="background: #D6EEEE"><b>Account Name</b></td>   

                <td>{!account.Name}</td> 

                <td style="background: #D6EEEE"><b>Contact Last Name</b></td>  

                <td>{!account.Contacts[0].LastName}</td> 

        </tr>

    </table>



In order to solve this error we'll have to modify our code as below

public Class myClass {

    public Account account {get;set;} 

    public String contactLastName {get;set;}

public myClass(){

        recordId = System.currentPageReference().getParameters().get('recordId');

        contactLastName = '';

        this.account = [SELECT Id, Name,(select id,LastName FROM Contacts) FROM Account WHERE Id =:recordId];           

    if(this.account.contacts.size() >0){

        contactLastName = this.account.contacts[0].LastName;

    }     

    }

}


VF Page

<apex:page renderAs="pdf" applyBodyTag="false" controller="myClass" >

<div class="header">

        <table>         

            <tr>

                <td style="background: #D6EEEE"><b>Account Name</b></td>   

                <td>{!account.Name}</td> 

                <td style="background: #D6EEEE"><b>Contact Last Name</b></td>  

                <td><!--{!account.Contacts[0].Name}-->{!contactLastName}</td> 

        </tr>

    </table>


Hope this will solve your problem, Please comment below if you have any question. I'll be happy to help.

Sunday, April 3, 2022

How to Update custom metadata type record using Metadata API

 In this example, I'll show you how can we write an Apex class to update the custom metadata record using Metadata API

Please follow the below steps:

Step 1 : Create a Custom metadata object and a field, in our example our custom metadata object is StatesCitiesPincode__mdt and a custom field State__c

Step 2: Create a record by clicking on the Manage StatesCitiesPincode button at the top and then click on the new button

Step 3: Now we'll create an apex class which will be used to update the record, whenever we update the custom metadata record using metadata API the system does an actual deployment and we can track it by checking deployment Status through the Setup.


  public class CreateUpdateMetadataUtils implements Metadata.DeployCallback {
    // Method to track deploy results
    public void handleResult(Metadata.DeployResult result,
                             Metadata.DeployCallbackContext context) {
        if (result.status == Metadata.DeployStatus.Succeeded) {
            System.debug('success: '+ result);
        } else {
            System.debug('fail: '+ result);
        }
    }
}
  

  public with sharing class UpdateCustomMetadata {
    
    public static void updateRecord() {
        
        try {                
            Metadata.DeployContainer mdContainer = new Metadata.DeployContainer();
            
            Metadata.CustomMetadata customMetadata = new Metadata.CustomMetadata();
            customMetadata.fullName = 'StatesCitiesPincode__mdt.Uttar_Pradesh';
            customMetadata.Label='Uttar Pradesh';
            
            Metadata.CustomMetadataValue customField = new Metadata.CustomMetadataValue();
            customField.field = 'State__c';
            customField.value = 'UP';
            
            
            customMetadata.values.add(customField);                
            mdContainer.addMetadata(customMetadata);            
            
              
            CreateUpdateMetadataUtils  callback = new CreateUpdateMetadataUtils();            
            Id jobId = Metadata.Operations.enqueueDeployment(mdContainer, callback);                        
            
            
        } catch (exception e) {
            
        }                
    }        
}
  

you can execute the method from the Anonymous Apex window UpdateCustomMetadata.updateRecord();

Saturday, September 5, 2020

Formula Field to Convert date value into the Month Name as Text like JAN, FEB, etc.

 Hello All, In this article we would learn how can we convert the date value into the Month Name,
for example, if you have one DateTime field like Createddate and your requirement is to display the Month Name instead of date like if we have DateTime value as 2018-01-17T11:18:31.000+05:30 so with our formula field we can display this date as JAN  similarly 2018-02-17T11:18:31.000+05:30 as FEB.

So in one line, the formula is below, you can use it accordingly however I will explain it by breaking into all functions which we have used in this.


CASE(MONTH(DATEVALUE(CreatedDate )),1,'JAN',2,'FEB',3,'MAR',4,'APR',5,'MAY',6,'JUN',7,'JUL',8,'AUG',9,'SEP',10,'OCT',11,'NOV',12,'DEC','')


Explanation of different functions used.

DATEVALUE(expression) -- DATEVALUE function accepts DateTime as argument (dateTime can be text also) and converts it into the DATE. 

ex. DATEVALUE(2018-02-17T11:18:31.000+05:30)  returns 2018-01-17

MONTH(date) -- MONTH functions accept DATE as an argument and returns the month,which is basically a number between 1 for (January) and 12 for (December)

ex. MONTH(2018-01-17) returns 1

CASE(expression, value1, result1, value2, result2,...,else_result) -- Checks an expression against a series of values.  If the expression compares equal to any value, the corresponding result is returned. If it is not equal to any of the values, the else-result is returned

ex CASE(MONTH(DATEVALUE(CreatedDate )),1,'JAN',2,'FEB',3,'MAR',4,'APR',5,'MAY',6,'JUN',7,'JUL',8,'AUG',9,'SEP',10,'OCT',11,'NOV',12,'DEC','')

here MONTH(DATEVALUE(CreateDate)) works like an expression and returns value as 1, 2 etc which inturn used as an argument in CASE function and CASE functions returns result accordingly.


I hope this explanation helps you. Thanks!!


Sunday, May 26, 2019

How to use custom metadata types in the lighting flow.

Hello guys, In this article, we will learn how can we use Flow builder, Process builder, and Custom metadata types to update records.

I have a scenario in which I have one custom metadata type named as STATESCITIESPINCODE which contains pin codes of corresponding cities with their states, now whenever a user creates the records he enters state name and city name so our process builder calls flow which having logic how to get pin code corresponding to state and city to enter by the user while creating the record and then our process builder update the record with the pin code.

so first let's create the custom metadata type which having the states, cities, and corresponding pin codes,

So go to Setup >> Enter custom metadata in the search box >> click on Custom Metadata Types under Develop
so I have custom metadata types with three custom fields City, State, and Pincode



now we'll create the flow
so go to setup >> Enter Flow >> Click on Flows under Process Automation

So in our flow, first of all, we'll create the variables for this click on Manage on the left and then click on New Resource then the popup will come in the search box enter variable and click on the variable


Repeat the steps for creating the three variables varCity, varState, varPincode, and varId of datatype Text.
Create another variable varUpdateCityRecord with datatype as Record and Object type is as City, which will be used to update the record



Create another variable varGetPincodeRecord with datatype as Record and Object type is as StatesCitiesPincode( which is our custom metadata object), this will be used to store the value of pin code.




Now we have created the variables now we'll search for the records in the custom metadata type. so for this click on the element on the left and drag the GetRecords under data, a popup will come, give a suitable label, in the object search your custom metadata type name, in the condition requirement select Conditions are met







Now Click on Assignment under the Logic and drag it to right again the popup will come, give some Label then set the variable values



next and final step is to update the Record variable, for this click on the Update Records and drag it to the right again popup will come, give the suitable name and then in the select variable select the varUpdateCityRecord variable which will update the Record with the pin code.





join all them together and the finally your flow will look like this


Save the flow as autolauchedflow, and don't forget to activate it.

Now create the process builder which will run when we try to save our city Object record and will call the flow to update the record with the corresponding pin code

Select City as an object, in the criteria, select No criteria—just execute the actions! 


and in the immediate actions  Select Flow as an action, give an action name and select your flow which you just created and provide values to the flow variables



Save your process builder and don't forget to activate it

Now everything is done try to create the City Record give postcode and state values and click on save and your record will be updated with the corresponding pin code.

That's it guys,


Monday, May 13, 2019

Prepopulate Lookup in Lightning record edit form when it override to New button in Service Console

In this article, we would learn how can we auto-populate with parent account when creating a new child record from the related list of parent.

In Salesforce when you create a master-detail relationship between two objects and whenever you create a child record from the parent related list, the parent record automatically auto populate lookup field of its parent when you try to create the child record.
But if you override the child object's New button with some custom lightning component and try to create a new child record in this case the parent record does not automatically auto-populate the lookup field of its parent.

So in this article, we would learn how to automatically auto-populate the lookup field of its parent.

For example, we have Account and Address object, Account is the parent and the Address is the child object, also I override Address component's New button with the custom lightning component in which I am using lighting record edit form to create the new record.

Here is the code for the lightning component

LightinigRecordEditForm.cmp

  <aura:component implements="lightning:actionOverride,force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction"  access="global" >
    
    
    <!-- Attributes --> 
    <aura:attribute name="parentRecordId" type="String" />   
    <aura:handler name="init" value="this" action="{!c.doInit}"/> 
    
    <lightning:card iconName="standard:account" title="New Address" class="">
        <div class="slds-p-left_large slds-p-right_medium"> 
            <lightning:recordEditForm
                                      onload="{!c.handleLoad}"
                                      recordId="{!v.recordId}"
                                      onsubmit="{!c.onSubmit}"
                                      onsuccess="{!c.onSuccess}"
                                      onerror="{!c.onError}"       
                                      objectApiName="Address__c">
                <lightning:messages />
                <h3 class="slds-section__title slds-theme--shade primaryPaletteBorder test-id__section-header-container" >
                    <span class="test-id__section-header-title section-header-title slds-p-horizontal--small slds-truncate" >Address Information</span>
                </h3>
                <div class="slds-grid">
                    <div class="slds-col slds-size_6-of-12 slds-p-around_small">                 
                        <lightning:inputField fieldName="Name" aura:id="addressName" />
                    </div>
                    <div class="slds-col slds-size_6-of-12 slds-p-around_small">
                        <lightning:inputField fieldName="Account__c" value="{!v.parentRecordId}"/>
                    </div>
                </div>
                
                
                <lightning:layout horizontalAlign="center" class="slds-m-top_large">
                    <lightning:button variant="neutral" label="Cancel" title="Cancel" type="text" onclick="{!c.onCancel}"/>
                    <lightning:button variant="brand" type="submit" name="save" label="Save" />
                </lightning:layout>
            </lightning:recordEditForm>     
        </div>
    </lightning:card>
</aura:component>
  
LightningRecordEditFormController.js

  ({
    doInit: function(component, event, helper){
     
        var parentId = helper.getParentId(component , event, 'inContextOfRef');
        var context = JSON.parse(window.atob(parentId));
        component.set("v.parentRecordId", context.attributes.recordId);
   
    },
    onSuccess : function(component, event, helper) {
        var toastEvent = $A.get("e.force:showToast");
        toastEvent.setParams({
            "title": "Success!",
            "message": "The record has been Saved successfully."
        });
        toastEvent.fire();
    },
    onSubmit : function(component, event, helper) {
    },
    onLoad : function(component, event, helper) {
        var toastEvent = $A.get("e.force:showToast");
        toastEvent.setParams({
            "title": "Loaded!",
            "message": "The record has been Loaded successfully ."
        });
        toastEvent.fire();
    },
    onError : function(component, event, helper) {
        var toastEvent = $A.get("e.force:showToast");
        toastEvent.setParams({
            "title": "Error!",
            "message": "Error."
        });
        toastEvent.fire();
    }
 
 
})
  
LightningRecordEditFormHelper.js
({
  getParentId: function(component, event, name) {
        name = name.replace(/[\[\]]/g, "\\$&");       
        var url = window.location.href;     
        var regex = new RegExp("[?&]" + name + "(=1\.([^&#]*)|&|#|$)");
        var results = regex.exec(url);
        if (!results) return null;
        if (!results[2]) return '';
        return decodeURIComponent(results[2].replace(/\+/g, " "));
    }
})
  

Tuesday, February 5, 2019

How to query fields which are in the fieldset using SOQL in Salesforce.

Hi all,
Today I am going to explain to you that how can you query all fields from fieldset.
Suppose you have created one fieldset in Contact object and you have also added some fields in that fileldset like this.

How to create fieldset in Salesforce?
Steps

  1. Enter your object name in the setup and click on fieldset.
  2. Click on New and enter details like it's label, API name etc.
  3. Click on save and then you will be redirected to on page where you can drag and drop all the fields which you want that should be in the fieldset.
So you are done with your fieldset and also you have added some fields to fieldset as well.
Now let's move to the next step.
So now you have two things

  1. Object API Name : Contact
  2. FieldSet API Name: testingFieldsetName (It will be same what you provide while creating fieldset)
Here is the code that will be used to query all fields available in the fieldset.


  String objectApiName = 'Contact';
String fieldSetName = 'testingFieldsetName';
       
//Get the fields from FieldSet
Schema.SObjectType sObjectTypeObj = Schema.getGlobalDescribe().get(objectApiName);
Schema.DescribeSObjectResult describeSObjectResultObj = sObjectTypeObj.getDescribe();           
Schema.FieldSet fieldSetObject = describeSObjectResultObj.FieldSets.getMap().get(fieldSetName);
      
//Field to be queried - fetched from fieldset
List<String> fieldsToQueryList = new List<String>();
       
for( Schema.FieldSetMember eachFieldSetMember : fieldSetObject.getFields() ){
    fieldsToQueryList.add(String.valueOf(eachFieldSetMember.getFieldPath()));
}
       
String query = 'SELECT '+ String.join(fieldsToQueryList , ',') + ' FROM CONTACT';
List<Contact> contactsList =  Database.query(query);
  
Hope this post helps you.



Wednesday, January 23, 2019

Line: 15, Column: 1 System.QueryException: List has no rows for assignment to SObject

you usually encounter this error when your soql query doesn't return any data and you tried to store the results retrieved from the SOQL to the sObject type variable or list of sobject type variable. 

Sunday, November 11, 2018

How to get Days, Hours and Minutes in specified format when two datetime fields are subtracted in formula field in salesforce

In this post we would learn how to get Days, Hours and Minutes in specified format when two datetime fields are subtracted in formula field in salesforce ?

Solution: 

TEXT(
FLOOR((Now()- CreatedDate))
) & " Days " &
TEXT(
FLOOR(MOD(((Now()- CreatedDate))*24,24))
) &" Hours " &
TEXT(
ROUND(MOD(((Now()- CreatedDate))*24*60),0)

)

you can replace Now() and createddate according to your datetime fields which you want to get datetime from.

Thursday, September 6, 2018

How to insert records of two different objects to the database using one single dml statement in salesforce??

This is the question that is usually asked in companies during interview that how can you  insert records of two different objects using one single dml statement. so after reading this article you will be able to explain your interviewer that how to do this.


  1.  First you need to create the instance of each object whether you are working with salesforce standard objects or custom objects. for example
          Account acc1 = new Account(Name = 'anyName');
          Contact con1 = new Contact(LastName = 'anyLastName');
         
       2.  Then you need to create the list of sObject to insert those instances created above into it.

          List<sObject> sObjectList = new List<sObject>();
  
       3.  Now you have to add those instances of different objects to the sObject List

          sObjectList.add(acc1);
          sObjectList.add(con1);
      
        4.  Now simply write one insert dml statement for sObjectList to insert both objects records                     simultaneously to the database.
     
            insert sobjectList;

hope you get useful information by reading the article.

Thanks.



Tuesday, September 4, 2018

How to enable user to enter only integer values to the input box using jQuery.


Answer:

Put this code in script tags and you'll be only able to enter only integer values in the input box.

$(document).ready(function(){
    $("input").keyup(function(){
      $(this).val( $(this).val().replace(/[^0-9]+/, '') );
        if($(this).val() == ''){
          $(this).val(0);                                 
        } 
    });
});



Friday, August 24, 2018

How to pass parameters to a JS function from VF page and then call apex method.??

Suppose requirement is that you want to send the id of a record to the apex method and your records are displaying on visualforce page using apex repeat. So this example will solve your problem.

visualforce page code


<apex:repeat value="{!contactList}" var="contact">
                    <tr>
                        <td>{!contact.Account.Name}</td>
                        <td onclick="myFunc('{!contact.Id}'); return false;">{!contact.FirstName}</td>
                        <td>{!contact.LastName}</td>
                        <td>{!contact.Phone}</td>
                    </tr>                                 
</apex:repeat>

so on the click of firstname you will call a js function that will call your action function and then you can call your apex method and pass your parameters


<script>
function myFunc(conId){           
         callActionFunction(conId);         
 }
         
</script>

your action function code put this code to your visualforce page


<apex:form id="fd">
            <apex:actionFunction action="{!callApexMethod}" name="callActionFunction"  rerender="">
            <apex:param id="myParam" name="contactid" value="" />
            </apex:actionFunction>
           
  </apex:form>

Apex Class


public void callApexMethod(){
         string passedParam1 = Apexpages.currentPage().getParameters().get('contactid');
      // write your logic here what you wanna perfom with id you just received from the contact recordyou click
}

Hopefully you get some information from this blog. If you have any problem you can comment down so that i can solve your problem. Thanks!