Reusable Related List using LWC in Salesforce

Reusable Related List using LWC in Salesforce

Sample code:

HTML:

<template>       
    <lightning-card title={titleWithCount} icon-name="standard:record">
        <lightning-button label="New" slot="actions" onclick={createNew}></lightning-button>
        <div slot="footer">
            <div  if:true={countBool}>
                <lightning-button label="View All" onclick={navigateToRelatedList}></lightning-button>
            </div>
        </div> 
        <div class="slds-m-around_medium">   
            <div if:true={listRecords}>   
                <template for:each={listRecords} for:item="rec">    
                    <div key={rec.Id} class="slds-box">                         
                        <lightning-record-view-form record-id={rec.Id} object-api-name={objectName}>
                            <div class="slds-grid">
                                <div class="slds-col slds-size_1-of-2">
                                    <lightning-output-field field-name={field1}></lightning-output-field>
                                    <lightning-output-field field-name={field2}></lightning-output-field>
                                </div>
                                <div class="slds-col slds-size_1-of-2">
                                    <lightning-output-field field-name={field3}></lightning-output-field>
                                    <lightning-output-field field-name={field4}></lightning-output-field>
                                </div>
                            </div>
                        </lightning-record-view-form><br/><br/>
                    </div>                       
                </template>   
            </div>   
        </div>   
    </lightning-card>       
</template>

JavaScript:

import { LightningElement, api, wire, track } from 'lwc'; 
import fetchRecords from '@salesforce/apex/RelatedListController.fetchRecords'; 
import { NavigationMixin } from 'lightning/navigation';
 
export default class RelatedList extends NavigationMixin( LightningElement ) { 
 
    @api objectName; 
    @api parentObjectName;
    @api fieldName; 
    @api fieldValue; 
    @api parentFieldAPIName; 
    @api recordId; 
    @api strTitle; 
    @api filterType; 
    @api operator; 
    @api fieldsList;
    @api relationshipApiName;
    @track field1;
    @track field2;
    @track field3;
    @track field4;
    @track listRecords;
    @track titleWithCount;
    @track countBool = false;

    connectedCallback() {

        var listFields = this.fieldsList.split( ',' );
        console.log( 'Fields are ' + listFields );
        this.field1 = listFields[ 0 ].trim();
        this.field2 = listFields[ 1 ].trim();
        this.field3 = listFields[ 2 ].trim();
        this.field4 = listFields[ 3 ].trim();
        console.log( 'Field 1 is ' + this.field1 );
        console.log( 'Field 2 is ' + this.field2 );
        console.log( 'Field 3 is ' + this.field3 );
        console.log( 'Field 4 is ' + this.field4 );

    }

    get vals() { 

        return this.recordId + '-' + this.objectName + '-' +  
               this.parentFieldAPIName + '-' + this.fieldName + '-' +  
               this.fieldValue + '-' + this.filterType + '-' + this.operator + '-' + this.fieldsList; 

    } 
     
    @wire(fetchRecords, { listValues: '$vals' }) 
    accountData( { error, data } ) {

        if ( data ) {
          
            this.listRecords = data.listRecords;

            if ( data.recordCount ) {
               
                if ( data.recordCount > 3 ) {

                    this.titleWithCount = this.strTitle + '(3+)';
                    this.countBool = true;
               
                } else {

                    this.countBool = false;
                    this.titleWithCount = this.strTitle + '(' + data.recordCount + ')';

                }
            }

        }

    }

    createNew() {

        this[NavigationMixin.Navigate]({
            type: 'standard__objectPage',
            attributes: {
                objectApiName: this.objectName,
                actionName: 'new'
            }
        });

    }

    navigateToRelatedList() {
       
        this[NavigationMixin.Navigate]({
            type: 'standard__recordRelationshipPage',
            attributes: {
                recordId: this.recordId,
                objectApiName: this.parentObjectName,
                relationshipApiName: this.relationshipApiName,
                actionName: 'view'
            }
        });

    }
 
} 

js-meta.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="RelatedList"> 
    <apiVersion>48.0</apiVersion> 
    <isExposed>true</isExposed> 
    <targets> 
        <target>lightning__RecordPage</target> 
    </targets> 
    <targetConfigs> 
        <targetConfig targets="lightning__RecordPage"> 
            <property name="strTitle" type="String" label="Title" description="Enter the title"/> 
            <property name="objectName" type="String" label="Object Name" description="Enter the object name"/> 
            <property name="parentObjectName" type="String" label="Parent Object Name" description="Enter the parent object name"/> 
            <property name="relationshipApiName" type="String" label="Relationship Name" description="Enter the relationship API name"/> 
            <property name="parentFieldAPIName" type="String" label="Parent Field API Name" description="Enter the parent field API Name"/> 
            <property name="fieldName" type="String" label="Field Name" description="Enter the field name"/> 
            <property name="fieldValue" type="String" label="Field Value" description="Enter the field value"/> 
            <property name="filterType" type="String" label="Filter Type" description="Enter the filter type"/> 
            <property name="operator" type="String" label="Operator" description="Enter the operator"/> 
            <property name="fieldsList" type="String" label="Fields List" description="Enter the field API names separated by coma. Do not enter more than 4 fields"/> 
        </targetConfig> 
    </targetConfigs> 
</LightningComponentBundle>

Apex Class:

public class RelatedListController { 
 
    @AuraEnabled( cacheable=true ) 
    public static RelatedListWrapper fetchRecords( String listValues )  { 

        system.debug( 'values are ' + listValues ); 
        List < String > strList = listValues.split( '-' ); 
        system.debug( 'values are ' + strList ); 
        RelatedListWrapper objWrap = new RelatedListWrapper();
         
        if ( strList.size() == 8 ) { 
         
            String recordId = strList.get( 0 ); 
            String objectName = strList.get( 1 ); 
            String parentFieldAPIName = strList.get( 2 ); 
            String fieldName = strList.get( 3 ); 
            String fieldValue = strList.get( 4 ); 
            String filterType = strList.get( 5 ); 
            String operator = strList.get( 6 ); 
            String fieldsList = strList.get( 7 ); 
             
            String strSOQL = 'SELECT Id';
            strSOQL += ', ' + fieldsList;
            String filter = ' FROM ' + objectName + ' WHERE ' + parentFieldAPIName + ' = \'' + recordId + '\' AND '; 
            if ( filterType == 'String' )     
                filter += fieldName + ' = \'' + fieldValue + '\''; 
            else if ( filterType == 'Boolean' )     
                filter += fieldName + ' = ' + fieldValue; 
            else 
                filter += fieldName + ' ' + operator + ' ' + fieldValue; 
            String strCountSOQL = ' SELECT COUNT() ' + filter;
            objWrap.recordCount = Database.countQuery( strCountSOQL );
            strSOQL += filter + ' LIMIT 3';     
            objWrap.listRecords = Database.query( strSOQL ); 
             
        }   
        return objWrap; 
         
    } 

    public class RelatedListWrapper {

        @AuraEnabled
        public List < SObject > listRecords;
        @AuraEnabled
        public Integer recordCount;

    }
         
}

Output:

Leave a Reply