Developers / Admins

Building a Lightning Web Component (LWC) to Filter Related Records

By Stephen Taylor

Branded content with Stony Point

Here’s a business problem: your company has multiple, very large customers, each with hundreds of users that have the potential to submit cases for support. When customer service personnel or management want to review the history of cases for a customer, they will see a very long related list – hundreds, if not thousands, of cases on the account record. Instead, they will want to quickly see cases with different statuses so they can analyze the health of the customer in question.

There are multiple native solutions within Salesforce to help address these issues, but all of them are less than optimal – for example:

  • Creating multiple list views for each customer for each status of Case.
  • Utilizing the new Enhanced Related List component to build a filtered related list for each stage.
  • Building a parameterized report that can run a report and show all Cases for a customer grouped by Status.

These are all creative solutions, but they require significant configuration and maintenance work for each customer, especially when case statuses are changed, added, or removed.

Creating one related list that can be easily filtered by multiple fields will allow users to quickly see only the records they want to see, and the filters will be populated dynamically. There will be no need for any configuration changes as statuses are changed.

The Recommended Solution (And How to Accomplish It)

The solution? Create a custom Lightning Web Component (LWC) to display a list of related cases for an account record that will allow the user to filter the list of cases based on the status field.

We will be exploring the topic of retrieving a list of related records in a Lightning Web Component. This is a topic we commonly cover in the Developing Salesforce Lightning Web Components (SP-DEX602) class at Stony Point. Traditionally, when accessing related records from an LWC, we have had to use custom Apex code to query the database and return the list of records.

With the Summer ’22 release of Salesforce, however, the new uiRelatedListApi wire adapter module has moved from beta into full support. This means that we can use the getRelatedListRecords function from this module to return related records without having to write custom Apex code.

What Is the uiRelatedListApi?

The uiRelatedListApi is a wire adapter module that Salesforce provides for use with Lightning Web Components – it is built on top of the Lightning Data Service (LDS) and the User Interface API. This module provides functions for retrieving related lists’ metadata and records. To return a list of related case records for an account, the function we are going to look at using (from this module) is the getRelatedListRecords.

Using the getRelatedListRecords Function

For our example, we will be creating a Lightning Web Component called filteredRelatedCaseList. In order to use the wire adapter function, we first need to import the function from the wire adapter module in our JavaScript file. Since this function is called using the wire service, we also need to import the wire decorator from the LWC module.

The getRelatedListRecords function will require a parentRecordId parameter (the Account ID) as well as a relatedListId parameter (in this case, Cases). Optionally, we can also specify a parameter to determine which fields should be returned for the related records. The object payload returned from this function will include the usual data and error properties that we see when using the wire service. The data property will contain a Related List Record Collection.

The Process

For this component, we will use the getRelatedListRecords function to return a list of related Case records for an Account. We will also incorporate a lightning-combobox base component to give our users filter options, and two methods (handleSelection, updateList) to handle the selection from the user and apply the logic to update the list of records based on the user’s selection.

The handleSelection method will access the event data to determine the user’s selection, and the updateList method will perform the logic to determine which records meet the selection criteria, and move them into an array property called casesToDisplay.

Since this component will be used on an Account record page, in our JavaScript file we will create a public property to inherit the Account ID from the record page (@api recordId), and then pass that ID as a parameter to the getRelatedListRecords function that is being called using the wire service. We will also create a filterOptions property to hold the label and values for the options in the lightning-combobox.

Once the getRelatedListRecords function has returned the payload, we move the contents of the data property into our cases property that we have defined. We will then call the updateList method in our JavaScript file to ensure the records returned are moved into the casesToDisplay array property.

In our HTML file for the component, we iterate over the casesToDisplay array property and access the field values to display in the UI.

In order to test out this component you can drop it on an account Lightning record page to see the related list of case records. Don’t forget to update your component’s configuration file to expose it to be used in the Lightning App Builder and set a target for a Lightning record page (example below).

This finished component will look like this:

Filtered Related Case List Component

filteredRelatedCaseList.js

// filteredRelatedCaseList.js
import { LightningElement, api, wire } from 'lwc';
import { getRelatedListRecords } from 'lightning/uiRelatedListApi';
export default class FilteredRelatedCaseList extends LightningElement {
    @api recordId;
    filterOptions = [
        { label: 'All', value: 'All'},
        { label: 'Closed', value: 'Closed' },
        { label: 'New', value: 'New' },
        { label: 'Working', value: 'Working' },
        { label: 'Escalated', value: 'Escalated' }
    ];
   
    cases = [];
    casesToDisplay = [];
    status = 'All';
    showCases = false;
   
    get cardLabel() {
        return 'Related Cases (' + this.cases.length + ')';
    }
    @wire(getRelatedListRecords, {
        parentRecordId: '$recordId',
        relatedListId: 'Cases',
        fields: ['Case.Id', 'Case.CaseNumber', 'Case.Subject', 'Case.Status', 'Case.Priority']
    })
    wiredCases({data, error}){
        if (data) {
            this.cases = data.records;
            this.updateList();
            this.dispatchEvent(new CustomEvent('casecount', { detail: this.cases.length}));
        }
        if (error) {
            console.error('Error occurred retrieving Case records...');
        }
    }
    handleSelection(event) {
        this.status = event.detail.value;
        this.updateList();
    }
    updateList() {
        if (this.status === 'All') {
            this.casesToDisplay = this.cases;
        } else {
            this.casesToDisplay = this.cases.filter(elem => elem.fields.Status.value == this.status);
        }
        this.showCases = this.casesToDisplay.length > 0 ? true : false;
    }
}

filteredRelatedCaseList.html

<!-- filteredRelatedCaseList.html -->
<template>
    <lightning-card title={cardLabel} icon-name="standard:case">
        <lightning-combobox label="Status Filter" options={filterOptions} value={status} onchange={handleSelection}
            class="slds-m-bottom_small"></lightning-combobox>
        <template lwc:if={showCases}>
            <template for:each={casesToDisplay} for:item="cas">
                <div key={cas.fields.Id.value} class="slds-m-bottom_small">
                    <lightning-tile label={cas.fields.CaseNumber.value}>
                        <dl class="slds-dl_horizontal">
                            <dt class="slds-dl_horizontal__label">
                                <p class="slds-truncate" title="Subject">Subject:</p>
                            </dt>
                            <dd class="slds-dl_horizontal__detail slds-tile__meta">
                                <p class="slds-truncate" title="Subject">{cas.fields.Subject.value}</p>
                            </dd>
                            <dt class="slds-dl_horizontal__label">
                                <p class="slds-truncate" title="Status">Status:</p>
                            </dt>
                            <dd class="slds-dl_horizontal__detail slds-tile__meta">
                                <p class="slds-truncate" title="Status">{cas.fields.Status.value}</p>
                            </dd>
                            <dt class="slds-dl_horizontal__label">
                                <p class="slds-truncate" title="Priority">Priority:</p>
                            </dt>
                            <dd class="slds-dl_horizontal__detail slds-tile__meta">
                                <p class="slds-truncate" title="Priority">{cas.fields.Priority.value}</p>
                            </dd>
                        </dl>
                    </lightning-tile>
                </div>
            </template>
        </template>
        <template lwc:else>
            <p>No Case records to display.</p>
        </template>
    </lightning-card>
</template>

filteredRelatedCaseList.js-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>55.0</apiVersion>
    <isExposed>true</isExposed>
    <masterLabel>Filtered Related Case List Component</masterLabel>
    <description>This component will display a related list of Case records that is filterable.</description>
    <targets>
        <target>lightning__RecordPage</target>
    </targets>
</LightningComponentBundle>

Summary

It is sometimes necessary to create custom Lightning Components in our Salesforce orgs to meet specific business requirements. When these requirements necessitate the use of related record information, we can now use the uiRelatedListApi wire adapter module to access that information without the need to use Apex.

Since the functions in this module are built on top of the Lightning Data Service, there is a marked advantage to using them over traditional Apex methods, because the LDS manages the data for us by refreshing the cache of records automatically, as well as handling security to ensure records and/or fields are not returned to which the current user does not have access.

This is something that – traditionally – we had to manage ourselves when using Apex to return records and field values. I would invite you to consider using wire adapter modules over traditional Apex whenever possible for any custom components you create for your orgs in order to take advantage of the data management features that the Lightning Data Service provides.

Next Steps

To learn more from me and the other instructors at Stony Point, sign up for Class Pass and enjoy unlimited access to all our training for a full year!

The Author

Stephen Taylor

Stephen is both the Curriculum Developer and an instructor at Stony Point, Inc.

Leave a Reply