Saturday, October 26, 2019

Custom Dependent Picklist Field in Salesforce using Lightning Web Components

This post explains how to implement custom dependent picklist field using lightning web components(lwc)



To get the picklist values in lightning web components we can use 'getPicklistValues' or 'getPicklistValuesByRecordType' wire adapters, these wire adapters uses the lightning/uiObjectInfoApi scoped module to get the picklist values based on specific Field or based on Record Type.

Syntax

import { getPicklistValues, getPicklistValuesByRecordType } from 'lightning/uiObjectInfoApi';

For the demo, I created two fields on Account.
Controlling Field(picklist): Account Country
Dependent Field(picklist): Account State

The structure of the dependent field


HTML Code
<template>
    <lightning-card title="Custom Dependent Picklist using Lightning Web Components"><br/>
        <div class="slds-grid slds-gutters" style="margin-left:3%">
            <div class="slds-col slds-size_1-of-4">
                <lightning-combobox label="Account Country" 
                                    name="country" 
                                    onchange={handleCountryChange} 
                                    options={controllingValues} 
                                    placeholder="--None--" 
                                    value={selectedCountry}></lightning-combobox><br/>
                
                <div if:true={selectedCountry}>
                    Selected Country: <b>{selectedCountry}</b>
                </div>
            </div>
            <div class="slds-col slds-size_1-of-4">
                <lightning-combobox label="Account State" 
                                    name="state"
                                    onchange={handleStateChange} 
                                    options={dependentValues} 
                                    placeholder="--None--" 
                                    value={selectedState}
                                    disabled={isEmpty}></lightning-combobox><br/>
                <div if:true={selectedState}>
                    Selected State: <b>{selectedState}</b>
                </div>
            </div>
        </div><br/>

        <div if:true={error}>
            <p>{error}</p>
        </div>
    </lightning-card>
</template>

Javascript Controller Code
import { LightningElement, wire, track } from 'lwc';
import { getPicklistValuesByRecordType } from 'lightning/uiObjectInfoApi';
import { getObjectInfo } from 'lightning/uiObjectInfoApi';
import ACCOUNT_OBJECT from '@salesforce/schema/Account';

export default class DependentPickListInLWC extends LightningElement {

    // Reactive variables
    @track controllingValues = [];
    @track dependentValues = [];
    @track selectedCountry;
    @track selectedState;
    @track isEmpty = false;
    @track error;
    controlValues;
    totalDependentValues = [];

    // Account object info
    @wire(getObjectInfo, { objectApiName: ACCOUNT_OBJECT })
    objectInfo;

    // Picklist values based on record type
    @wire(getPicklistValuesByRecordType, { objectApiName: ACCOUNT_OBJECT, recordTypeId: '$objectInfo.data.defaultRecordTypeId'})
    countryPicklistValues({error, data}) {
        if(data) {
            this.error = null;

            let countyOptions = [{label:'--None--', value:'--None--'}];

            // Account Country Control Field Picklist values
            data.picklistFieldValues.Account_Country__c.values.forEach(key => {
                countyOptions.push({
                    label : key.label,
                    value: key.value
                })
            });

            this.controllingValues = countyOptions;

            let stateOptions = [{label:'--None--', value:'--None--'}];

             // Account State Control Field Picklist values
            this.controlValues = data.picklistFieldValues.Account_State__c.controllerValues;
            // Account State dependent Field Picklist values
            this.totalDependentValues = data.picklistFieldValues.Account_State__c.values;

            this.totalDependentValues.forEach(key => {
                stateOptions.push({
                    label : key.label,
                    value: key.value
                })
            });

            this.dependentValues = stateOptions;
        }
        else if(error) {
            this.error = JSON.stringify(error);
        }
    }

    handleCountryChange(event) {
        // Selected Country Value
        this.selectedCountry = event.target.value;
        this.isEmpty = false;
        let dependValues = [];

        if(this.selectedCountry) {
            // if Selected country is none returns nothing
            if(this.selectedCountry === '--None--') {
                this.isEmpty = true;
                dependValues = [{label:'--None--', value:'--None--'}];
                this.selectedCountry = null;
                this.selectedState = null;
                return;
            }

            // filter the total dependent values based on selected country value 
            this.totalDependentValues.forEach(conValues => {
                if(conValues.validFor[0] === this.controlValues[this.selectedCountry]) {
                    dependValues.push({
                        label: conValues.label,
                        value: conValues.value
                    })
                }
            })

            this.dependentValues = dependValues;
        }
    }

    handleStateChange(event) {
        this.selectedState = event.target.value;
    }
}

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

You can also find the code on Github
GitHub Link


Result

Monday, October 21, 2019

How to get Current Logged in User information in Lightning Web Component(lwc)

This post explains how to get logged in user information in lightning web components(lwc)



check below post how to import current user id in lightning web components
https://www.salesforcecodecrack.com/2019/01/how-to-import-current-user-id.html

To get the record details to use the getRecord wire adapter from 'lightning/uiRecordApi' scope module.
Syntax
import { getRecord } from 'lightning/uiRecordApi';

HTML code
<template>
    <lightning-card title="Current Logged User Information">
        <template if:true={objUser}>
            <dl class="slds-list_horizontal slds-wrap" style="margin-left: 3%;">
                <dt class="slds-item_label slds-truncate" title="First Name">First Name:</dt>
                <dd class="slds-item_detail slds-truncate"><b>{objUser.FirstName}</b></dd>
                <dt class="slds-item_label slds-truncate" title="Last Name">Last Name:</dt>
                <dd class="slds-item_detail slds-truncate"><b>{objUser.LastName}</b></dd>
                <dt class="slds-item_label slds-truncate" title="Full Name">Name:</dt>
                <dd class="slds-item_detail slds-truncate"><b>{objUser.Name}</b></dd>
                <dt class="slds-item_label slds-truncate" title="Alias">Alias:</dt>
                <dd class="slds-item_detail slds-truncate"><b>{objUser.Alias}</b></dd>
                <dt class="slds-item_label slds-truncate" title="Active">Is Active:</dt>
                <dd class="slds-item_detail slds-truncate"><b>{objUser.IsActive}</b></dd>
            </dl>
        </template>
    </lightning-card>
</template>

Javascript Controller 
import { LightningElement, track, wire} from 'lwc';

// importing to get the record details based on record id
import { getRecord } from 'lightning/uiRecordApi';

// impoting USER id
import USER_ID from '@salesforce/user/Id'; 

export default class CurrentUserDetailsInLWC extends LightningElement {

    @track objUser = {};
    
    // using wire service getting current user data
    @wire(getRecord, { recordId: USER_ID, fields: ['User.FirstName', 'User.LastName', 'User.Name', 'User.Alias', 'User.IsActive'] })
    userData({error, data}) {
        if(data) {
            window.console.log('data ====> '+JSON.stringify(data));

            let objCurrentData = data.fields;

            this.objUser = {
                FirstName : objCurrentData.FirstName.value,
                LastName : objCurrentData.LastName.value,
                Name : objCurrentData.Name.value,
                Alias : objCurrentData.Alias.value,
                IsActive : objCurrentData.IsActive.value,
            }
        } 
        else if(error) {
            window.console.log('error ====> '+JSON.stringify(error))
        } 
    }

}

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

Result

Sunday, October 20, 2019

Lightning Web Component - Display reference/related objects fields data in lightning data table

This post explains how to display reference object fields data in the lightning data table in lightning web components(lwc)


HTML code
<template>
    <lightning-card title="Showing Reference Fields Data in Lightning Datatable">
        <lightning-datatable columns={columns} 
                            data={data} 
                            key-field="id"
                            hide-checkbox-column="true"
                            show-row-number-column="true"></lightning-datatable>
    </lightning-card>
</template>

Javascript Controller
import {LightningElement, track, wire} from 'lwc';

// importing Apex Class
import getOppdata from '@salesforce/apex/LWCExampleController.retriveOpportunities';

// Datatable Columns
const columns = [
    {
        label: 'Opportunity Name',
        fieldName: 'Name',
        type: 'text',
    }, {
        label: 'Account Name',
        fieldName: 'AccountName',
        type: 'text'
    }, {
        label: 'Account Owner',
        fieldName: 'AccountOwner',
        type: 'text'
    }, {
        label: 'Opportunity Owner',
        fieldName: 'OpportunityOwner',
        type: 'text'
    }, {
        label: 'CreatedDate',
        fieldName: 'CreatedDate',
        type: 'date'
    }
];


export default class ReferenceDataInLwcDatatable extends LightningElement {
    @track data = [];
    @track columns = columns;

    @wire(getOppdata)
    opp({error, data}) {
        if(data) {

            let currentData = [];

            data.forEach((row) => {

                /* 
                * Creating the an empty object
                * To reslove "TypeError: 'set' on proxy: trap returned falsish for property"
                */

                let rowData = {};

                rowData.Name = row.Name;
                rowData.CreatedDate = row.CreatedDate;

                // Account related data
                if (row.Account) {
                    rowData.AccountName = row.Account.Name;
                    rowData.AccountOwner = row.Account.Owner.Name;
                }

                // Owner releated data
                if (row.Owner) {
                    rowData.OpportunityOwner = row.Owner.Name;
                }

                currentData.push(rowData);
            });

            this.data = currentData;
        }
        else if(error) {
            window.console.log(error);
        }
    }
}

Apex Class
public inherited sharing class LWCExampleController {    
    @AuraEnabled(cacheable=true)
    public static list<Opportunity> retriveOpportunities() {
        return [SELECT Id, Name, Account.Name, Account.owner.name, Owner.Name, CreatedDate FROM Opportunity LIMIT 10];
    }
}

Result

Saturday, October 19, 2019

How to test salesforce performance and speed in Lightning Experience

If your Users are experiencing slow page-loading times when using Lightning Experience, it may be related to one or more of the following issue types.
  • Geographical
  • Device
  • Browser
  • Salesforce organization configuration issues

It is a simple online tool to measure your browser Javascript speed and your internet connection speed to Salesforce’s servers. 

How to access the tool?

To access this tool simply log-on to your Salesforce org and remove everything after “[your domain name].lightning.force.com/” in the browser URL and add the speedtest.jsp 
Ex:
https://<your domain>.lightning.force.com/speedtest.jsp
OR
https://[instance].salesforce.com/speedtest.jsp


Click the "Test Speed" button, tool tests all the performances, Once the test is finished, results will be displayed.

Reference
https://help.salesforce.com/articleView?id=000316034&language=en_US&type=1&mode=1

Thursday, October 17, 2019

Custom Data table with multiple row selection in Lightning Web Components(lwc)

This post explains how to implement custom data table with multiple row selection in Lightning Web Component(lwc)



customDatatableInLWC.html
<template>
    <lightning-card title="Custom Data table in Lightning Web Components">
        <div class="slds-grid slds-gutters">
            <div class="slds-col">
                <span></span>
            </div>
            <div class="slds-col">
                <span>
                    <lightning-button label="Show Selected Contacts" onclick={showContacts} style="margin-left: 40%" variant="brand"></lightning-button>
                </span>
            </div>
        </div><br/>
        <table class="slds-table slds-table_cell-buffer slds-table_bordered">
            <thead>
                <tr class="slds-line-height_reset">
                    <th class="" scope="col">
                        <div class="slds-truncate">
                            <lightning-input onchange={allSelected} type="checkbox"></lightning-input>
                        </div>
                    </th>
                    <th class="" scope="col">
                        <div class="slds-truncate" title="Name">Name</div>
                    </th>
                    <th class="" scope="col">
                        <div class="slds-truncate" title="First Name">First Name</div>
                    </th>
                    <th class="" scope="col">
                        <div class="slds-truncate" title="Last Name">Last Name</div>
                    </th>
                    <th class="" scope="col">
                        <div class="slds-truncate" title="Phone">Phone</div>
                    </th>
                    <th class="" scope="col">
                        <div class="slds-truncate" title="Email">Email</div>
                    </th>
                </tr>
            </thead>
            <tbody>
                <template for:each={data} for:item="con">
                    <tr key={con.Id}>
                        <th scope="col">
                            <div>
                                <lightning-input type="checkbox" value={con.Name} data-id={con.Id}></lightning-input>
                            </div>
                        </th>
                        <th scope="col">
                            <div>{con.Name}</div>
                        </th>
                        <th scope="col">
                            <div>{con.FirstName}</div>
                        </th>
                        <th scope="col">
                            <div>{con.LastName}</div>
                        </th>
                        <th scope="col">
                            <div>
                                <lightning-formatted-phone value={con.Phone}></lightning-formatted-phone>
                            </div>
                        </th>
                        <th scope="col">
                            <div>
                                <lightning-formatted-email value={con.Email}></lightning-formatted-email>
                            </div>
                        </th>
                    </tr>
                </template>
            </tbody>
        </table>

        <!--
            This modal box used to show the selected contacts
        -->

        <div if:true={selectedCons}>
            <template if:true={bShowModal}>
                <section aria-describedby="modal-content-id-1" aria-labelledby="modal-heading-01" aria-modal="true" class="slds-modal slds-fade-in-open" role="dialog" tabindex="-1">
                    <div
                        class="slds-modal__container">
                        <!-- modal header start -->
                        <header class="slds-modal__header">
                            <button class="slds-button slds-button_icon slds-modal__close slds-button_icon-inverse" onclick={closeModal} title="Close">
                                <lightning-icon alternative-text="close" icon-name="utility:close" size="small" variant="inverse"></lightning-icon>
                                <span class="slds-assistive-text">Close</span>
                            </button>
                            <h2 class="slds-text-heading_medium slds-hyphenate" id="modal-heading-01">Selected Contacts Records</h2>
                        </header>
                        <!-- modal body start -->
                        <div class="slds-modal__content slds-p-around_medium" id="modal-content-id-1">
                            <template for:each={selectedCons} for:item="con">
                                <dl class="slds-list_horizontal slds-wrap" if:true={con.Id} key={con.Id}>
                                    <dt class="slds-item_label slds-truncate" title="First Name">Contact Name:</dt>
                                    <dd class="slds-item_detail slds-truncate">{con.Name}</dd>
                                    <dt class="slds-item_label slds-truncate" title="LastName">Contact Id:</dt>
                                    <dd class="slds-item_detail slds-truncate">{con.Id}</dd>
                                    <hr></dl>
                                </template>

                            </div>
                            <!-- modal footer start-->
                            <footer class="slds-modal__footer">
                                <button class="slds-button slds-button_neutral" onclick={closeModal}>Cancel</button>
                            </footer>
                        </div>
                    </section>
                    <div class="slds-backdrop slds-backdrop_open"></div>
                </template>
            </div>
        </lightning-card>
    </template>

customDatatableInLWC.js
import { LightningElement, track, wire } from 'lwc';

// importing Apex Class
import retriveCons from '@salesforce/apex/LWCExampleController.getContacts';

export default class CustomHTMLDatatable extends LightningElement {
    // reactive variables
    @track data = [];
    @track error;
    @track bShowModal = false;
    @track selectedCons;

    // opening the modal
    openModal() { this.bShowModal = true; }
    // closeing the modal
    closeModal() { this.bShowModal = false;}

    // Getting Contacts using Wire Service
    @wire(retriveCons)
    contacts(result) {
        if (result.data) {
            this.data = result.data;
            this.error = undefined;

        } else if (result.error) {
            this.error = result.error;
            this.data = undefined;
        }
    }

    // Select the all rows
    allSelected(event) {
        let selectedRows = this.template.querySelectorAll('lightning-input');
        
        for(let i = 0; i < selectedRows.length; i++) {
            if(selectedRows[i].type === 'checkbox') {
                selectedRows[i].checked = event.target.checked;
            }
        }
    }

    showContacts() {
        this.bShowModal = true;

        this.selectedCons = [];

        let selectedRows = this.template.querySelectorAll('lightning-input');

        // based on selected row getting values of the contact
        for(let i = 0; i < selectedRows.length; i++) {
            if(selectedRows[i].checked && selectedRows[i].type === 'checkbox') {
                this.selectedCons.push({
                    Name: selectedRows[i].value,
                    Id: selectedRows[i].dataset.id
                })
            }
        }
    }

}

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


Apex Class
public inherited sharing class LWCExampleController {    
 @AuraEnabled(Cacheable = true)
    public static List<Contact> getContacts(){
        return [SELECT Id, Name, FirstName,LastName, Phone, Email FROM Contact limit 10];
    }
}

Result