Client Side (JavaScript) Pagination In Salesforce Lightning Web Component
Pagination allows users to see the data chunks in an organized way. This article is about designing a solution for client side (JavaScript) pagination for lightning data table in salesforce lightning web components.
We will fetch data from apex server and will store in to the data. We will calculate then the no of
pages. We will calculate it by using the data per page.
pages. We will calculate it by using the data per page.
Apex Class : [AccountClass .cls]
1
2
3
4
5
6
7
8
9
10
|
public with sharing class AccountClass {
@AuraEnabled
public static List<Account> getAccountList(){
return [select id, Name , Phone from Account limit 2000];
}
}
|
LWC HTML File : [dataTablePagination.html]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
<template>
<div class="container">
<lightning-card>
<lightning-layout multiple-rows="true">
<lightning-layout-item size="12" padding="around-medium">
<div class="slds-align_absolute-center">
<lightning-datatable
key-field="id"
data={currentPageData}
columns={columns}
hide-checkbox-column="true"
>
</lightning-datatable>
</div>
</lightning-layout-item>
<lightning-layout-item size="12" margin="around-small">
<div class="slds-align_absolute-center">
<ul class="slds-button-group-row">
<template if:true={hasPrev}>
<li class="slds-button-group-item" >
<button class="slds-button slds-button_neutral" onclick ={onPrev}> prev
</button>
</li>
</template>
<template for:each={pagesList} for:item= "pageNumber">
<li class="slds-button-group-item" key={pageNumber}>
<button data-id={pageNumber} class="slds-button slds-button_neutral"
onclick={onPageClick}>{pageNumber}</button>
</li>
</template>
<template if:true={hasNext}>
<li class="slds-button-group-item" >
<button class="slds-button slds-button_neutral" onclick={onNext}
>next</button>
</li>
</template>
</ul>
</div>
</lightning-layout-item>
</lightning-layout>
</lightning-card>
</div>
</template>
|
JavaScript Code : [dataTablePagination.js]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
import {LightningElement,track} from 'lwc';
import getAccountList from '@salesforce/apex/AccountClass.getAccountList';
const columns = [{
label: 'Name',
fieldName: 'Name'
},
{
label: 'Phone',
fieldName: 'Phone',
type: 'Phone'
},
];
export default class dataTablePagination extends LightningElement {
data = [];
@track page = 1;
perpage = 5;
@track pages = [];
set_size = 5;
columns = columns
renderedCallback() {
this.renderButtons();
}
renderButtons = () => {
this.template.querySelectorAll('button').forEach((but) => {
but.style.backgroundColor = this.page === parseInt(but.dataset.id, 10) ? 'dodgerblue' : 'white';
but.style.color = this.page === parseInt(but.dataset.id, 10) ? 'white' : 'black';
});
}
get pagesList() {
let mid = Math.floor(this.set_size / 2) + 1;
if (this.page > mid) {
return this.pages.slice(this.page - mid, this.page + mid - 1);
}
return this.pages.slice(0, this.set_size);
}
async connectedCallback() {
this.data = await getAccountList();
this.setPages(this.data);
}
pageData = () => {
let page = this.page;
let perpage = this.perpage;
let startIndex = (page * perpage) - perpage;
let endIndex = (page * perpage);
return this.data.slice(startIndex, endIndex);
}
setPages = (data) => {
let numberOfPages = Math.ceil(data.length / this.perpage);
for (let index = 1; index <= numberOfPages; index++) {
this.pages.push(index);
}
}
get hasPrev() {
return this.page > 1;
}
get hasNext() {
return this.page < this.pages.length
}
onNext = () => {
++this.page;
}
onPrev = () => {
--this.page;
}
onPageClick = (e) => {
this.page = parseInt(e.target.dataset.id, 10);
}
get currentPageData() {
return this.pageData();
}
}
|
Terminology’s used in the code:-
data = data fetched from server.
page = current page no.
perpage = data per page.
pages = number of pages = size of data/perPage.
set_size = no of the pages we want to show at a time. no of page number buttons.
Meta-XML File [dataTablePagination.js-meta.xml]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>47.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__AppPage</target>
<target>lightning__RecordPage</target>
<target>lightning__HomePage</target>
</targets>
</LightningComponentBundle>
|
Output :
Documentation :
Here we are tracking two private variables pages and page. page is current page and initialized with 1. let’s go by piece by piece of this code. In LWC when the component is loaded on the page then constructor of the corresponding js runs and then it calls the connected callback function. In connected call back function we are fetching the data from our aura enabled apex method.
We are going to call the apex method imperatively in connected callback. As the getAccountList() will return a promise so we can handle it using the async await. After getting the data we set the data in tot our private variable data and then we call a function setPages to initialize the list pages.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
async connectedCallback() {
this.data = await getAccountList();
this.setPages(this.data);
}
setPages = (data) => {
let numberOfPages = Math.ceil(data.length / this.perPage);
for (let index = 1; index <= numberOfPages; index++) {
this.pages.push(index);
}
}
|
As the await is an asynchronous process so the components renders and when the pages array is initialized again the component renders recuse we have marked the array pages as tracked property. So the component rerenders and this time the getter get pagesList() is computed and return the page numbers to display.
1
2
3
4
5
6
7
8
9
10
11
|
get pagesList() {
let mid = Math.floor(this.set_size / 2) + 1;
if (this.page > mid) {
return this.pages.slice(this.page - mid, this.page + mid - 1);
}
return this.pages.slice(0, this.set_size);
}
|
In the rendered call back function we highlight the current page button which is selected.In the rendered call back function we highlight the current page button which is selected.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
renderedCallback() {
this.renderButtons();
}
renderButtons = () => {
this.template.querySelectorAll('button').forEach((but) => {
but.style.backgroundColor =
this.page === parseInt(but.dataset.id, 10) ? 'yellow' : 'white';
});
}
|
To get the page data , the getter currentPageData is computed from component and then the page renders with the current page data.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
get currentPageData() {
return this.pageData();
}
pageData = () => {
let page = this.page;
let perpage = this.perpage;
let startIndex = (page * perpage) - perpage;
let endIndex = (page * perpage);
return this.data.slice(startIndex, endIndex);
}
|
Now when we click on button the page variable is being set to the current page and then it rerenders the component and then the getters are computed again. And so changing just one page variable is accomplishing our custom pagination task..
No comments:
Post a Comment