Skip to content

Instantly share code, notes, and snippets.

@amitastreait
Created April 11, 2021 06:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save amitastreait/843b4e93ce7f9d93a51a582be741987a to your computer and use it in GitHub Desktop.
Save amitastreait/843b4e93ce7f9d93a51a582be741987a to your computer and use it in GitHub Desktop.
<!--
@File Name : contactDataTable.html
@Description :
@Author : Amit Singh (SFDCPanther)
@Group :
@Last Modified By : Amit Singh
@Last Modified On : 12-06-2020
@Modification Log :
Ver Date Author Modification
1.0 5/28/2020 Amit Singh (SFDCPanther) Initial Version
-->
<template>
<lightning-card
variant="Narrow"
title="Contact Records"
icon-name="standard:contact"
>
<div class="slds-m-around_small">
<template if:true={errors}>
</template>
</div>
<div class="slds-m-around_small">
<template if:false={errors}>
<template if:true={records}>
<c-do-pagination
records={records}
show-table="true"
columns={columns}
recordsperpage="8"
onactions={handleRowActions}
onpagination={handlePagination}
>
</c-do-pagination>
</template>
</template>
</div>
</lightning-card>
</template>
/**
* @File Name : contactDataTable.js
* @Description :
* @Author : A Singh
* @Group :
* @Last Modified By : Amit Singh
* @Last Modified On : 12-06-2020
* @Modification Log :
* Ver Date Author Modification
* 1.0 6/5/2020 A Singh Initial Version
**/
import { LightningElement, track } from 'lwc';
import getContacts from '@salesforce/apex/ContactController.getContacts';
import sharedjs from 'c/sharedjs';
const columns = [
{ label: 'Name', fieldName: 'Name', wrapText: 'true', sortable: true, editable: true },
{ label: 'Email', fieldName: 'Email', type: 'email', sortable: true, editable: true },
{ label: 'Phone', fieldName: 'Phone', type: 'phone', sortable: true, editable: true },
{ label: 'Title', fieldName: 'Title', sortable: true, editable: true },
{
label: 'Account',
fieldName: 'ACC_NAME',
wrapText: 'true',
cellAttributes: {
iconName: { fieldName: 'accIconName' },
iconPosition: 'left'
},
sortable: true
},
{
label: 'Owner',
fieldName: 'OWNER',
cellAttributes: {
iconName: { fieldName: 'iconName' },
iconPosition: 'left'
},
sortable: true
},
{
label: 'View',
fieldName: 'URL',
type: 'url',
wrapText: 'true',
typeAttributes: {
tooltip: { fieldName: 'Name' },
label: {
fieldName: 'Name'
},
target: '_blank'
}
},
{ label: 'View', type: 'button', typeAttributes: {
label: 'View', name: 'View', variant: 'brand-outline',
iconName: 'utility:preview', iconPosition: 'right'
}
},
];
export default class ContactDataTable extends LightningElement {
@track records;
@track errors;
columns = columns;
connectedCallback() {
this.handleDoInit();
}
handleDoInit() {
sharedjs._servercall(
getContacts,
undefined,
this.handleSuccess.bind(this),
this.handleError.bind(this)
);
}
handleSuccess(result) {
result.forEach(element => {
if (element.OwnerId) {
element.OWNER = element.Owner.Name;
element.iconName = 'standard:user';
}
if (element.AccountId) {
element.ACC_NAME = element.Account.Name;
element.accIconName = 'standard:account';
}
element.URL = 'https://' + window.location.host + '/' + element.Id;
});
this.records = result;
this.errors = undefined;
}
handleError(error) {
this.errors = error;
this.records = undefined;
}
handleRowActions(event){
window.console.log(' Row Level Action Handled ', event.detail.actionName);
window.console.log(' Row Level Action Handled ', JSON.stringify(event.detail.data));
}
handlePagination(event){
//window.console.log('Pagination Action Handled ', JSON.stringify(event.detail.records));
}
}
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>50.0</apiVersion>
<isExposed>true</isExposed>
<masterLabel>Contact Data Table</masterLabel>
<targets>
<target>lightning__RecordPage</target>
<target>lightning__AppPage</target>
<target>lightning__HomePage</target>
<target>lightningCommunity__Page</target>
<target>lightningCommunity__Default</target>
</targets>
</LightningComponentBundle>
<template>
<div class="slds-m-aroung_small slds-align_absolute-center">
<lightning-spinner if:true={isLoading} alternative-text="Loading" size="small"></lightning-spinner>
<div slot="actions">
<lightning-button
variant="neutral"
title="first"
label="First"
class="slds-float_left"
icon-name="utility:chevronleft"
icon-position="left"
onclick={handleClick}
></lightning-button>
&nbsp;
<lightning-button
variant="neutral"
title="previous"
class="slds-float_left"
label="Previous"
icon-name="utility:chevronleft"
icon-position="left"
onclick={handleClick}
></lightning-button>
<template if:true={pagelinks}>
<lightning-button-group>
<template for:each={pagelinks} for:item="page">
<lightning-button
key={page}
label={page}
onclick={handlePage}
></lightning-button>
</template>
</lightning-button-group>
</template>
<lightning-button
variant="neutral"
title="next"
class="slds-float_right"
label="Next"
icon-name="utility:chevronright"
icon-position="right"
onclick={handleClick}
></lightning-button>
&nbsp;
<lightning-button
variant="neutral"
title="last"
class="slds-float_right"
label="Last"
icon-name="utility:chevronright"
icon-position="right"
onclick={handleClick}
></lightning-button>
</div>
</div>
<div class="slds-m-top_small"></div>
<h2
class="slds-m-aroung_small slds-align_absolute-center"
style="color: firebrick;"
>
Displaying Page No:
<strong>&nbsp;{pageNo}/{totalPages}&nbsp;</strong>and displaying records
<template if:true={end}>
from {endRecord}/{totalRecords}
</template>
<template if:false={end}>
from ({startRecord}-{endRecord})/{totalRecords}
</template>
</h2>
<div class="slds-m-top_small"></div>
<div class="slds-m-aroung_small">
<template if:true={showTable}>
<lightning-datatable
key-field="Id"
data={recordsToDisplay}
show-row-number-column="false"
hide-checkbox-column
columns={columns}
onrowaction={handleRowAction}
default-sort-direction={defaultSortDirection}
sorted-direction={sortDirection}
sorted-by={sortedBy}
onsort={onHandleSort}
onsave={handleSave}
draft-values={draftValues}
>
</lightning-datatable>
</template>
</div>
</template>
.customSelect select {
padding-right: 1.25rem;
min-height: inherit;
line-height: normal;
height: 1.4rem;
}
.customSelect label {
margin-top: 0.1rem;
}
.customSelect .slds-select_container::before {
border-bottom: 0;
}
.customInput {
width: 3rem;
height: 1.4rem;
text-align: center;
border: 1px solid #dddbda;
border-radius: 3px;
background-color: #fff;
}
import { LightningElement, api, track } from "lwc";
import { updateRecord } from 'lightning/uiRecordApi';
import { refreshApex } from '@salesforce/apex';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
const DELAY = 300;
export default class DoPaginaton extends LightningElement {
@api showTable = false;
@api records;
@api recordsperpage;
@api columns;
@track draftValues = [];
@track recordsToDisplay;
totalRecords;
pageNo;
totalPages;
startRecord;
endRecord;
end = false;
pagelinks = [];
isLoading = false;
defaultSortDirection = 'asc';
sortDirection = 'asc';
ortedBy;
connectedCallback() {
this.isLoading = true;
this.setRecordsToDisplay();
}
setRecordsToDisplay() {
this.totalRecords = this.records.length;
this.pageNo = 1;
this.totalPages = Math.ceil(this.totalRecords / this.recordsperpage);
this.preparePaginationList();
for (let i = 1; i <= this.totalPages; i++) {
this.pagelinks.push(i);
}
this.isLoading = false;
}
handleClick(event) {
let label = event.target.label;
if (label === "First") {
this.handleFirst();
} else if (label === "Previous") {
this.handlePrevious();
} else if (label === "Next") {
this.handleNext();
} else if (label === "Last") {
this.handleLast();
}
}
handleNext() {
this.pageNo += 1;
this.preparePaginationList();
}
handlePrevious() {
this.pageNo -= 1;
this.preparePaginationList();
}
handleFirst() {
this.pageNo = 1;
this.preparePaginationList();
}
handleLast() {
this.pageNo = this.totalPages;
this.preparePaginationList();
}
preparePaginationList() {
this.isLoading = true;
let begin = (this.pageNo - 1) * parseInt(this.recordsperpage);
let end = parseInt(begin) + parseInt(this.recordsperpage);
this.recordsToDisplay = this.records.slice(begin, end);
this.startRecord = begin + parseInt(1);
this.endRecord = end > this.totalRecords ? this.totalRecords : end;
this.end = end > this.totalRecords ? true : false;
const event = new CustomEvent('pagination', {
detail: {
records : this.recordsToDisplay
}
});
this.dispatchEvent(event);
window.clearTimeout(this.delayTimeout);
this.delayTimeout = setTimeout(() => {
this.disableEnableActions();
}, DELAY);
this.isLoading = false;
}
disableEnableActions() {
let buttons = this.template.querySelectorAll("lightning-button");
buttons.forEach(bun => {
if (bun.label === this.pageNo) {
bun.disabled = true;
} else {
bun.disabled = false;
}
if (bun.label === "First") {
bun.disabled = this.pageNo === 1 ? true : false;
} else if (bun.label === "Previous") {
bun.disabled = this.pageNo === 1 ? true : false;
} else if (bun.label === "Next") {
bun.disabled = this.pageNo === this.totalPages ? true : false;
} else if (bun.label === "Last") {
bun.disabled = this.pageNo === this.totalPages ? true : false;
}
});
}
handleRowAction(event) {
const actionName = event.detail.action.name;
const row = event.detail.row;
const rowAction = new CustomEvent('actions', {
detail: {
actionName : actionName,
data : row
}
});
this.dispatchEvent(rowAction);
}
handlePage(button) {
this.pageNo = button.target.label;
this.preparePaginationList();
}
onHandleSort(event) {
const { fieldName: sortedBy, sortDirection } = event.detail;
const cloneData = [...this.recordsToDisplay];
cloneData.sort(this.sortBy(sortedBy, sortDirection === 'asc' ? 1 : -1));
this.recordsToDisplay = cloneData;
this.sortDirection = sortDirection;
this.sortedBy = sortedBy;
}
sortBy( field, reverse, primer ) {
const key = primer
? function( x ) {
return primer(x[field]);
}
: function( x ) {
return x[field];
};
return function( a, b ) {
a = key(a);
b = key(b);
return reverse * ( ( a > b ) - ( b > a ) );
};
}
handleSave(event) {
this.isLoading = true;
const recordInputs = event.detail.draftValues.slice().map(draft => {
const fields = Object.assign({}, draft);
return { fields };
});
const promises = recordInputs.map(recordInput => updateRecord(recordInput));
window.console.log(' Updating Records.... ');
Promise.all(promises).then(record => {
this.dispatchEvent(
new ShowToastEvent({
title: 'Success',
message: 'All Records updated',
variant: 'success'
})
);
this.draftValues = [];
eval("$A.get('e.force:refreshView').fire();");
return refreshApex(this.recordsToDisplay);
}).catch(error => {
window.console.error(' error **** \n '+error);
})
.finally(()=>{
this.isLoading = false;
})
}
}
/* eslint-disable no-else-return */
/**
* @File Name : sharedjs.js
* @Description :
* @Author : amit.singh@salesforcemvps.com
* @Group :
* @Last Modified By : Amit Singh
* @Last Modified On : 12-06-2020
* @Modification Log :
* Ver Date Author Modification
* 1.0 5/17/2020 amit.singh@salesforcemvps.com Initial Version
**/
import { ShowToastEvent } from "lightning/platformShowToastEvent";
/*
! To store all the JS functions for the various LWC
* This JavaScript file is used to provide many reusability functionality like pubsub
* Reusable Apex Calls to Server, Preparing Dynamic Toasts
Todo : PubSub JS file of LWC & Aura Components
? V2
*/
var callbacks = {};
/**
* Registers a callback for an event
* @param {string} eventName - Name of the event to listen for.
* @param {function} callback - Function to invoke when said event is fired.
*/
const subscribe = (eventName, callback) => {
if (!callbacks[eventName]) {
callbacks[eventName] = new Set();
}
callbacks[eventName].add(callback);
};
/**
* Unregisters a callback for an event
* @param {string} eventName - Name of the event to unregister from.
* @param {function} callback - Function to unregister.
*/
const unregister = (eventName, callback) => {
if (callbacks[eventName]) {
callbacks[eventName].delete(callback);
// ! delete the callback from callbacks variable
}
};
const unregisterAll = () => {
callbacks = {};
};
/**
* Fires an event to listeners.
* @param {string} eventName - Name of the event to fire.
* @param {*} payload - Payload of the event to fire.
*/
const publish = (eventName, payload) => {
if (callbacks[eventName]) {
callbacks[eventName].forEach(callback => {
try {
callback(payload);
} catch (error) {
// fail silently
}
});
}
};
/**
* Todo: Calls an Apex Class method and send the response to call back methods.
* @param {*} _serveraction - Name of the apex class action needs to execute.
* @param {*} _params - the list of parameters in JSON format
* @param {*} _onsuccess - Name of the method which will execute in success response
* @param {*} _onerror - Name of the method which will execute in error response
*/
const _servercall = (_serveraction, _params, _onsuccess, _onerror) => {
if (!_params) {
_params = {};
}
_serveraction(_params)
.then(_result => {
if (_result && _onsuccess) {
_onsuccess(_result);
}
})
.catch(_error => {
if (_error && _onerror) {
_onerror(_error);
}
});
};
/**
* Todo: Prepare the toast object and return back to the calling JS class
* @param {String} _title - title of of the toast message
* @param {String} _message - message to display to the user
* @param {String} _variant - toast type either success/error/warning or info
* @param {String} _mode - defines either toast should auto disappear or it should stick.
*/
const _toastcall = (_title, _message, _variant, _mode) => {
const _showToast = new ShowToastEvent({
title: _title,
message: _message,
mode: _mode,
variant: _variant
});
return _showToast;
};
/**
* Todo: Parse the Error message and returns the parsed response to calling JS method.
* @param {Array} errors - Error Information
*/
const _reduceErrors = errors => {
if (!Array.isArray(errors)) {
errors = [errors];
}
return errors
.filter(error => !!error)
.map(error => {
if (Array.isArray(error.body)) {
return error.body.map(e => e.message);
} else if (error.body && typeof error.body.message === "string") {
return error.body.message;
} else if (typeof error.message === "string") {
return error.message;
}
return error.statusText;
})
.reduce((prev, curr) => prev.concat(curr), [])
.filter(message => !!message);
};
/*
Todo: Export all the functions so that these are accisible from the other JS Classes
*/
export default {
subscribe,
unregister,
publish,
unregisterAll,
_servercall,
_toastcall,
_reduceErrors
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment