Dynamic List Component in Lightning

In most of the projects, there is one common requirement to display the list of records for different Sobjects. If it is a Sales project then we need to display a list of Leads or Opportunities, and if it is a Service project then we need to display the list of Accounts, Cases and so on. Every time we have to develop such a requirement, we create the component, write apex class to return the records, and display it on the page. This repeats for the number of different Sobject list we need to display on different pages. This is where we can use Dynamic List Component in Lightning.

Today, we will go through the Dynamic List Component. A single component that will be used to display a list of records. This component will work for any Sobject and the Columns for the table will be configurable for each Sobject.

Steps to Implement

  1. Create a Lightning component to display the datatable. It will have attributes to store the Sobject name, list of records, and list of columns.
  2. Create the design attributes in the Design resource that will be used to select the Sobject name and Fieldset API name at the time of adding component on the page in App Builder.
  3. Call an Apex method from the Lightning Component from init handler that will pass the Sobject name and the API name of the Fieldset as a parameter. Make sure that you have the Fieldset created with the name provided for the selected Sobject.
  4. Apex method will fetch the list of fields from Fieldset for selected Sobject and create a dynamic query to get the list of records.
  5. Create a wrapper that will contain the list of records and list of fields and return to Lightning Component.
  6. Assign the list of records and list of fields to data and columns attributes respectively.

While adding the Lightning component to the page from App Builder, select the Sobject name like Account and enter the API name of Fieldset for that particular Sobject and we are done. Our Component will take care of displaying the datatable with columns. Fields in the Fieldset will determine columns.

In order to add/remove columns, you just need to add/remove fields from Fieldset for a particular Sobject.

To display Dynamic Picklist as Design Attribute such as Sobject Picklist in our case is not that straight forward. I have attached the code but I haven’t explained it in this post. For that, you can check this implementation to understand it better.

Code

ListComponent.cmp

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes" access="global"
                controller="ListController">

    <!-- Attributes to store Sobject name, list of records in data attribute, list of columns in columns attribute -->
    <aura:attribute name="strSobjectName" type="String" default="Account"/>
    <aura:attribute name="strFieldSet" type="String" default=""/>
    <aura:attribute name="data" type="Object"/>
	<aura:attribute name="columns" type="List"/>
    
    <!-- Init Handler -->
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    
    <lightning:card>
        <h1 class="slds-align_absolute-center">{!v.strSobjectName} Records</h1> <br/>
        
        <!-- To display list of records -->
        <lightning:datatable data="{!v.data}" 
            columns="{!v.columns}" 
            keyField="id"/>
    </lightning:card>
    
</aura:component>

ListComponentController.js

({
	doInit : function(component, event, helper) {
		helper.doInitHelper(component, event, helper);
	}
})

ListComponentHelper.js

({
	doInitHelper : function(component, event, helper) {
		
        // Calling apex method to fetch the records and passing Sobject name.
        var objAction = component.get("c.getSObjects");
        objAction.setParams({
            'strSObjectName' : component.get('v.strSobjectName'),
            'strFieldSetName' : component.get('v.strFieldSet')
        });
    	objAction.setCallback(this, function(objResponse) {
            var objState = objResponse.getState();
            if (objState === "SUCCESS") {
                
                // Assigning the list of records and columns to data and columns attributes respectively.
                var lstSobjectsWrapper = objResponse.getReturnValue();
                let lstColumnsFromFieldSet = [];
                for(let objRecord in lstSobjectsWrapper.lstFieldSets){
                    lstColumnsFromFieldSet.push(
                    	{
                            label: lstSobjectsWrapper.lstFieldSets[objRecord].strLabel, 
                         	fieldName: lstSobjectsWrapper.lstFieldSets[objRecord].strName, type: 'text',sortable:true
                        }
                    );
                }
                component.set('v.columns', lstColumnsFromFieldSet);
                component.set("v.data", lstSobjectsWrapper.lstSObjectRecords);
            } else if (objState === "ERROR") {
                
                // Error Handling.
            }
        });
        $A.enqueueAction(objAction);
	}
})

ListComponent.design

<design:component label="List Component">
    <design:attribute name="strSobjectName" label="Select List Object" 
                      description="Name of the SObject for List Component" 
                      datasource="apex://ListSObjects"/>
    <design:attribute name="strFieldSet" label="Select Fieldset API Name" 
                      description="API Name of the Fieldset of the Sobject"/>
</design:component>

ListSobjects.apxc

global class ListSObjects extends VisualEditor.DynamicPickList{    
    
    // Return the default value for Picklist.
    global override VisualEditor.DataRow getDefaultValue(){
        VisualEditor.DataRow defaultValue = new VisualEditor.DataRow('Account', 'Account');
        return defaultValue;
    }
    
    // To return the list of Sobjects.
    global override VisualEditor.DynamicPickListRows getValues() {
        List<Schema.SObjectType> lstObjectSchema = Schema.getGlobalDescribe().Values();
        VisualEditor.DataRow objListValue;
        VisualEditor.DynamicPickListRows  lstSObjects = new VisualEditor.DynamicPickListRows();
        for(SObjectType objSobject : lstObjectSchema){
            objListValue = new VisualEditor.DataRow(objSobject.getDescribe().getName(), objSobject.getDescribe().getName());
        	lstSObjects.addRow(objListValue);
        }
        return lstSObjects;
    }
}

ListController.apxc

public class ListController {
    @AuraEnabled
    public static ListController.ListControllerWrapper getSObjects(String strSObjectName, String strFieldSetName){
        
        // This method will return the wrapper which has list of records and list of columns.
        List<ListController.FieldSetWrapper> lstFieldSets = new List<ListController.FieldSetWrapper>();
        List<SObject> lstSObjectRecords = new List<SObject>();
        ListController.ListControllerWrapper lstWrapperToReturn = new ListController.ListControllerWrapper();
        
        // Getting the list of fields to display using field set name.
        Map<String, Schema.SObjectType> mapGlobalDescribe = Schema.getGlobalDescribe();
        Schema.SObjectType objSobjectType = mapGlobalDescribe.get(strSObjectName);
        Schema.DescribeSObjectResult objdsr = objSobjectType.getDescribe();
        Schema.FieldSet objFieldSet = objdsr.fieldSets.getMap().get(strFieldSetName);
        
        // Creating dynamic SOQL query to fetch the records.
        String strQuery = 'SELECT ';
        for(Schema.FieldSetMember objSetMember : objFieldSet.getFields()) {
            strQuery += objSetMember.getFieldPath() + ', ';
            ListController.FieldSetWrapper objField = new ListController.FieldSetWrapper();
            objField.strLabel = objSetMember.getLabel();
            objField.strName = objSetMember.getFieldPath();
            lstFieldSets.add(objField);
        }
        strQuery += 'Id';
        strQuery += ' FROM ' +strSObjectName;
        lstSobjectRecords = Database.query(strQuery);
        
        // Creating instance of wrapper to return.
        lstWrapperToReturn.lstSObjectRecords = lstSObjectRecords;
        lstWrapperToReturn.lstFieldSets = lstFieldSets;
        return lstWrapperToReturn;
        
    }
    
    public class ListControllerWrapper {
        @AuraEnabled public List<SObject> lstSObjectRecords;
        @AuraEnabled public List<ListController.FieldSetWrapper> lstFieldSets;
    }
    
    public class FieldSetWrapper {
        @AuraEnabled public String strLabel;
        @AuraEnabled public String strName;
    }
}

Dynamic List Component in Lightning

After adding Dynamic List Component into any Lightning page using App Builder, the output will look something like this:

Dynamic List Component in Lightning
Dynamic List Component in Lightning

This is all for the Dynamic List Component in Lightning. You can modify it by providing page size for table or where conditions for SOQL query using design attributes to make it more dynamic.

If you don’t want to miss new post, please Subscribe here.

If you want to check more custom implementations like Dynamic List Component in Lightning, you can check it here.

Leave a Comment