Wednesday, November 3, 2021

Dynamically Add/Remove rows using Lightning Web Components(LWC)

 This post explains how to add/remove the rows using the Lighting web component(LWC).

HTML Code:

<template>
   <lightning-card>
      <lightning-spinner if:true={isSpinner} variant="brand" size="large"> </lightning-spinner>
      <lightning-layout>
         <lightning-layout-item size="12">
            <lightning-button class="slds-float--right slds-m-around_small" variant="brand" label="Save"
               onclick={saveRows}>
            </lightning-button>
            <table class="slds-table slds-table_cell-buffer slds-table_bordered slds-border_left slds-border_right"
               aria-labelledby="element-with-table-label other-element-with-table-label">
               <thead>
                  <tr>
                     <th>Name</th>
                     <th>Industry</th>
                     <th>Phone</th>
                     <th>Email</th>
                     <th></th>
                  </tr>
               </thead>
               <tbody>
                  <template for:each={filterList} for:item="filterData" for:index="index">
                     <tr key={filterData}>
                        <td>
                           <lightning-input type="text" name="accName" data-index={index}
                              variant="label-hidden" placeholder="" onchange={handleChange}
                              value={filterData.Name}>
                           </lightning-input>
                        </td>
                        <td>
                           <lightning-combobox name="industry" data-index={index} variant="label-hidden"
                              placeholder="" onchange={handleChange} value={filterData.Industry}
                              options={industryOptions}>
                           </lightning-combobox>
                        </td>
                        <td>
                           <lightning-input type="text" name="accEmail" data-index={index}
                              variant="label-hidden" placeholder="" onchange={handleChange}
                              value={filterData.Email}>
                           </lightning-input>
                        </td>
                        <td>
                           <lightning-input type="text" name="accPhone" data-index={index}
                              value={filterData.Phone} variant="label-hidden" onchange={handleChange}>
                           </lightning-input>
                        </td>
                        <td>
                           <lightning-button-icon data-index={filterData.id} class="slds-float--right"
                              icon-name="action:new" onclick={handleAddRow}></lightning-button-icon>
                           <lightning-button-icon data-index={filterData.id} class="slds-float--right"
                              icon-name="action:delete" onclick={handleRemoveRow}></lightning-button-icon>
                        </td>
                     </tr>
                  </template>
               </tbody>
            </table>
         </lightning-layout-item>
      </lightning-layout>
   </lightning-card>
</template>

JS Code:
import { LightningElement, wire } from 'lwc';
import { getPicklistValues } from 'lightning/uiObjectInfoApi';
import { getObjectInfo } from 'lightning/uiObjectInfoApi';
import ACCOUNT_OBJECT from '@salesforce/schema/Account';
import INDUSTRY_FIELD from '@salesforce/schema/Account.Industry';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import saveAccounts from '@salesforce/apex/LWCExampleController.saveAccounts';

export default class DynamicallyAddRow extends LightningElement {
    industryOptions = [{ value: '-None-', label: '' }];
    filterList = [];
    keyIndex = 0;
    isSpinner = false;

    @wire(getObjectInfo, { objectApiName: ACCOUNT_OBJECT })
    accountinfo;

    @wire(getPicklistValues, { recordTypeId: '$accountinfo.data.defaultRecordTypeId', fieldApiName: INDUSTRY_FIELD })
    industryValues({ data, error }) {
        if (data) {
            data.values.forEach(val => {
                this.industryOptions = [...this.industryOptions, { value: val.value, label: val.label }];
            });
        }
        else if (error) {
            this.processErrorMessage(error);
        }
    }

    connectedCallback() {
        this.handleAddRow();
    }

    handleChange(event) {
        if (event.target.name == 'accName') {
            this.filterList[event.currentTarget.dataset.index].Name = event.target.value;
        }
        else if (event.target.name == 'industry') {
            this.filterList[event.currentTarget.dataset.index].Industry = event.target.value;
        }
        else if (event.target.name == 'accEmail') {
            this.filterList[event.currentTarget.dataset.index].Email = event.target.value;
        }
        else if (event.target.name == 'accPhone') {
            this.filterList[event.currentTarget.dataset.index].Phone = event.target.value;
        }
    }

    handleAddRow() {
        let objRow = {
            Name: '',
            Industry: '',
            Phone: '',
            Email: '',
            id: ++this.keyIndex
        }

        this.filterList = [...this.filterList, Object.create(objRow)];
    }

    handleRemoveRow(event) {
        this.filterList = this.filterList.filter((ele) => {
            return parseInt(ele.id) !== parseInt(event.currentTarget.dataset.index);
        });

        if (this.filterList.length == 0) {
            this.handleAddRow();
        }
    }

    saveRows() {
        console.log('this.filterList => ', this.filterList);
        this.isSpinner = true;
        saveAccounts({ lstAccs: this.filterList }).then(result => {
            this.isSpinner = false;
            this.showToastMessage('success', 'Accounts Saved Successfully!!', 'Success');
            this.filterList = [];
            if (this.filterList.length == 0) {
                this.handleAddRow();
            }
            console.log('result ==> ', result);
        }).catch(error => {
            this.processErrorMessage(error);
            this.isSpinner = false;
        })
    }

    processErrorMessage(message) {
        let errorMsg = '';
        if (message) {
            if (message.body) {
                if (Array.isArray(message.body)) {
                    errorMsg = message.body.map(e => e.message).join(', ');
                } else if (typeof message.body.message === 'string') {
                    errorMsg = message.body.message;
                }
            }
            else {
                errorMsg = message;
            }
        }
        this.showToastMessage('error', errorMsg, 'Error!');
    }

    showToastMessage(variant, message, title) {
        this.dispatchEvent(
            new ShowToastEvent({
                title: title,
                message: message,
                variant: variant
            })
        );
    }
}

Apex Class:
public inherited sharing class LWCExampleController {

    @AuraEnabled
    public static List<Account> saveAccounts(List<Account> lstAccs) {
        try {
            insert lstAccs;
            return lstAccs;
        }
        catch(Exception ex) {
            throw new AuraHandledException(ex.getMessage());
        }
    }
}
Output:


Saturday, June 19, 2021

How to get Community Id and base path in lighting web components(lwc)

This post explains how to get community Id and base path in lightning web components(lwc)

HTML Code

<template>
    <lightning-card>
        <div class="slds-text-heading_medium slds-text-align_center">
            <b>Community Id:</b> {currentcommunityId}
        </div>
        <div class="slds-text-heading_medium slds-text-align_center">
            <b>Community Basepath:</b> {currentcommunityBasePath}
        </div>
    </lightning-card>
</template>

Javascript Code

import {LightningElement, api, track, wire} from 'lwc';
 
// We can get the community Id for use in the callout
import communityId from '@salesforce/community/Id';
 
// Get the base path for navigating to non-named pages
import communityBasePath from '@salesforce/community/basePath';

export default class CommunityName extends LightningElement {

    currentcommunityId;
    currentcommunityBasePath;

    connectedCallback() {
        this.currentcommunityId = communityId;
        this.currentcommunityBasePath = communityBasePath;
    }

}
Configuration File

<?xml version="1.0"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
	<apiVersion>52.0</apiVersion>
	<isExposed>true</isExposed>
	<targets>
		<target>lightning__RecordPage</target>
		<target>lightningCommunity__Page</target>
		<target>lightningCommunity__Default</target>
	</targets>
</LightningComponentBundle>
Output



Saturday, May 1, 2021

LeadStaus Object in Salesforce

 LeadStatus object Represents the status of a Lead, such as Open, Qualified, or Converted.

SOQL Query

select id, MasterLabel, IsConverted, IsDefault from Leadstatus

Result



Dynamic Search/Custom Search functionality in Lightning Web Components(lwc)

 HTML Code

<template>
    <lightning-card title="Custom Search Functionality in LWC" icon-name="standard:account">
        <div if:true={errorMsg} style="margin-left: 3%;">
            <p style="color: red;">{errorMsg}</p>
        </div>

        <lightning-layout multiple-rows="true" vertical-align="end">
            <lightning-layout-item size="12" small-device-size="10" medium-device-size="8" large-device-size="6" padding="around-small">
                    <div class="slds-form-element">
                            <div class="slds-form-element__control">
                                    <lightning-input type="text" 
                                                     label="Enter Account Name" 
                                                     onchange={handleAccountName} ></lightning-input>
                            </div>
                        </div> 
            </lightning-layout-item>
            <lightning-layout-item size="12" small-device-size="2" medium-device-size="2" large-device-size="2" padding="around-small">
                    <lightning-button label="Search" 
                                      variant="brand" 
                                      onclick={handleSearch}></lightning-button>
                </lightning-layout-item>
            </lightning-layout><br/>

        <div if:true={searchData}>
            <lightning-datatable data={searchData} 
                                 columns={columns} 
                                 key-field="id"
                                 hide-checkbox-column="true"></lightning-datatable>
        </div>
    </lightning-card>

</template>

JS Code

import { LightningElement } from 'lwc';
import serachAccs from '@salesforce/apex/LWCExamples.retriveAccs';

const columns = [
    {
        label: 'Name',
        fieldName: 'Name'
    }, {
        label: 'Industry',
        fieldName: 'Industry',
    }, {
        label: 'Phone',
        fieldName: 'Phone',
        type: 'phone',
    }, {
        label: 'Type',
        fieldName: 'Type',
        type: 'text'
    },
];

export default class DynamicSearchInLWC extends LightningElement {

    searchData;
    columns = columns;
    errorMsg = '';
    strSearchAccName = '';
    

    handleAccountName(event) {
        this.errorMsg = '';
        this.strSearchAccName = event.currentTarget.value;
    }

    handleSearch() {
        if(!this.strSearchAccName) {
            this.errorMsg = 'Please enter account name to search.';
            this.searchData = undefined;
            return;
        }

        serachAccs({strAccName : this.strSearchAccName})
        .then(result => {
            this.searchData = result;
        })
        .catch(error => {
            this.searchData = undefined;
            if(error) {
                if (Array.isArray(error.body)) {
                    this.errorMsg = error.body.map(e => e.message).join(', ');
                } else if (typeof error.body.message === 'string') {
                    this.errorMsg = error.body.message;
                }
            }
        }) 
    }
}

Apex Class

public inherited sharing class LWCExamples {
 
    @AuraEnabled(Cacheable = true)
    public static list<Account> retriveAccs(String strAccName) {
        strAccName = '%' + strAccName + '%';
        list<Account> lstAccs = [SELECT  Id, Name, Industry, Phone, Type From Account WHERE Name LIKE :strAccName];

        if(lstAccs.isEmpty()) {
            throw new AuraHandledException('No Record Found..');
        }
        return lstAccs; 
    }
}

Result



Thursday, February 4, 2021

jQuery Datatable in Lightning Web Component(lwc)

This post explains how to use jquery data tables in the lightning web component(lwc).


Prerequisites:

Step 1 : Download Required Resources 

1. Download jQuery DataTables Plugin

Click on the following link to download the DataTables library. [version 1.10.18]


This zip file includes CSS, javascript, and other files related to the plugin.

2. Download jQuery library [version 3.3.1 Recommended]

Click on the following link to download JQuery 3.3.1 minified version. [3.3.1 Recommended]


Step 2: Upload Files to static resource

upload files to static resourecs



Demo:

HTML Code:
<template>
   <lightning-card title="JQuery Datatable Demo">
      <div class="slds-m-around_medium">
         <table lwc:dom="manual"
            class="tableClass slds-table slds-table_cell-buffer slds-table_bordered" 
            style="width:100%">
         </table>
      </div>
   </lightning-card>
</template>
JS Code:
import {
    LightningElement
} from 'lwc';
import dataTableResource from '@salesforce/resourceUrl/DataTableDemo';
import JqueryResource from '@salesforce/resourceUrl/Jquery331';
import {
    loadScript,
    loadStyle
} from 'lightning/platformResourceLoader';
import {
    ShowToastEvent
} from 'lightning/platformShowToastEvent';
// import toast message event .

// import apex class and it's methods.
import getAccounts from '@salesforce/apex/LWCExampleController.getAccounts';

export default class JqueryDataTableLWCDemo extends LightningElement {
    accounts = [];
    error;

    async connectedCallback() {
        await this.fetchAccoutns();

        Promise.all([
            loadScript(this, JqueryResource),
            loadScript(this, dataTableResource + '/DataTables-1.10.18/js/jquery.dataTables.min.js'),
            loadStyle(this, dataTableResource + '/DataTables-1.10.18/css/jquery.dataTables.min.css'),
        ]).then(() => {
            console.log('script loaded sucessfully');

            const table = this.template.querySelector('.tableClass');
            const columnNames = ['Name', 'Industry', 'Type', 'Phone', 'Rating'];
            let tableHeaders = '<thead> <tr>';
            columnNames.forEach(header => {
                tableHeaders += '<th>' + header + '</th>';
            });
            tableHeaders += '</tr></thead>';
            table.innerHTML = tableHeaders;

            let jqTable = $(table).DataTable();
            $('div.dataTables_filter input').addClass('slds-input');
            $('div.dataTables_filter input').css("marginBottom", "10px");

            this.accounts.forEach(rec => {
                let tableRows = [];
                tableRows.push('<a href="/lightning/r/Account/' + rec.Id + '/view">' + rec.Name + '</a>');
                tableRows.push(rec.Industry != undefined ? rec.Industry : '');
                tableRows.push(rec.Type != undefined ? rec.Type : '');
                tableRows.push(rec.Phone != undefined ? rec.Phone : '');
                tableRows.push(rec.Rating != undefined ? rec.Rating : '');
                jqTable.row.add(tableRows);
            });
            jqTable.draw();

        }).catch(error => {
            this.error = error;
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Error!!',
                    message: JSON.stringify(error),
                    variant: 'error',
                }),
            );
        });
    }

    async fetchAccoutns() {
        await getAccounts()
            .then(data => {
                if (data) {
                    this.accounts = data;
                }
            })
            .catch(error => {
                this.error = error;
                this.accounts = undefined;
                this.error = 'Unknown error';
                if (Array.isArray(error.body)) {
                    this.error = error.body.map(e => e.message).join(', ');
                } else if (typeof error.body.message === 'string') {
                    this.error = error.body.message;
                }
                this.dispatchEvent(
                    new ShowToastEvent({
                        title: 'Error!!',
                        message: error,
                        variant: 'error',
                    }),
                );
            });
    }
}
Apex Class
public inherited sharing class LWCExampleController {
	@AuraEnabled(Cacheable = true)
	public static List<Account> getAccounts(){
	  return [SELECT Id, Name,Industry, Type, Phone, Rating, AccountNumber FROM Account ORDER BY Name];
	}
}

Tuesday, February 2, 2021

Custom Spinner in Lightning Web Component(lwc)

 This post explains how to create a custom spinner in lightning web components(lwc)

HTML Code

<template>
   <lightning-card>
      <div align="center"  if:true={isSpinner}>
         <div class="loader"></div>
         Please wait...
      </div>
      <div align="center" if:true={showButon}>
         <lightning-button label="Enable Spinner" variant="brand" onclick={enableSpinner}>
         </lightning-button>
      </div>
   </lightning-card>
</template>

JS Code

import {
    LightningElement
} from 'lwc';
export default class Customspinner extends LightningElement {
    isSpinner = false;
    showButon = true;

    enableSpinner() {
        if (!this.isSpinner) {
            this.isSpinner = true;
            this.showButon = false;
        }
    }
}
CSS Code
.loader {
  border: 5px solid #f3f3f3;
  border-radius: 50%;
  border-top: 5px solid #3498db;
  width: 60px;
  height: 60px;
  -webkit-animation: spin 2s linear infinite; /* Safari */
  animation: spin 2s linear infinite;
}

/* Safari */
@-webkit-keyframes spin {
  0% { -webkit-transform: rotate(0deg); }
  100% { -webkit-transform: rotate(360deg); }
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
Output


Tuesday, January 19, 2021

Expand/Collapse Sections In Salesforce Lightning Web Component(lwc)

This post explains how to create expand/collapse sections in Salesforce Lightning Web Component(lwc) using the details tag in html.

Demo:

HTML Code:

<template>
    <lightning-card title="Expand/Collapse Sections In Salesforce Lightning Web Component"><br />
        <div style="padding-left: 10px;">
            <details open>
                <summary>India</summary>
                <ul>
                    <li>Hyderabad</li>
                    <li>Delhi</li>
                    <li>Mumbaie</li>
                </ul>
            </details><br>
            <details>
                <summary>USA</summary>
                <ul>
                    <li>New York</li>
                    <li>Las Vegas</li>
                    <li>Miami</li>
                </ul>
            </details><br>
            <details>
                <summary>China</summary>
                <ul>
                    <li>Shenzhen</li>
                    <li>Guangzhou</li>
                    <li>Shanghai</li>
                </ul>
            </details>
        </div>
    </lightning-card>
</template>

CSS

details > summary {
  padding: 4px;
  background-color: #eeeeee;
  outline: none;
}

Output