This is a quick post to understand how sorting is accomplished in lightning datatable (LWC).
Lightning datatable provides an onsort attribute which will allow us to implement the sorting for the elements in the table. You could implement sorting locally or via making a server call.
Local Sorting
You would generally implement this type of sorting if you know that the list of elements is going to be small and limited. For example, if you’re displaying a list of approval history records for a particular record, you know that the number of records won’t be more (assuming you have a simple approval process).
In the example below, we have created a simple component which displays the list of the contacts (firstName and lastName). When the header column is clicked the onsort handler is invoked, the field and the sort order is passed and using this information the list is sorted.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<lightning-datatable | |
key-field="Id" | |
data={results} | |
columns={columns} | |
hide-checkbox-column ="false" | |
show-row-number-column="true" | |
onsort={updateColumnSorting} | |
sorted-by={sortBy} | |
sorted-direction={sortDirection} | |
row-number-offset ="0" > | |
</lightning-datatable> | |
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { LightningElement,track,wire } from 'lwc'; | |
import fetchContact from '@salesforce/apex/ContactList.fetchContactLocal'; | |
const dataTablecolumns = [{ | |
label: 'First Name', | |
fieldName: 'FirstName', | |
sortable : true, | |
type: 'text' | |
}, | |
{ | |
label : 'Last Name', | |
fieldName : 'LastName', | |
type : 'text', | |
sortable : true | |
}] | |
export default class ContactListLocalSort extends LightningElement { | |
@track results=[]; | |
@track columns = dataTablecolumns; | |
@track sortBy='FirstName'; | |
@track sortDirection='asc'; | |
@wire(fetchContact) contactList({error, data}) { | |
if(data) | |
this.results=Object.assign([], data); | |
if(error) | |
console.log(error); | |
} | |
updateColumnSorting(event){ | |
let fieldName = event.detail.fieldName; | |
let sortDirection = event.detail.sortDirection; | |
//assign the values | |
this.sortBy = fieldName; | |
this.sortDirection = sortDirection; | |
//call the custom sort method. | |
this.sortData(fieldName, sortDirection); | |
} | |
//This sorting logic here is very simple. This will be useful only for text or number field. | |
// You will need to implement custom logic for handling different types of field. | |
sortData(fieldName, sortDirection) { | |
let sortResult = Object.assign([], this.results); | |
this.results = sortResult.sort(function(a,b){ | |
if(a[fieldName] < b[fieldName]) | |
return sortDirection === 'asc' ? –1 : 1; | |
else if(a[fieldName] > b[fieldName]) | |
return sortDirection === 'asc' ? 1 : –1; | |
else | |
return 0; | |
}) | |
} | |
} |
https://gist.github.com/jungleeforce/7ffb0e94bf0d5641d162f6295ac9df9f.js
Sorting via server call
As you would have guessed this would be useful when you have a huge list and you are displaying a small chunk of the total records.
The major advantage of this method is that you need not implement any custom logic at all. The sorting will be completely handled by the SOQL. Another thing to note here is that you will have to disable the data-table so that the user’s do not click on the header in the time the server call is being executed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<lightning-datatable | |
key-field="Id" | |
data={results} | |
columns={columns} | |
hide-checkbox-column ="false" | |
show-row-number-column="true" | |
onsort={updateColumnSorting} | |
sorted-by={sortBy} | |
sorted-direction={sortDirection} | |
row-number-offset ="0" > | |
</lightning-datatable> | |
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { LightningElement,track,wire } from 'lwc'; | |
import fetchContact from '@salesforce/apex/ContactList.fetchContact'; | |
const dataTablecolumns = [{ | |
label: 'First Name', | |
fieldName: 'FirstName', | |
sortable : true, | |
type: 'text' | |
}, | |
{ | |
label : 'Last Name', | |
fieldName : 'LastName', | |
type : 'text', | |
sortable : true | |
}] | |
export default class ContactListServerSort extends LightningElement { | |
@track results=[]; | |
@track columns = dataTablecolumns; | |
@track sortBy='FirstName'; | |
@track sortDirection='asc'; | |
//since we have used the dynamic wiring, | |
//the list is automatically refreshed when the sort direction or order changes. | |
@wire(fetchContact,{field : '$sortBy',sortOrder : '$sortDirection'}) contactList({error, data}) { | |
if(data) | |
this.results=Object.assign([], data); | |
if(error) | |
console.log(error); | |
} | |
updateColumnSorting(event){ | |
let fieldName = event.detail.fieldName; | |
let sortDirection = event.detail.sortDirection; | |
//assign the values. This will trigger the wire method to reload. | |
this.sortBy = fieldName; | |
this.sortDirection = sortDirection; | |
} | |
} |
Apex class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public with sharing class ContactList { | |
@AuraEnabled (Cacheable=true) | |
public static List<Contact> fetchContactLocal(){ | |
return [SELECT Id, FirstName, LastName | |
FROM CONTACT Order By FirstName ASC]; | |
} | |
@AuraEnabled (Cacheable=true) | |
public static List<Contact> fetchContact(String field, String sortOrder){ | |
return Database.query('SELECT Id, FirstName, LastName FROM Contact ORDER BY '+field+' '+sortOrder); | |
} | |
} |
Thank you for the nice post!
I want what is reason behind when you says if you have small amount amount of data then use ‘Local Sorting ‘. Why we can’t use local sorting for large amount of data ?
When u do local sorting the data is stored in-memory and that consumes lot of CPU resources. Now if you were to start sorting, paginating the records locally ( in the page) you will see performance issues when u load huge amount of data, says >10k ( again this depends on the machine’s configuration, how many tabs are already open and how much of the machine’s resources are utilized etc).