LWC: Audit log viewer using the infinite scrolling feature of the lightning data table

Do you want to know what are the best practices when you want to display a large amount of data in your Lightning Web Component? If you know that your component has to display a large amount of data, consider using the lazy loading of data. Never display the data upfront which the user might never ask for. It is always a good practice to load the minimum required amount of data on the component load, and then load the subsequent data on demand. There are a lot of ways to implement lazy loading in lightning component and the simplest and most elegant way to implement lazy loading is by using the infinite scrolling feature provided as a part of the lightning data table.

Today, we will build a lightning web component that displays the audit log history of the org using the lightning data table. Below are the key concepts that will be covered in this blog:
1) Use of infinite scrolling in the lightning data table
2) How to call apex method on initialization of a component
3) How to make use of a wrapper class to return a composite data structure
4) How to use various advanced features of ES6 such as a promise



Let us first try to understand what is lighting data table, its features, usage, and limitations. The lightning data table is used to display any kind of data in a tabular format. For each column, you can specify a data type and the component will display the data according to the specified data type. For example, if you specify the data type of a column as date, the values in that column are automatically formated as date fields.
The mandatory attributes that you need to populate when using lightning-data-table are data, columns, and key-field.
Data: The data attribute corresponds to the data which needs to be displayed in the table - this will be an array of objects.
Columns: The columns attribute corresponds to what information from the data attribute you need to display in the table - this is again an array of objects with each object containing at least following attributes - label and fieldName. The value in fieldName should match with the information passed into the data attribute.
Key-field: The key-field associates each row with a unique id - usually you will use the record id as the value in the key-field attribute.
The are several features supported by the lightning data table, out of which we will discuss one of the most important feature which is the infinite scrolling of rows in this article. To implement infinite scrolling, you need to include the attribute named enable-infinite-loading. Along with this, you need to include another attribute named onloadmore which will refer to a method present in your JavaScript class file and this method will be responsible to fetch more data and pass it back to the lightning data table. Lets now have a look at the code to see this in action.
The code is also available on Github.
auditTrailViewer.html
In the component markup, we have used the lightning data table component and have passed in all the required attributes that we discussed above. Please note that the lightning data table is wrapped inside a div tag with a height of 310px which gives the table a scroll bar. Because we have added the attribute enable-infinite-loading, so when the table is scrolled, the onloadmore is automatically called.
auditLogViewer.js
On the component load, the constructor of the component is automatically called. To make the component more performant, we query only 10 rows when the component loads. Initially, we keep the offset as 0 and the limit as 10 so that we get the top 10 records from the table. As and when the user scrolls the data table, the loadMoreData method is called, which increments the offset by 10 and makes the server call to fetch the next 10 records. This keeps on happening until we query all the records from the database. Now the question is how do we know that we have queried all the records from the database. We will see that in the apex controller.
Let's understand the loadMoreData method now. Here we make use of the Javascript promise. The first thing we do in the loadMoreData is that we turn on the spinner so that the user knows that some action is being performed. This is done by setting the is-loading attribute of the lightning data table as true. The target of the event is actually the lightning data table and on the target, we are setting isLoading as true which internally sets the attribute is-loading on lightning data table as true. In the next step, we increase the offset by 10 and call the loadRecords method. The loadRecords method returns us a promise and in the promise, we set the isLoading back to false which causes the spinner to disappear.
In the loadRecords method, we call the method present in our apex controller which issues a SOQL and returns us a composite data structure. We parse the response and add the new records into the existing _records array. Since the _records property is marked as tracked, this causes the component to rerender with the new data set.
AuditTrailViewerCtrl.cls
The getRecords method accepts two parameters. The first parameter is queryLimit is which fixed at 10 for each call. The second parameter is queryOffset which is 0 for the first call and gets incremented by 10 for each subsequent call. In each call, we return an instance of SetupAuditTrailInfo which is a wrapper class. The wrapper class contains 2 properties - the total count of records present in SetupAuditTrail object and the list of records of SetupAuditTrail. Please note that it is necessary to mark both the properties as AuraEnabled, only then it will be accessible in the JavaScript controller. If you don't mark a wrapper class property as @AuraEnabled, then the framework will not serialize that property. The count of records helps us determine whether we have queried all of the records from this table or not. In our JavaScript controller, we compare the total count of records with the offset to determine whether we need to make a server call on the scroll event or not.
Hope you have enjoyed reading this article. If you have any questions, please post them in the comments section.


Comments

Popular posts from this blog

Salesforce Lightning: Countdown timer

Salesforce Hacks: System.LimitException: Too many queueable jobs added to the queue: 2

Building an Org Role Hierarchy component in LWC