tag:blogger.com,1999:blog-64572520888733712922024-03-28T23:30:04.702-04:00Salesforce Lightning Web ComponentsAmolhttp://www.blogger.com/profile/04561932834601726448noreply@blogger.comBlogger7125tag:blogger.com,1999:blog-6457252088873371292.post-52508750480515140922019-09-09T15:15:00.002-04:002020-09-08T08:28:34.357-04:00Salesforce: Export to Excel with Lightning Web Component<head>
<script data-ad-client="ca-pub-6231630339453617" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
</head>
<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="color: #20124d; font-size: large;">Hello Guys,</span><br />
<span style="color: #20124d;"><br /></span>
<span style="color: #20124d; font-size: large;">I hope you are doing well. In this post, we are going to see an implementation of "<b>Export to Excel" </b>in lightning web components.</span><br />
<span style="color: #20124d;"><span style="font-size: large;"><br /></span>
</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqOakEcqu70vblIf96fsOgdQZviMKKyqEM9Qw3IFgp8xmZUvFgd6EFaLQPFf0NQ9v2sdyhqJQRHOWrPuLtILOMIQ_1__dScQCRY5O3Q5t_ciy203lZOB2hpq0yNpVdcU1jIatYSvoCcAG7/s1600/Capture.PNG" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><span style="color: #20124d;"><img border="0" data-original-height="294" data-original-width="1340" height="137" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqOakEcqu70vblIf96fsOgdQZviMKKyqEM9Qw3IFgp8xmZUvFgd6EFaLQPFf0NQ9v2sdyhqJQRHOWrPuLtILOMIQ_1__dScQCRY5O3Q5t_ciy203lZOB2hpq0yNpVdcU1jIatYSvoCcAG7/s640/Capture.PNG" width="640" /></span></a></div>
<span style="color: #20124d;"><span style="font-size: large;"><br /></span>
<span style="font-size: large;"><br /></span>
</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgO3oBxMAk2Gv24cRLvGyhMHjz8QH5pcp-RS3ObIed-oWE6F7POiGFfZ4eCZPAk5wfXokyTf4KnRIS-3gyNPSxIlZblccY40Wfg5L3fGHvuYeZV4i_0TKswovxxGXrZEBUpd_o5_xPLEE8C/s1600/animation.gif" style="margin-left: 1em; margin-right: 1em;"><span style="color: #20124d;"><img border="0" data-original-height="179" data-original-width="320" height="356" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgO3oBxMAk2Gv24cRLvGyhMHjz8QH5pcp-RS3ObIed-oWE6F7POiGFfZ4eCZPAk5wfXokyTf4KnRIS-3gyNPSxIlZblccY40Wfg5L3fGHvuYeZV4i_0TKswovxxGXrZEBUpd_o5_xPLEE8C/s640/animation.gif" width="640" /></span></a></div>
<div>
<span style="color: #20124d;"><br /></span></div>
<div>
<span style="color: #20124d; font-size: large;">Exporting the data in Excel is a very common requirement for Developers. We will see how this can be achieved with Lightning web components.</span><br />
<span style="color: #20124d;"><span style="font-size: large;"><br /></span>
<span style="font-size: large;">Following HTML code just do a couple of things.</span></span><br />
<div style="text-align: left;">
</div>
<ul style="text-align: left;">
<li><span style="color: #20124d; font-size: large;"> Show a link to "Download Excel"</span></li>
<li><span style="color: #20124d; font-size: large;"> Show the data to be exported, in the lightning data table.</span></li>
<li><span style="color: #20124d; font-size: large;"> Click on the Download Excel button would call the js method called </span><b style="color: #20124d; font-size: x-large;">exportToCSV.</b></li>
</ul>
<br />
<span style="color: #20124d; font-size: large;"><b><br /></b></span>
<br />
<h3 style="text-align: left;">
<i style="font-family: arial, helvetica, sans-serif;"><b><span style="color: #20124d; font-size: large;">exportToExcelDemo.html</span></b></i></h3>
</div>
<div>
<pre style="background: rgb(240, 240, 240); border: 1px dashed rgb(204, 204, 204); font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="overflow-wrap: normal;"><span style="color: #20124d;"> <template>
<a target="_self" class="slds-button" download="ExportToCSV.csv" href={hrefdata} onclick={exportToCSV}
style="margin-left: 80%;">Download Excel</a>
<lightning-datatable data={contactList} columns={contactColumns} key-field="id"
hide-checkbox-column="true">
</lightning-datatable>
</template>
</span></code></pre>
<span style="color: #20124d; font-size: large;">This js file contains the main logic to export the data.</span><br />
<div style="font-weight: 400; letter-spacing: normal; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">
<div style="font-family: "times new roman"; font-size: medium; font-style: normal; margin: 0px;">
<span style="color: #20124d; font-size: large;"><br /></span></div>
<div style="font-family: "times new roman"; font-style: normal; margin: 0px;">
<br />
<ul style="text-align: left;">
<li><span style="color: #20124d; font-size: large;">Link click will call the exportToCSV method. This function creates a CSV data required for our excel file. </span></li>
<li><span style="color: #20124d; font-size: large;">CSV created based on the controller method getContacts() which passes the contact wrapper.</span></li>
</ul>
</div>
<div style="font-family: "times new roman"; font-style: normal; margin: 0px;">
<span style="color: #20124d; font-size: large;"><br /></span></div>
<h3 style="margin: 0px; text-align: left;">
<span face="" style="color: #20124d; font-size: large;"><i>exportToExcelDemo.js</i></span></h3>
</div>
<pre style="background: rgb(240, 240, 240); border: 1px dashed rgb(204, 204, 204); font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="overflow-wrap: normal;"><span style="color: #20124d;"> import {
LightningElement,
track
} from "lwc";
import getContacts from "@salesforce/apex/ExportToExcelDemoController.getContacts";
const columns = [{
label: "Name",
fieldName: "contactName",
type: "text"
},
{
label: "Email",
fieldName: "contactEmail",
type: "text"
}
];
export default class ExportToExcelDemo extends LightningElement {
@track hrefdata;
@track contactList;
@track contactColumns = columns;
connectedCallback() {
this.getContacts();
}
getContacts() {
getContacts()
.then(result => {
this.contactList = result;
})
.catch(error => {
this.error = error;
console.log(this.error);
});
}
exportToCSV() {
let columnHeader = ["Name", "Email"]; // This array holds the Column headers to be displayd
let jsonKeys = ["contactName", "contactEmail"]; // This array holds the keys in the json data
var jsonRecordsData = this.contactList;
let csvIterativeData;
let csvSeperator
let newLineCharacter;
csvSeperator = ",";
newLineCharacter = "\n";
csvIterativeData = "";
csvIterativeData += columnHeader.join(csvSeperator);
csvIterativeData += newLineCharacter;
for (let i = 0; i < jsonRecordsData.length; i++) {
let counter = 0;
for (let iteratorObj in jsonKeys) {
let dataKey = jsonKeys[iteratorObj];
if (counter > 0) { csvIterativeData += csvSeperator; }
if ( jsonRecordsData[i][dataKey] !== null &&
jsonRecordsData[i][dataKey] !== undefined
) { csvIterativeData += '"' + jsonRecordsData[i][dataKey] + '"';
} else { csvIterativeData += '""';
}
counter++;
}
csvIterativeData += newLineCharacter;
}
console.log("csvIterativeData", csvIterativeData);
this.hrefdata = "data:text/csv;charset=utf-8," + encodeURI(csvIterativeData);
}
}
</span></code></pre>
<span style="color: #20124d;"><br /></span>
<span style="color: #20124d; font-size: large;">Finally, this simple controller method that returns you the contact wrapper containing the data.</span><br />
<span style="color: #20124d; font-size: large;"><br /></span>
<br />
<h3 style="text-align: left;">
<span face="" style="color: #20124d; font-size: large;"><span style="font-size: medium;"><i>ExportToExcelDemoController.cls</i></span> </span></h3>
<pre style="background: rgb(240, 240, 240); border: 1px dashed rgb(204, 204, 204); font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="overflow-wrap: normal;"><span style="color: #20124d;">public with sharing class ExportToExcelDemoController {
public class ContactWrapper{
@AuraEnabled
public string contactName;
@AuraEnabled
public string contactEmail;
public ContactWrapper(Contact contactObj){
this.contactName = contactObj.Name;
this.contactEmail = contactObj.Email;
}
}
@AuraEnabled
public static List<ContactWrapper> getContacts(){
List<ContactWrapper> contactWrapperList = new List<ContactWrapper>();
for(Contact cwObj : [select id, Name, Email from Contact limit 5]){
contactWrapperList.add(new ContactWrapper(cwObj));
}
return contactWrapperList;
}
}
</span></code></pre>
<span style="color: #20124d;"><br /></span></div>
<div>
<span style="color: #20124d;"><br /></span></div>
<div>
<span style="color: #20124d; font-size: large;">It's pretty easy, isn't it?</span><br />
<span style="color: #20124d;"><span style="font-size: large;"><br /></span>
<span style="font-size: large;">I hope you enjoyed the learning, please write me back the suggestions, comments or any issues. Let's meet in our next post with more learnings and fun. :)</span></span></div>
</div>
Amolhttp://www.blogger.com/profile/04561932834601726448noreply@blogger.com4tag:blogger.com,1999:blog-6457252088873371292.post-49054527834942862392019-08-20T16:37:00.002-04:002020-09-08T08:28:52.001-04:00Lightning Web Component - How to use the Lightning "Data Table" with "Input" elements<head>
<script data-ad-client="ca-pub-6231630339453617" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
</head>
<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: left;">
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">Hello Guys, hope you are doing well.</span><br />
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">We might come across the situation where we need to show input fields along with lightning data table. So here we are going to see an example of how to achieve that in Lightning Web Component.</span></div>
<div style="text-align: left;">
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">For simplicity here, I am taking an example of marking attendance for Students.</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEuhp2VTQc8_vvQNy9j1JVX0jPOszLuuThXrpRhfVPKDZcxfFnn2c_DeAYZiIcDPLW5UwiQxQVVl_TbzbYJWtggz9kHnJbcwsLyR49k5nIKawGCwf1VBp5ZdgEM18LOPxu3HINp1dUc6w2/s1600/chrome-capture.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="193" data-original-width="500" height="244" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEuhp2VTQc8_vvQNy9j1JVX0jPOszLuuThXrpRhfVPKDZcxfFnn2c_DeAYZiIcDPLW5UwiQxQVVl_TbzbYJWtggz9kHnJbcwsLyR49k5nIKawGCwf1VBp5ZdgEM18LOPxu3HINp1dUc6w2/s640/chrome-capture.gif" width="640" /></a></div>
<br />
<br />
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">So Lets start the implementation.</span><br />
<span style="font-family: "times" , "times new roman" , serif;"><br /></span>
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">First, consider adding one input field on your HTML page in LWC.</span><br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> <lightning-input type="date" onchange={datechangeevent} label="Select Date" value={selecteddate} required>
</lightning-input>
</code></pre>
<br />
<br />
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">Then add the lightning data table.</span><br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> <lightning-datatable data={students} columns={columns} key-field="Id" onrowselection={getSelectedName}>
</lightning-datatable>
</code></pre>
<br />
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">Add one button This button will be called to save the selected records in the data table along with the selected date in the date picker. <b><i>showConfirmation </i></b>action will just show the popup to confirm the action. Once the user hits the Yes on popup, <b><i>addAttendance </i></b>method will be called.</span><br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> <lightning-button label="Save" variant="brand" onclick={showConfirmation} class="slds-m-top_medium">
</lightning-button>
</code></pre>
<br />
<div>
<br /></div>
<div>
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">Here are the details of the js side</span><br />
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span>
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">This change event will capture the changed date in the date-picker into selecteddate variable.</span></div>
<div>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> @track selecteddate;
datechangeevent(event) {
this.selecteddate = event.target.value;
}
</code></pre>
</div>
<div>
<br /></div>
<div>
<span style="font-size: large;"><br /></span>
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">The following code will fetch the default data to be shown on the data table.</span></div>
<div>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> @track students;
getStudents(data) {
this.selecteddate = null;
getContacts({
opportunityId: this.opportunityId
})
.then(result => {
this.students = result;
})
.catch(error => {
this.error = error;
});
}
</code></pre>
</div>
<div>
<span style="font-size: large;"><br /></span>
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">Following code will be used to call the controller method and pass on the selected date and records in the data table.</span><br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> addAttendance() {
this.popup = false;
fireEvent(this.pageRef, "loadingAction", true);
console.log("this.selecteddate==>" + this.selecteddate);
console.log("this.selectedContacts==>" + this.selectedContacts);
createNewAttendanceDetails({
attendanceDate: this.selecteddate,
opportunityId: this.opportunityId,
contactList: this.selectedContacts
})
.then(result => {
console.log(result);
this.dispatchEvent(
new ShowToastEvent({
title: "Success",
message: "Attendance Created Successfully.",
variant: "success"
})
);
})
.catch(error => {
this.error = error;
});
}
</code></pre>
<br />
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">Following Apex controller method will be accepting the parameters sent by java-script lwc.</span><br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> public static Boolean createNewAttendanceDetails(Date attendanceDate, String opportunityId, List<String> contactList){
//We have all the data available in this function, we can take an action based on our requirements
return true;
}
</code></pre>
</div>
<br />
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="font-size: large;"><br /></span></span>
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">So that's it, we are ready with our sample use case.</span><br />
<span style="font-family: "times" , "times new roman" , serif;"><span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span></span>
<span style="font-family: "times" , "times new roman" , serif;"><span style="font-family: "times" , "times new roman" , serif; font-size: large;">I hope you liked the post and it helped. Please let me know your suggestions and feedback. </span></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">Thank you so much for visiting.</span></div>
<div style="background-color: #272822; color: #f8f8f2; font-family: Consolas, "Courier New", monospace; font-size: 14px; line-height: 19px; white-space: pre;">
<div>
</div>
</div>
</div>
Amolhttp://www.blogger.com/profile/04561932834601726448noreply@blogger.com1tag:blogger.com,1999:blog-6457252088873371292.post-58225313284457311242019-06-23T09:12:00.001-04:002020-09-08T08:29:03.241-04:00LWC : Create/Edit Form with Custom Lookup and Navigation<head>
<script data-ad-client="ca-pub-6231630339453617" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
</head>
<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: left;">
<span style="font-size: large;">Hello Guys, </span><br />
<span style="font-size: large;"><br /></span>
<span style="font-size: large;">Hope you are doing well. In this post we are going to see the very basic and common requirement of Create a record with a form with input fields, custom lookup, and navigation with the help of Lightning Web components.</span></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<span style="font-size: large;">So Let's start.</span></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<span style="font-size: large;">In the end, our screen will look somewhat like below.</span></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiriJcw_RV-F3yflLCpYVdWZKjt7wFzLbs_C1FLFrDzNkPb8uOxnsvXorZrS6IjYD_nF3rs9Suxkh99Fx3Hup8Wj0KxYZTy_tsw7tA7jIC8GCV2bvxMt-mT_qVkPux5dQzVjM37rx4Z9AtU/s1600/chrome-capture.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="436" data-original-width="1230" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiriJcw_RV-F3yflLCpYVdWZKjt7wFzLbs_C1FLFrDzNkPb8uOxnsvXorZrS6IjYD_nF3rs9Suxkh99Fx3Hup8Wj0KxYZTy_tsw7tA7jIC8GCV2bvxMt-mT_qVkPux5dQzVjM37rx4Z9AtU/s640/chrome-capture.gif" width="640" /></a></div>
<br />
<span style="font-size: large;">Create a Lightning web component with name </span><span style="font-size: large;"><i>createContactForm</i>.</span><br />
<span style="font-size: large;">In this example, we are going to create a contact record with a custom loo</span><span style="font-size: large;">kup of Account. This component will have the input elements to create a contact record. Here we are going to use standard <i>lightning-record-edit-form</i>. We just need to pass a few parameters such as Object name, fields, etc.</span><br />
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<span style="font-size: large;">We can define what actions need to be performed before load form load(<i>onload</i>) or before we submit a form(<i>onsubmit</i>) or after the successful execution of a form(<i>onsuccess</i>)</span></div>
<div style="text-align: left;">
<span style="font-size: large;">Implementation of these methods is explained in <i>createContactForm.js</i></span></div>
<div>
<i><br /></i></div>
<span style="font-size: large;"><i>createContactForm.html</i></span><br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> <template>
<div class="slds-m-around_large">
<div if:false={isLoaded} class="slds-is-relative">
<lightning-spinner alternative-text="Loading...">
</lightning-spinner>
</div>
</div>
<lightning-card title="Contact Information">
<template if:true={accountRecord}>
<h1>Selected Account : <b>{accountRecord.Name}</b></h1>
</template>
<lightning-record-edit-form id="contactForm" object-api-name="Contact" layout-type="compact"
horizontal-align="stretch" title="Contact Information" onsuccess={handleContactSuccess}
onsubmit={handleOnContactSubmit} onload={handleOnLoad}>
<lightning-messages>
</lightning-messages>
<lightning-layout horizontal-align="stretch">
<lightning-layout-item flexibility="auto" >
<lightning-input-field field-name='FirstName'></lightning-input-field>
</lightning-layout-item>
<lightning-layout-item flexibility="auto" >
<lightning-input-field field-name='LastName'></lightning-input-field>
</lightning-layout-item>
</lightning-layout>
<lightning-layout horizontal-align="stretch">
<lightning-layout-item flexibility="auto" >
<lightning-input-field field-name='Title'></lightning-input-field>
</lightning-layout-item>
<lightning-layout-item flexibility="auto" >
<lightning-input-field field-name='Department'></lightning-input-field>
</lightning-layout-item>
</lightning-layout>
<lightning-layout horizontal-align="stretch">
<lightning-layout-item flexibility="auto" >
<lightning-input-field field-name='Email' required></lightning-input-field>
</lightning-layout-item>
<lightning-layout-item flexibility="auto" >
<lightning-input-field field-name='Alternate_Email__c'></lightning-input-field>
</lightning-layout-item>
</lightning-layout>
<lightning-layout horizontal-align="stretch">
<lightning-layout-item flexibility="auto" >
<lightning-input-field field-name='Phone'></lightning-input-field>
</lightning-layout-item>
<lightning-layout-item flexibility="auto" >
<lightning-input-field field-name='Extension__c'></lightning-input-field>
</lightning-layout-item>
</lightning-layout>
<lightning-layout horizontal-align="stretch">
<lightning-layout-item flexibility="auto" >
<lightning-input-field field-name='OtherPhone'></lightning-input-field>
</lightning-layout-item>
<lightning-layout-item flexibility="auto" >
</lightning-layout-item>
</lightning-layout>
<lightning-layout horizontal-align="stretch">
<lightning-layout-item flexibility="auto" >
</lightning-layout-item>
<lightning-layout-item flexibility="auto" >
</lightning-layout-item>
</lightning-layout>
<lightning-layout horizontal-align="stretch">
<lightning-layout-item flexibility="auto" >
<lightning-button variant="brand" type="submit" name="save" label="Save"
style="padding-left: 0.75rem;">
</lightning-button>
<lightning-button label="Cancel" variant="brand" onclick={cancelContactScreen}
style="padding-left: 0.75rem;">
</lightning-button>
</lightning-layout-item>
</lightning-layout>
</lightning-record-edit-form>
</lightning-card>
</template>
</code></pre>
<br />
<span style="font-size: large;">This is the JS file/ class handles the actions needed by createContactForm.html. These actions include the onload, onsubmit, onsuccess.</span><br />
<ul style="text-align: left;">
<li><span style="font-size: large;">We are showing the loading icon on the screen until the form is loaded(<i>handleOnLoad</i>)</span></li>
<li><span style="font-size: large;">Before we submit a form, we need to assign Account record id(explained later) to a contact record. So we are doing this in <i>handleOnContactSubmit</i> function. If you observe we have prevented the event until we assign all the values and perform our validations. Once we assign the related values, we are going to submit the form</span></li>
<li><span style="font-size: large;">Once the form is submitted and server-side action takes place, <i>handleContactSuccess</i> gets called. Here we are showing the success message and navigating a screen to a create contact record.</span></li>
<li><span style="font-size: large;">We have a Cancel button which navigates us to the home screen.</span></li>
<li><span style="font-size: large;">If you observe we are throwing events for success or cancel action, so that recipient of the component will take further actions according to their needs.</span></li>
</ul>
<br />
<span style="font-size: large;"><i>createContactForm.js</i></span><br />
<pre style="background: rgb(240, 240, 240); border: 1px dashed rgb(204, 204, 204); font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 646.469px;"><code style="overflow-wrap: normal;">
import { LightningElement, api, track } from "lwc";
import { ShowToastEvent } from "lightning/platformShowToastEvent";
export default class CreateContactForm extends LightningElement {
@api accountRecord;
@api eventRecordId;
@track isLoaded = false;
handleOnLoad() {
this.isLoaded = true;
}
handleContactSuccess(event) {
console.log(event.detail.fields);
this.dispatchEvent(
new ShowToastEvent({
title: "Success",
message: "Contact created Successfully.",
variant: "success"
})
);
this.dispatchEvent(
new CustomEvent("contactsuccess", {
detail: event.detail.id,
bubbles: true
})
);
}
handleOnContactSubmit(event) {
event.preventDefault(); // stop the form from submitting
const fields = event.detail.fields;
if (this.accountRecord === undefined || this.accountRecord === null) {
this.dispatchEvent(
new ShowToastEvent({
title: "Error",
message: "Please select an Account",
variant: "error"
})
);
return;
}
fields.AccountId = this.accountRecord.Id;
this.template.querySelector("lightning-record-edit-form").submit(fields);
}
cancelContactScreen() {
this.dispatchEvent(
new CustomEvent("contactcancel", {
bubbles: true
})
);
}
}
</code></pre>
<br />
<span style="font-size: large;">This is a wrapper component which uses the component we created earlier <i>createContactForm.js.</i> Also, we are going to use the custom Account lookup component, which we can be referred to in <a href="https://salesforcelightningwebcomponents.blogspot.com/2019/04/custom-lookupautocomplete-with-event.html" target="_blank">this post.</a> You can customize this component/queries according to your need.</span><br />
<div>
<i style="font-size: x-large;"><br /></i></div>
<span style="font-size: large;">We are taking the Account record from the custom lookup component and passing it on to contact form component.</span><br />
<span style="font-size: large;"><br /></span>
<span style="font-size: large;"><i>contactFormWithCustomLookup.html</i></span><br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> <template>
<lightning-card title={title} icon-name="standard:record">
<div class="slds-m-around_medium">
<lightning-layout horizontal-align="stretch">
<lightning-layout-item flexibility="auto" style="padding-left: 0.75rem;">
<c-lookup-search label="Custom Lookup - Account" selectedsobject="Account"
onlookupselect={handlelookupselectaccount}></c-lookup-search>
</lightning-layout-item>
<lightning-layout-item flexibility="auto" style="padding-left: 0.75rem;margin-top: 37px;">
Please start typing Account name in a box.
</lightning-layout-item>
</lightning-layout>
<c-create-contact-form oncontactsuccess={contactCreateSuccess} account-record={selectedAccountRecord}
event-record-id={eventRecordId} oncontactcancel={contactCancel}></c-create-contact-form>
</div>
</lightning-card>
</template>
</code></pre>
<br />
<br />
<span style="font-size: large;">This JS method handles the success/cancel action event thrown by contact form component.</span><br />
<span style="font-size: large;">On success, we are navigating to contact record and on cancel to the home page.</span><br />
<span style="font-size: large;"><br /></span>
<span style="font-size: large;"><i>contactFormWithCustomLookup.js</i></span><br />
<pre style="background: rgb(240, 240, 240); border: 1px dashed rgb(204, 204, 204); font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 646.469px;"><code style="overflow-wrap: normal;">
import {
LightningElement,
track,
api
} from "lwc";
import {
NavigationMixin
} from "lightning/navigation";
export default class ContactFormWithCustomLookup extends NavigationMixin(
LightningElement
) {
@api title = "Create Contact";
@track selectedAccountRecord;
@track isLoaded = false;
contactCreateSuccess(event) {
this[NavigationMixin.Navigate]({
type: "standard__recordPage",
attributes: {
recordId: event.detail,
objectApiName: "Contact", // objectApiName is optional
actionName: "view"
}
});
}
contactCancel() {
this[NavigationMixin.Navigate]({
type: "standard__objectPage",
attributes: {
objectApiName: "Account",
actionName: "home"
}
});
}
handlelookupselectaccount(event) {
this.selectedAccountRecord = event.detail;
}
}
</code></pre>
<br />
<span style="font-size: large;">Just create a lightning page/app and include this component in it, you are ready with your implementation.</span><br />
<br />
<span style="font-size: large;">So that's all, wasn't is so simple????</span><br />
<span style="font-size: large;"><br /></span>
<span style="font-size: large;">I hope you enjoyed the learning, please write me back the suggestions, comments or any issues. Let's meet in our next post with more learnings and fun. :)</span><br />
<span style="font-size: large;"><br /></span>
<span style="font-size: large;">THANK YOU!</span></div>
Amolhttp://www.blogger.com/profile/04561932834601726448noreply@blogger.com4tag:blogger.com,1999:blog-6457252088873371292.post-21207840406417790392019-06-09T18:50:00.005-04:002020-09-08T08:29:16.778-04:00How to get URL parameters in Lightning Web Components??<head>
<script data-ad-client="ca-pub-6231630339453617" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
</head>
<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">Hello Guys, h</span><span style="font-family: "times" , "times new roman" , serif; font-size: large;">ope you are doing great!</span><br />
<div>
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">Did you have a requirement to get the URL parameters in Lightning web component and use them further??</span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">Here is the simple answer. As LWC is purely based on Javascript, we can utilize the Javascript functions to do this activity. I was working with communities and wanted to pass on some URL parameters, here is the implementation.</span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">This was my URL.</span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><Community URL>?eventid=00UJ000000AzjeuMAB</span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span></div>
<div>
<br /></div>
<pre style="background: rgb(240, 240, 240); border: 1px dashed rgb(204, 204, 204); font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 646.469px;"><code style="overflow-wrap: normal;">
var eventId = ((new URL(window.location.href)).searchParams.get("eventid"));
</code></pre>
<h2 style="text-align: left;">
<span style="font-weight: normal;"><span style="font-size: large;">The above line will give me the Event Id retrieved from URL. Sooo simple.</span></span></h2>
<div>
<span style="font-family: times, "times new roman", serif;"><span style="font-size: large;">I hope you liked the post and it helped. Let me know your suggestions and feedback. </span></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">Thank you so much for visiting.</span></div>
</div>
Amolhttp://www.blogger.com/profile/04561932834601726448noreply@blogger.com0tag:blogger.com,1999:blog-6457252088873371292.post-40116098346078245752019-04-18T15:42:00.007-04:002020-09-08T08:29:29.127-04:00Custom Lookup/Autocomplete with Event Bubbling and Wire Method to Function<head>
<script data-ad-client="ca-pub-6231630339453617" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
</head>
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">Hello Guys, h</span><span style="font-family: "times" , "times new roman" , serif; font-size: large;">ope you are doing great!</span><br />
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span><span style="font-family: "times" , "times new roman" , serif; font-size: large;">This post explains the basic use case of custom Lookup/Autocomplete with Lightning web components. This component uses the Event bubbling and with Wire method to function.</span><br />
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span><span style="font-family: "times" , "times new roman" , serif; font-size: large;">Here is the sample, how it will look. This generic lookup can be used with any object. Just pass on the SObject name and some parameters, it will be available to use. </span><br />
<span style="font-size: large;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiS6zh7C1z8wwZ1_kux7coA6hTUAEqp6qGO0jB42JghZaxl3MhPnEiNrTSusODrH19r9lpSX0VHEzYD1i7hzJsa1icCMydY4oNscqlRHfNjNZFSZ1psjNwXCK-mpxILUrVhWNzPC1Nip8Iq/s1600/chrome-capture+%25284%2529.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="317" data-original-width="455" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiS6zh7C1z8wwZ1_kux7coA6hTUAEqp6qGO0jB42JghZaxl3MhPnEiNrTSusODrH19r9lpSX0VHEzYD1i7hzJsa1icCMydY4oNscqlRHfNjNZFSZ1psjNwXCK-mpxILUrVhWNzPC1Nip8Iq/s1600/chrome-capture+%25284%2529.gif" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><i>Example:</i></span><br />
<pre style="background: rgb(240, 240, 240); border: 1px dashed rgb(204, 204, 204); font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; width: 646.469px;"><code style="overflow-wrap: normal;"> <c-lookup-search label="Custom Lookup - Account" selectedsobject="Account"
recordlimit="10" onlookupselect={handlelookupselectaccount}></c-lookup-search>
</code></pre>
<div>
<br /></div>
<div style="text-align: left;">
<code style="overflow-wrap: normal;"><span style="font-family: "times" , "times new roman" , serif; font-size: large;">Lets see the details component wise.</span></code></div>
<div style="text-align: left;">
<code style="overflow-wrap: normal;"><span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span></code></div>
<div style="text-align: left;">
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">The following component will hold a lookup option element. Click on the option will fire a bubbling event. This event will be caught by parent and grandparent components.</span></div>
<div style="text-align: left;">
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span><span style="font-family: "times" , "times new roman" , serif; font-size: large;">The event will pass the selected record in the details.</span></div>
<div style="text-align: left;">
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyfh-Bi_atVErw-UQXsnDbfAh0_6-AqgiCNrJx3D1I72k7VJ6IFNwVPUeyQkWP7MGCewb790vzRwCuTDyD8Dj24lYAF1UjNhWHO94HMqh7W8U1r5JHU6uqRMDe7xFnpwlfnEaYAeiPHIJn/s1600/111.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="390" data-original-width="1293" height="193" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyfh-Bi_atVErw-UQXsnDbfAh0_6-AqgiCNrJx3D1I72k7VJ6IFNwVPUeyQkWP7MGCewb790vzRwCuTDyD8Dj24lYAF1UjNhWHO94HMqh7W8U1r5JHU6uqRMDe7xFnpwlfnEaYAeiPHIJn/s640/111.PNG" width="640" /></a></div>
<br /></div>
<div style="text-align: left;">
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><i>lookupItem.html</i></span></div>
<br />
<pre style="background: rgb(240, 240, 240); border: 1px dashed rgb(204, 204, 204); font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; width: 646.469px;"><code style="overflow-wrap: normal;"> <template>
<template if:true={record}>
<lightning-layout vertical-align="center">
<div style="cursor:pointer" key={record.Id} data-contact-id={record.Id} onclick={handleSelect}>
<lightning-layout-item padding="around-small">
{record.Name}
</lightning-layout-item>
</div>
</lightning-layout>
</template>
<template if:false={record}>
<p>No contact data available.</p>
</template>
</template>
</code></pre>
</div>
<br />
<br />
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><i>lookupItem.js</i></span><br />
<br />
<pre style="background: rgb(240, 240, 240); border: 1px dashed rgb(204, 204, 204); font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; width: 646.469px;"><code style="overflow-wrap: normal;"> import { LightningElement, api } from 'lwc';
export default class LookupItem extends LightningElement {
@api record;
// This method handles the selection of lookup value
handleSelect(event) {
// Event will be triggerred and bubbled to parent and grandparent.
// Check the parameters passed.
const selectEvent = new CustomEvent('lookupselect', {
detail: this.record,
bubbles: true,
composed: true
});
// Fire the custom event
this.dispatchEvent(selectEvent);
}
}
</code></pre>
</div>
<br />
<br />
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">The following component will hold an input text to search the lookup. It will do the server side Apex call to get the records. Apex call is generic so it can accommodate any SObject. Records will be then iterated over lookup-item component which we created in the earlier step.</span><br />
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span><span style="font-family: "times" , "times new roman" , serif; font-size: large;">Note: Currently this component searches the text on Name field of the SObject. But we can change/make it generic.</span><br />
<br />
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><i>lookupSearch.html</i></span><br />
<br />
<pre style="background: rgb(240, 240, 240); border: 1px dashed rgb(204, 204, 204); font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; width: 646.469px;"><code style="overflow-wrap: normal;"> <template>
<div class="slds-m-around_medium selectoptions">
<lightning-input class="slds-m-bottom_small" label="Search" value={selectedName} minlength="1" isloading=true onkeyup={handleKeyChange}>
</lightning-input>
<template if:true={showoptions}>
<template if:true={records}>
<template for:each={records} for:item="record">
<template if:true={record}>
<c-lookup-item key={record.Id} record={record} onlookupselect={handlelookupselect}>
</c-lookup-item>
</template>
</template>
</template>
<template if:true={noRecordsFlag}>
<p>'{searchString}' in {label}s</p>
</template>
</template>
</div>
</template>
</code></pre>
<br />
<br />
<i><span style="font-family: "times" , "times new roman" , serif; font-size: large;">lookupSearch.js</span></i><br />
<i style="font-family: Times, "Times New Roman", serif; font-size: x-large;"><br /></i>
<br />
<pre style="background: rgb(240, 240, 240); border: 1px dashed rgb(204, 204, 204); font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; width: 646.469px;"><code style="overflow-wrap: normal;"> import { LightningElement, track, api, wire} from 'lwc';
import getLookupSerachRecords from '@salesforce/apex/ManageRecordsController.getLookupSerachRecords';
export default class LookupSearch extends LightningElement {
// Tracked properties
@track records;
@track noRecordsFlag = false;
@track showoptions = true;
@track searchString = '';
@track selectedName;
// API properties
@api selectedsobject;
@api recordlimit;
@api label;
// Wire method to function, which accepts the Search String, Dynamic SObject, Record Limit, Search Field
@wire(getLookupSerachRecords, { searchString: '$searchString' , selectedSObject : '$selectedsobject', recordLimit : '$recordlimit'})
wiredContacts({ error, data }) {
this.noRecordsFlag = 0;
if (data) {
this.records = data;
this.error = undefined;
this.noRecordsFlag = this.records.length === 0 ? true : false;
} else if (error) {
this.error = error;
this.records = undefined;
}
}
// handle event called lookupselect
handlelookupselect(event){
this.selectedName = event.detail.Name;
this.showoptions = false;
}
// key change on the text field
handleKeyChange(event) {
this.showoptions = true;
this.searchString = event.target.value;
}
}
</code></pre>
<br />
<br />
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><i>lookupSearch.css</i></span><br />
<br />
<pre style="background: rgb(240, 240, 240); border: 1px dashed rgb(204, 204, 204); font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; width: 646.469px;"><code style="overflow-wrap: normal;"> lightning-input,
c-lookup-item {
position: relative;
border: solid 1px #ecebea;
border-radius: 4px;
display: block;
padding: 2px;
}
c-lookup-item {
margin: 1px 0;
}
lightning-input:before,
c-lookup-item:before,
selectoptions:before {
color: #dddbda;
position: absolute;
top: -9px;
left: 4px;
background-color: #ffffff;
padding: 0 4px;
}
selectoptions {
border: solid 1px #ecebea;
}
</code></pre>
<br />
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">We are done with our web component implementation, now its time to use it.</span><br />
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span><span style="font-family: "times" , "times new roman" , serif; font-size: large;">You can see that we have included the </span><span style="background-color: #f0f0f0;"><span style="font-family: "times" , "times new roman" , serif; font-size: large;">lookup-search</span></span><span style="font-family: "times" , "times new roman" , serif; font-size: large;"> component with the parameters. Parameters are pretty easy and straight forward. </span><br />
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span><span style="font-family: "times" , "times new roman" , serif; font-size: large;"><i>label </i>: Label to be shown on the UI</span><br />
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><i>selectedsobject </i>: SObject from which data to be fetched.</span><br />
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><i>recordlimit </i>: Number of records to be fetched.</span><br />
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span>
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">Please check .js file, handlers will give you the selected record. The selected lookup record can be used for your further operations.</span><br />
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWXmQ0QNf9PE126LzqzJ888GP29gR8Zn2EatJgNL1qhLrbDqt_YexP6cHsppS9d_1QzvE189sV3u2upSsvmZYLm9s2z_q9OF6dB7nRbHC0TNYegyg-d2sZM4czgW9vzk4B4WC01Yrtyqtp/s1600/222.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="172" data-original-width="1340" height="82" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWXmQ0QNf9PE126LzqzJ888GP29gR8Zn2EatJgNL1qhLrbDqt_YexP6cHsppS9d_1QzvE189sV3u2upSsvmZYLm9s2z_q9OF6dB7nRbHC0TNYegyg-d2sZM4czgW9vzk4B4WC01Yrtyqtp/s640/222.PNG" width="640" /></a></div>
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span><i><span style="font-family: "times" , "times new roman" , serif; font-size: large;">lookupWrapperParent.html</span></i><br />
<i><span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span></i>
<br />
<pre style="background: rgb(240, 240, 240); border: 1px dashed rgb(204, 204, 204); font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; width: 646.469px;"><code style="overflow-wrap: normal;"> <template>
<lightning-card title="Custom Lookup - Account" icon-name="custom:custom57">
<c-lookup-search label="Custom Lookup - Account" selectedsobject="Account"
recordlimit="10"
onlookupselect={handlelookupselectaccount}></c-lookup-search>
<tempate if:true={selectedAccountRecord}>
<p>SELECTED RECORD ID : {selectedAccountRecord.Id}</p>
<p>SELECTED RECORD VALUE : {selectedAccountRecord.Name}</p>
</tempate>
</lightning-card>
<lightning-card title="Custom Lookup - Contact" icon-name="custom:custom57">
<c-lookup-search label="Contact" selectedsobject="Contact" recordlimit="10"
onlookupselect={handlelookupselectcontact}>
</c-lookup-search>
<tempate if:true={selectedContactRecord}>
<p>SELECTED RECORD ID : {selectedContactRecord.Id}</p>
<p>SELECTED RECORD VALUE : {selectedContactRecord.Name}</p>
</tempate>
</lightning-card>
</template>
</code></pre>
<br />
<br />
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><i>lookupWrapperParent.js</i></span><br />
<br />
<pre style="background: rgb(240, 240, 240); border: 1px dashed rgb(204, 204, 204); font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; width: 646.469px;"><code style="overflow-wrap: normal;"> import { LightningElement, track } from 'lwc';
export default class LookupWrapperParent extends LightningElement {
@track selectedAccountRecord;
@track selectedContactRecord;
// Event bubbles to grandparent and being handled here - Account
handlelookupselectaccount(event) {
this.selectedAccountRecord = event.detail;
}
// Event bubbles to grandparent and being handled here - Contact
handlelookupselectcontact(event) {
this.selectedContactRecord = event.detail;
}
} </code></pre>
<br />
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span>
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">Apex class </span><br />
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><i><br /></i></span>
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><i>ManageRecordsController.cls</i></span><br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> public with sharing class ManageRecordsController {
@AuraEnabled(cacheable=true)
public static List<Account> getLookupSerachRecords(String searchString, String selectedSObject, Integer recordLimit) {
if(searchString != null && searchString != ''){
String query = 'select Name, Id from ' + selectedSObject;
query += ' where Name like \'%'+ searchString +'%\' ';
query+= ' limit ' + recordLimit;
return Database.query(query);
}
return null;
}
}
</code></pre>
<span style="font-family: "times" , "times new roman" , serif; font-size: large;">It was a simple example which shows the custom lookup or Autocomplete with Event Bubbling and Wire Method to Function.</span><br />
<span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span><span style="font-family: "times" , "times new roman" , serif; font-size: large;"></span>
<br />
<div style="text-align: left;">
<span style="font-weight: normal;"><span style="font-family: "times" , "times new roman" , serif; font-size: large;">I hope you enjoyed the learning, please write me back the suggestions, comments or any issues. Let's meet in our next post with more learnings and fun. :)</span></span></div>
<div style="text-align: left;">
<span style="font-weight: normal;"><span style="font-family: "times" , "times new roman" , serif; font-size: large;"><br /></span></span><span style="font-weight: normal;"><span style="font-family: "times" , "times new roman" , serif; font-size: large;">THANK YOU!</span></span></div>
</div>
Amolhttp://www.blogger.com/profile/04561932834601726448noreply@blogger.com3tag:blogger.com,1999:blog-6457252088873371292.post-68506118112345584492019-04-10T13:29:00.005-04:002020-09-08T08:29:40.620-04:00renderedCallback() function/action is getting called multiple times : How to handle?<head>
<script data-ad-client="ca-pub-6231630339453617" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
</head>
<div dir="ltr" style="text-align: left;" trbidi="on">
<h4 style="text-align: left;">
<div class="MsoNormal" style="line-height: normal;">
<span style="color: #444444;"><br /><span style="font-weight: normal;">Hello Guys,</span></span><br />
<span style="color: #444444; font-weight: normal;"><br /></span> <span style="color: #444444; font-weight: normal;">If you have worked on Lightning Web Components and used the </span><span style="color: #444444;">renderedCallback</span><span style="color: #444444; font-weight: normal;">() method, you might have seen that it gets called multiple times with one action/operation.<br /><br />Before going into the issue, first, let's try to understand what exactly</span><span style="color: #444444;">renderedCallback</span><span style="color: #444444; font-weight: normal;">() does. This hook flows from child to parent. When a component rerenders, all the expressions used in the template are reevaluated.</span></div>
<div>
<span style="color: #444444; font-weight: normal;"><br />Means all the template variables will be refreshed to get the latest value. Due to mutations, a component is generally rendered multiple times during its lifespan in an application. If you want this action to be called only once and not many times, ummmmm???<br /><br />Soooo how to handle this?<br /><br />Do you remember the Apex Trigger and recursion handling? We use the static variable to stop the recursion. <br /><br />Similar to that, we are going to do it here.</span></div>
<div class="MsoNormal" style="line-height: normal;">
<span style="color: #444444; font-weight: normal;"><br />1) Create one private property in your class. In our example its </span><span style="color: #444444;">isRenderCallbackActionExecuted</span><br />
<div class="MsoNormal" style="line-height: normal; mso-margin-bottom-alt: auto; mso-margin-top-alt: auto; mso-outline-level: 4;">
<br /></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in;">
<br /></div>
<div class="MsoNormal" style="background: #1E1E1E; line-height: 14.25pt; margin-bottom: .0001pt; margin-bottom: 0in;">
<span style="font-weight: normal;"><span style="color: #569cd6; font-family: "consolas"; font-size: 14.0pt;">import</span><span style="color: #d4d4d4; font-family: "consolas"; font-size: 14.0pt;"> { LightningElement, track, api } </span><span style="color: #569cd6; font-family: "consolas"; font-size: 14.0pt;">from</span><span style="color: #d4d4d4; font-family: "consolas"; font-size: 14.0pt;"> </span><span style="color: #ce9178; font-family: "consolas"; font-size: 14.0pt;">'lwc'</span><span style="color: #d4d4d4; font-family: "consolas"; font-size: 14.0pt;">;<o:p></o:p></span></span></div>
<div class="MsoNormal" style="background: #1E1E1E; line-height: 14.25pt; margin-bottom: .0001pt; margin-bottom: 0in;">
<span style="font-weight: normal;"><span style="color: #569cd6; font-family: "consolas"; font-size: 14.0pt;">export</span><span style="color: #d4d4d4; font-family: "consolas"; font-size: 14.0pt;"> </span><span style="color: #569cd6; font-family: "consolas"; font-size: 14.0pt;">default</span><span style="color: #d4d4d4; font-family: "consolas"; font-size: 14.0pt;"> </span><span style="color: #569cd6; font-family: "consolas"; font-size: 14.0pt;">class</span><span style="color: #d4d4d4; font-family: "consolas"; font-size: 14.0pt;"> RenderCallBackExample </span><span style="color: #569cd6; font-family: "consolas"; font-size: 14.0pt;">extends</span><span style="color: #d4d4d4; font-family: "consolas"; font-size: 14.0pt;"> LightningElement {<o:p></o:p></span></span></div>
<div class="MsoNormal" style="background: #1E1E1E; line-height: 14.25pt; margin-bottom: .0001pt; margin-bottom: 0in;">
<br /></div>
<div class="MsoNormal" style="background: #1E1E1E; line-height: 14.25pt; margin-bottom: .0001pt; margin-bottom: 0in;">
<span style="font-weight: normal;"><span style="color: #d4d4d4; font-family: "consolas"; font-size: 14.0pt;">isRenderCallbackActionExecuted = </span><span style="color: #569cd6; font-family: "consolas"; font-size: 14.0pt;">false</span><span style="color: #d4d4d4; font-family: "consolas"; font-size: 14.0pt;">;<o:p></o:p></span></span></div>
<div class="MsoNormal" style="background: #1E1E1E; line-height: 14.25pt; margin-bottom: .0001pt; margin-bottom: 0in;">
<br /></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in;">
<br /></div>
<span style="color: #444444; font-weight: normal;">2) In your </span><span style="color: #444444;">renderedCallback </span><span style="color: #444444; font-weight: normal;">method add the following lines. What will these couple of lines do?</span><br />
<span style="color: #444444;"><span style="font-weight: normal;">It will check if the action has been already executed, by checking if the flag is set. If it's true it will skip the execution and our function will be called only once.</span></span><br />
<br />
<div class="MsoNormal" style="background: #1E1E1E; line-height: 14.25pt; margin-bottom: .0001pt; margin-bottom: 0in;">
<span style="color: #d4d4d4; font-family: "consolas"; font-size: 14pt; font-weight: normal;">renderedCallback() {<o:p></o:p></span></div>
<div class="MsoNormal" style="background: #1E1E1E; line-height: 14.25pt; margin-bottom: .0001pt; margin-bottom: 0in;">
<span style="font-weight: normal;"><span style="color: #d4d4d4; font-family: "consolas"; font-size: 14.0pt;"> </span><span style="color: #569cd6; font-family: "consolas"; font-size: 14.0pt;">if</span><span style="color: #d4d4d4; font-family: "consolas"; font-size: 14.0pt;"> (</span><span style="color: #569cd6; font-family: "consolas"; font-size: 14.0pt;">this</span><span style="color: #d4d4d4; font-family: "consolas"; font-size: 14.0pt;">.isRenderCallbackActionExecuted)) {<o:p></o:p></span></span></div>
<div class="MsoNormal" style="background: #1E1E1E; line-height: 14.25pt; margin-bottom: .0001pt; margin-bottom: 0in;">
<span style="font-weight: normal;"><span style="color: #d4d4d4; font-family: "consolas"; font-size: 14.0pt;"> </span><span style="color: #569cd6; font-family: "consolas"; font-size: 14.0pt;">return</span><span style="color: #d4d4d4; font-family: "consolas"; font-size: 14.0pt;">;<o:p></o:p></span></span></div>
<div class="MsoNormal" style="background: #1E1E1E; line-height: 14.25pt; margin-bottom: .0001pt; margin-bottom: 0in;">
<span style="color: #d4d4d4; font-family: "consolas"; font-size: 14pt; font-weight: normal;"> }<o:p></o:p></span></div>
<div class="MsoNormal" style="background: #1E1E1E; line-height: 14.25pt; margin-bottom: .0001pt; margin-bottom: 0in;">
<br /></div>
<div class="MsoNormal" style="background: #1E1E1E; line-height: 14.25pt; margin-bottom: .0001pt; margin-bottom: 0in;">
<span style="font-weight: normal;"><span style="color: #569cd6; font-family: "consolas"; font-size: 14.0pt;"> this</span><span style="color: #d4d4d4; font-family: "consolas"; font-size: 14.0pt;">.isRenderCallbackActionExecuted = </span><span style="color: #569cd6; font-family: "consolas"; font-size: 14.0pt;">true</span><span style="color: #d4d4d4; font-family: "consolas"; font-size: 14.0pt;">;<o:p></o:p></span></span></div>
<div class="MsoNormal" style="background: #1E1E1E; line-height: 14.25pt; margin-bottom: .0001pt; margin-bottom: 0in;">
<span style="color: #d4d4d4; font-family: "consolas"; font-size: 14pt; font-weight: normal;"> // Method action implementation.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: #1E1E1E; line-height: 14.25pt; margin-bottom: .0001pt; margin-bottom: 0in;">
<span style="color: #d4d4d4; font-family: "consolas"; font-size: 14pt; font-weight: normal;">}<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in;">
<br /></div>
<span style="color: #444444; font-weight: normal;">Now, you might ask, this is the solution for executing it only once, what if I want this to be called once, on a particular action such as button click or anything. It's simple. Just reset the isRenderCallbackActionExecuted flag to false again. So next time method will execute once again. </span></div>
<div class="MsoNormal" style="line-height: normal;">
<span style="color: #444444; font-weight: normal;"><br /></span> <span style="color: #444444; font-weight: normal;">Example: Following code is the snippet for Search box text change.</span><br />
<span style="color: #444444; font-weight: normal;"><br /></span>
<br />
<div class="MsoNormal" style="background: #1E1E1E; line-height: 14.25pt; margin-bottom: .0001pt; margin-bottom: 0in;">
<span style="color: #d4d4d4; font-family: "consolas"; font-size: 14pt; font-weight: normal;">handleKeyChange(event) {<o:p></o:p></span></div>
<div class="MsoNormal" style="background: #1E1E1E; line-height: 14.25pt; margin-bottom: .0001pt; margin-bottom: 0in;">
<br /></div>
<div class="MsoNormal" style="background: #1E1E1E; line-height: 14.25pt; margin-bottom: .0001pt; margin-bottom: 0in;">
<span style="font-weight: normal;"><span style="color: #d4d4d4; font-family: "consolas"; font-size: 14.0pt;"> </span><span style="color: #569cd6; font-family: "consolas"; font-size: 14.0pt;">if</span><span style="color: #d4d4d4; font-family: "consolas"; font-size: 14.0pt;"> (</span><span style="color: #569cd6; font-family: "consolas"; font-size: 14.0pt;">this</span><span style="color: #d4d4d4; font-family: "consolas"; font-size: 14.0pt;">.searchKey !== event.target.value) {<o:p></o:p></span></span></div>
<div class="MsoNormal" style="background: #1E1E1E; line-height: 14.25pt; margin-bottom: .0001pt; margin-bottom: 0in;">
<span style="font-weight: normal;"><span style="color: #d4d4d4; font-family: "consolas"; font-size: 14.0pt;"> </span><span style="color: #569cd6; font-family: "consolas"; font-size: 14.0pt;">this</span><span style="color: #d4d4d4; font-family: "consolas"; font-size: 14.0pt;">.isRenderCallbackActionExecuted = </span><span style="color: #569cd6; font-family: "consolas"; font-size: 14.0pt;">false</span><span style="color: #d4d4d4; font-family: "consolas"; font-size: 14.0pt;">;<o:p></o:p></span></span></div>
<div class="MsoNormal" style="background: #1E1E1E; line-height: 14.25pt; margin-bottom: .0001pt; margin-bottom: 0in;">
<span style="font-weight: normal;"><span style="color: #d4d4d4; font-family: "consolas"; font-size: 14.0pt;"> </span><span style="color: #569cd6; font-family: "consolas"; font-size: 14.0pt;">this</span><span style="color: #d4d4d4; font-family: "consolas"; font-size: 14.0pt;">.searchKey = event.target.value;<o:p></o:p></span></span></div>
<div class="MsoNormal" style="background: #1E1E1E; line-height: 14.25pt; margin-bottom: .0001pt; margin-bottom: 0in;">
<span style="color: #d4d4d4; font-family: "consolas"; font-size: 14pt; font-weight: normal;"> }<o:p></o:p></span></div>
<div class="MsoNormal" style="background: #1E1E1E; line-height: 14.25pt; margin-bottom: .0001pt; margin-bottom: 0in;">
<br /></div>
<div class="MsoNormal" style="background: #1E1E1E; line-height: 14.25pt; margin-bottom: .0001pt; margin-bottom: 0in;">
<span style="color: #d4d4d4; font-family: "consolas"; font-size: 14pt; font-weight: normal;">}<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in;">
<br /></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in;">
<br /></div>
<span style="color: #444444;"><span style="font-weight: normal;">I hope you enjoyed the learning, please write me back the suggestions, comments or any issues. Let's meet in our next blog with more learnings and fun. :)</span><br /><br /><br />THANK YOU!</span></div>
</h4>
</div>
Amolhttp://www.blogger.com/profile/04561932834601726448noreply@blogger.com2tag:blogger.com,1999:blog-6457252088873371292.post-30634194118080796362019-04-09T20:31:00.001-04:002020-09-08T08:29:52.103-04:00Salesforce : Lightning Web Components : Pagination with Search and List View - Step by Step Implementation<head>
<script data-ad-client="ca-pub-6231630339453617" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
</head>
<div dir="ltr" style="text-align: left;" trbidi="on">
<head>
<script src="https://alexgorbatchev.com/pub/sh/2.1.364/scripts/shCore.js" type="text/javascript"></script>
<script src="https://alexgorbatchev.com/pub/sh/2.1.364/scripts/shBrushRuby.js" type="text/javascript"></script> <script src="https://alexgorbatchev.com/pub/sh/2.1.364/scripts/shLegacy.js" type="text/javascript"></script>
<link href="https://alexgorbatchev.com/pub/sh/2.1.364/styles/shCore.css" rel="stylesheet" type="text/css"></link>
<link href="https://alexgorbatchev.com/pub/sh/2.1.364/styles/shThemeDefault.css" rel="stylesheet" type="text/css"></link> <script language="javascript">
window.onload = function () {
dp.SyntaxHighlighter.ClipboardSwf = 'http://alexgorbatchev.com/pub/sh/2.1.364/scripts/clipboard.swf';
dp.SyntaxHighlighter.HighlightAll('code');
dp.SyntaxHighlighter.BloggerMode();
}
</script>
</head>
<br />
<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-size: large;">Hello Guys,</span><br />
<span style="font-size: large;">As we have seen Salesforce recently published a very very important development feature/platform called <b>'Lightning Web Components'</b>. If you are new to these, I have a sample Pagination implementation example which will try to cover some of the use cases in Lightning web components.</span><br />
<span style="font-size: large;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiLiHaP1zJtXFSBZidrWsDkAfbo54ApFXULollHlpthtzXInHtoLEYpmG9jTIYtdiGSbjysZE_FQBOPy6CyFQVW-vjXoQzkzcGGPugOh_Uu9XsUAumIv2zB3srgKtrsdbOzhMqjE9tVRKp/s1600/chrome-capture.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="485" data-original-width="1314" height="236" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiLiHaP1zJtXFSBZidrWsDkAfbo54ApFXULollHlpthtzXInHtoLEYpmG9jTIYtdiGSbjysZE_FQBOPy6CyFQVW-vjXoQzkzcGGPugOh_Uu9XsUAumIv2zB3srgKtrsdbOzhMqjE9tVRKp/s640/chrome-capture.gif" width="640" /></a></div>
<span style="font-size: large;"><br /></span><span style="font-size: large;">Let's begin with our journey to <b>Pagination</b>. :)</span><br />
<h2>
</h2>
<h2 style="text-align: left;">
</h2>
<h2>
<ul style="text-align: left;">
<li><span style="font-size: large;"><span style="font-weight: normal;">Create a component called </span>paginatorBottom<span style="font-weight: normal;">. This component will have the buttons for the pagination such as </span>Previous<span style="font-weight: normal;">, </span>Next<span style="font-weight: normal;">, </span>First<span style="font-weight: normal;">, </span>Last<span style="font-weight: normal;">. This component will fire events on the button actions which will be caught by the parent components.</span></span></li>
</ul>
</h2>
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsVbhoKOE7tJ8ScIGHCKQZ__HAZc_JS2k3TYzlSOXO-QF6mmp4xXHNvpAOtt3djAScGukI5olb4XcGO7dt1n2qiREVeSn_kNgtlMgp7ofsqFSpmbdpmfKL5r31wsv0EnjHAPa_HMdCNsI/s1600/buttons.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="48" data-original-width="550" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsVbhoKOE7tJ8ScIGHCKQZ__HAZc_JS2k3TYzlSOXO-QF6mmp4xXHNvpAOtt3djAScGukI5olb4XcGO7dt1n2qiREVeSn_kNgtlMgp7ofsqFSpmbdpmfKL5r31wsv0EnjHAPa_HMdCNsI/s1600/buttons.PNG" /></a><br />
<h3 style="text-align: left;">
<i><b><span style="font-size: large;">paginatorBottom.html</span></b></i></h3>
<div style="text-align: left;">
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> <template>
<lightning-layout>
<lightning-layout-item>
<lightning-button label="First" icon-name="utility:chevronleft" onclick={handleFirst}
disabled={showFirstButton}></lightning-button>
</lightning-layout-item>
<lightning-layout-item>
<lightning-button label="Previous" icon-name="utility:chevronleft" onclick={handlePrevious}
disabled={showFirstButton}></lightning-button>
</lightning-layout-item>
<lightning-layout-item flexibility="grow"></lightning-layout-item>
<lightning-layout-item>
<lightning-button label="Next" icon-name="utility:chevronright" icon-position="right" onclick={handleNext}
disabled={showLastButton}></lightning-button>
</lightning-layout-item>
<lightning-layout-item>
<lightning-button label="Last" icon-name="utility:chevronright" icon-position="right" onclick={handleLast}
disabled={showLastButton}></lightning-button>
</lightning-layout-item>
</lightning-layout>
</template>
</code></pre>
</div>
<h2 style="text-align: left;">
</h2>
<h3 style="text-align: left;">
<i><span style="font-size: large;">
paginatorBottom.js</span></i></h3>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> import { LightningElement, api } from 'lwc';
export default class PaginatorBottom extends LightningElement {
// Api considered as a reactive public property.
@api totalrecords;
@api currentpage;
@api pagesize;
// Following are the private properties to a class.
lastpage = false;
firstpage = false;
// getter
get showFirstButton() {
if (this.currentpage === 1) {
return true;
}
return false;
}
// getter
get showLastButton() {
if (Math.ceil(this.totalrecords / this.pagesize) === this.currentpage) {
return true;
}
return false;
}
//Fire events based on the button actions
handlePrevious() {
this.dispatchEvent(new CustomEvent('previous'));
}
handleNext() {
this.dispatchEvent(new CustomEvent('next'));
}
handleFirst() {
this.dispatchEvent(new CustomEvent('first'));
}
handleLast() {
this.dispatchEvent(new CustomEvent('last'));
}
}
</code></pre>
<h2 style="text-align: left;">
<ul style="font-weight: normal;">
<li><span style="font-weight: normal;"><span style="font-size: large;">Create a Lightning Web component called as a recordList. This component will fetch the records from the Apex class by calling the method. This component will give us information about the Total number of records, Total pages, Accounts data.</span></span></li>
</ul>
<ul style="font-weight: normal;">
<li><span style="font-weight: normal;"><span style="font-size: large;">We can see that the recordList.js will have the chaining of the apex method calls(First record count method call then retrieve actual data method call). I intentionally added chaining to showcase how it works.</span></span></li>
</ul>
<ul style="text-align: left;">
<li><span style="font-size: large;"><span style="font-weight: normal;">This component also has the Search functionality. It showcases the usage of standard renderedCallback function and how to avoid the recursive of infinite calls. Ex. </span>isSearchChangeExecuted <span style="font-weight: normal;">variable.</span></span></li>
</ul>
</h2>
<div style="text-align: left;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPhPwb2zpOrmf9ggh59kmGSCD7YnHFl3wrmUafU0i9EpCx84SSEcPsdRu-Buw1b8KeyfrNpVKx8o3PxkaIjMiFaH3CesWo16W6aAdFb0UV_Tk3hiwYtcNwS3Rxcp8k0wFjbQvLBXxggC0/s1600/records.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="312" data-original-width="608" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPhPwb2zpOrmf9ggh59kmGSCD7YnHFl3wrmUafU0i9EpCx84SSEcPsdRu-Buw1b8KeyfrNpVKx8o3PxkaIjMiFaH3CesWo16W6aAdFb0UV_Tk3hiwYtcNwS3Rxcp8k0wFjbQvLBXxggC0/s1600/records.PNG" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<h3 style="text-align: left;">
<i><span style="font-size: large;">
recordList.html</span></i></h3>
<div>
<pre style="background: rgb(240, 240, 240); border: 1px dashed rgb(204, 204, 204); color: black; font-family: arial; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; overflow-wrap: normal;"><span style="font-size: 12px;"> <template>
<lightning-card title="Accounts List" icon-name="custom:custom63">
<div class="slds-m-around_medium">
<lightning-input type="search" onchange={handleKeyChange} class="slds-m-bottom_small" label="Search"
value={searchKey}></lightning-input>
<template if:true={accounts}>
<table
class="slds-table slds-table_bordered slds-table_striped slds-table_cell-buffer slds-table_fixed-layout">
<thead>
<tr class="slds-text-heading_label">
<th scope="col">
<div class="slds-truncate" title="ID">ID</div>
</th>
<th scope="col">
<div class="slds-truncate" title="Name">Name</div>
</th>
</tr>
</thead>
<tbody>
<!-- Use the Apex model and controller to fetch server side data -->
<template for:each={accounts} for:item="account">
<tr key={account.Id}>
<th scope="row">
<div class="slds-truncate" title={account.Id}>{account.Id}</div>
</th>
<td>
<div class="slds-truncate" title={account.Name}>{account.Name}</div>
</td>
</tr>
</template>
</tbody>
</table>
</template>
</div>
<p class="slds-m-vertical_medium content">Total records: <b>{totalrecords} </b> Page <b>{currentpage}</b> of
<b> {totalpages}</b></p>
</lightning-card>
</template> </span><span style="font-size: large;"><b><i>
</i></b></span></code></pre>
<h3 style="text-align: left;">
<span style="font-size: large;"><i>recordList.js</i></span></h3>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> import { LightningElement, track, api } from 'lwc';
import getAccountsList from '@salesforce/apex/ManageRecordsController.getAccountsList';
import getAccountsCount from '@salesforce/apex/ManageRecordsController.getAccountsCount';
export default class RecordList extends LightningElement {
@track accounts;
@track error;
@api currentpage;
@api pagesize;
@track searchKey;
totalpages;
localCurrentPage = null;
isSearchChangeExecuted = false;
// not yet implemented
pageSizeOptions =
[
{ label: '5', value: 5 },
{ label: '10', value: 10 },
{ label: '25', value: 25 },
{ label: '50', value: 50 },
{ label: 'All', value: '' },
];
handleKeyChange(event) {
if (this.searchKey !== event.target.value) {
this.isSearchChangeExecuted = false;
this.searchKey = event.target.value;
this.currentpage = 1;
}
}
renderedCallback() {
// This line added to avoid duplicate/multiple executions of this code.
if (this.isSearchChangeExecuted && (this.localCurrentPage === this.currentpage)) {
return;
}
this.isSearchChangeExecuted = true;
this.localCurrentPage = this.currentpage;
getAccountsCount({ searchString: this.searchKey })
.then(recordsCount => {
this.totalrecords = recordsCount;
if (recordsCount !== 0 && !isNaN(recordsCount)) {
this.totalpages = Math.ceil(recordsCount / this.pagesize);
getAccountsList({ pagenumber: this.currentpage, numberOfRecords: recordsCount, pageSize: this.pagesize, searchString: this.searchKey })
.then(accountList => {
this.accounts = accountList;
this.error = undefined;
})
.catch(error => {
this.error = error;
this.accounts = undefined;
});
} else {
this.accounts = [];
this.totalpages = 1;
this.totalrecords = 0;
}
const event = new CustomEvent('recordsload', {
detail: recordsCount
});
this.dispatchEvent(event);
})
.catch(error => {
this.error = error;
this.totalrecords = undefined;
});
}
}
</code></pre>
<div>
<ul style="text-align: left;">
<li><span style="font-size: large;">Now we will create a parent component which will include both these components.</span></li>
<li><span style="font-size: large;">This component will handle the events fired by buttons.</span></li>
</ul>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_VkA54T07-vcPy1rHHkPfQLjpXp9KQ7NRKyRNVtfN27-zvEK-2Bvln4crtzqU_CJtN1CP8e2JYdS9rLRV6yAWewJqfoSgFq6YqyV-BFe3HmrTMU0EK1f_O01HNf3-zFq8qd57cfLHze8/s1600/pagination.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="397" data-original-width="610" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_VkA54T07-vcPy1rHHkPfQLjpXp9KQ7NRKyRNVtfN27-zvEK-2Bvln4crtzqU_CJtN1CP8e2JYdS9rLRV6yAWewJqfoSgFq6YqyV-BFe3HmrTMU0EK1f_O01HNf3-zFq8qd57cfLHze8/s1600/pagination.PNG" /></a></div>
<div>
<span style="font-size: large;"><br /></span></div>
<h3 style="text-align: left;">
<span style="font-size: large;"><i>paginationParent.html</i></span></h3>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> <template>
<lightning-card>
<c-record-list currentpage={page} onrecordsload={handleRecordsLoad} pagesize={pagesize}></c-record-list>
<div class="slds-m-around_medium">
<c-paginator-bottom onprevious={handlePrevious} onnext={handleNext} onfirst={handleFirst}
onlast={handleLast} currentpage={page} totalrecords={totalrecords} pagesize={pagesize}>
</c-paginator-bottom>
</div>
</lightning-card>
</template>
</code></pre>
<div>
<span style="font-size: large;"><br /></span></div>
<div>
<h3 style="text-align: left;">
<span style="font-size: large;"><i>paginationParent.js</i></span></h3>
<span style="font-size: large;"><br /></span></div>
<div>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> import { LightningElement, track, api } from 'lwc';
const PAGE_SIZE = 5;
export default class PaginationParent extends LightningElement {
@api page = 1;
@api totalrecords;
@api _pagesize = PAGE_SIZE;
get pagesize() {
return this._pagesize;
}
set pagesize(value) {
this._pagesize = value;
}
handlePrevious() {
if (this.page > 1) {
this.page = this.page - 1;
}
}
handleNext() {
if (this.page < this.totalPages)
this.page = this.page + 1;
}
handleFirst() {
this.page = 1;
}
handleLast() {
this.page = this.totalPages;
}
handleRecordsLoad(event) {
this.totalrecords = event.detail;
this.totalPages = Math.ceil(this.totalrecords / this.pagesize);
}
handlePageChange(event) {
this.page = event.detail;
}
}
</code></pre>
<div>
<span style="font-size: large;">Now finally create Apex class <b>ManageRecordsController</b>, which will give us the required information such as record count, account list.</span></div>
<div>
<span style="font-size: large;"><br /></span></div>
<div>
<span style="font-size: large;">Note: We have intentionally created separate methods for record count and account list, to showcase the chaining of the Apex method calls.</span></div>
<div>
<b style="font-size: x-large;"><br /></b>
<br />
<h3 style="text-align: left;">
<b><i><span style="font-size: large;">ManageRecordsController.cls</span></i></b></h3>
</div>
<div>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> public with sharing class ManageRecordsController {
@AuraEnabled(cacheable = true)
public static List<Account> getAccountsList(Integer pagenumber, Integer numberOfRecords, Integer pageSize, String searchString) {
String searchKey = '%' + searchString + '%';
String query = 'select id, Name from Account ';
if (searchString != null && searchString != '') {
query += ' where name like \'%' + searchString + '%\' ';
}
query += ' limit ' + pageSize + ' offset ' + (pageSize * (pagenumber - 1));
return Database.query(query);
}
@AuraEnabled(cacheable = true)
public static Integer getAccountsCount(String searchString) {
String query = 'select count() from Account ';
if (searchString != null && searchString != '') {
query += ' where name like \'%' + searchString + '%\' ';
}
return Database.countQuery(query);
}
}
</code></pre>
<div>
<span style="font-size: large;">We are ready with our pagination Lightning Web Component implementation. You can include this component anywhere. </span></div>
<div>
<span style="font-size: large;"><br /></span></div>
<div>
<span style="font-size: large;">Example</span></div>
<div>
<br /></div>
<div>
<div style="color: #d4d4d4; font-family: consolas, "courier new", monospace; font-size: 14px; white-space: pre;">
<div style="background-color: #1e1e1e; line-height: 19px;">
<div>
<span style="color: grey;"><</span><span style="color: #569cd6;">template</span><span style="color: grey;">></span></div>
<div>
<span style="color: grey;"><</span><span style="color: #569cd6;">c-pagination-bar</span><span style="color: grey;">></</span><span style="color: #569cd6;">c-pagination-bar</span><span style="color: grey;">></span></div>
<div>
<span style="color: grey;"></</span><span style="color: #569cd6;">template</span><span style="color: grey;">></span></div>
</div>
</div>
</div>
<div>
<br /></div>
<div>
<br /></div>
<h2 style="text-align: left;">
<span style="font-size: large; font-weight: normal;">And don't forget to include following lines in the meta.xml file, in case you wanna expose this pagination on App/Record/Hope page.</span></h2>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>45.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__AppPage</target>
<target>lightning__RecordPage</target>
<target>lightning__HomePage</target>
</targets>
</LightningComponentBundle>
</code></pre>
<h2 style="text-align: left;">
<span style="font-weight: normal;"><span style="font-size: large;">I hope you enjoyed the learning, please write me back the suggestions, comments or any issues. Let's meet in our next blog with more learnings and fun. :)</span></span></h2>
<div>
<span style="font-weight: normal;"><br /></span></div>
<div>
<b>THANK YOU.</b></div>
</div>
</div>
</div>
</div>
</div>
Amolhttp://www.blogger.com/profile/04561932834601726448noreply@blogger.com23