Filtered related list using lightning:datatable

We can use a lightning:datatable component or aura:iteration to display data in tabular format. In this example we will use lightning:datatable component.

Note: lightning:datatable components are not supported on mobile devices.

For detail features supported please read https://developer.salesforce.com/docs/component-library/bundle/lightning:datatable/documentation

At the time of writing of this blog, resizing of columns was not working.
https://success.salesforce.com/issues_view?id=a1p3A0000018C5BQAU

Tables can be populated during initialization using the data, columns, and keyField attributes. The keyField attribute is required for correct table behavior. It associates each row with a unique identifier.

In this example we creates a table whose first column displays a hyper linked column to detail page of record.
Currently Salesforce does not provide option to filter results of related list e.g. one list of closed opportunities and another list for won opportunities or in our example user just want to see request order that are in Draft status. https://success.salesforce.com/ideaview?id=08730000000BrbgAAC

Filtered related list using lightning:datatable

Custom component cmpFilteredRelatedListDT uses Apex controller

<!-- 
    /**
     * @name       : cmpFilteredRelatedListDT
     * @category   : Lightning Component
     * @description: Lightning custom component for displaying filtered related list using lightning:datatable
     * @author     : Accletron Consulting   
     * @copyright  : Copyright © 2019 Accletron Consulting; All Rights Reserved
     */
 -->
<aura:component implements="flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId" access="global" controller="RelatedListController">
	<aura:attribute name="sdata"    type="Request_Order__c"/>
        <aura:attribute name="scolumns" type="List"/>
        <aura:attribute name="errors"   type="Object"/>
        <aura:attribute name="recordId" type="Id" />

        <aura:handler name="init" value="{! this }" action="{! c.init }"/>
        <lightning:datatable 
            data="{! v.sdata }"
            columns="{! v.scolumns }"
            keyField="RO_number__c"
            errors="{!v.errors}"
            hideCheckboxColumn="true"/>
</aura:component>	
/**
 * @name       : cmpFilteredRelatedListDTController.js
 * @category   : Lightning Component Controller
 * @description: Client side controller for displaying a filtered related list using lightning:datatable
 * @author     : Accletron Consulting 
 * @copyright  : Copyright © 2019 Accletron Consulting; All Rights Reserved
 */
({
    init : function(component, event, helper) {
        component.set("v.scolumns", [
            {label:'Name', fieldName: 'linkName', type: 'url', typeAttributes: {label: { fieldName: 'Name' }, target: '_blank'}},
            {label:"Service Order", fieldName:"RO_number__c", type:"text"},
            {label:"Serial Number", fieldName:"Serial_Number__c", type:"text"},
            {label:"Status", fieldName:"Status__c", type:"text"}
        ]);
        helper.getFilteredData(component);
    }
})
/**
 * @name       : cmpFilteredRelatedListDTHelper.js
 * @category   : Lightning Component Helper
 * @description: Client side helper  for displaying a filtered related list using lightning:datatable
 * @author     : Accletron Consulting 
 * @copyright  : Copyright © 2019 Accletron Consulting; All Rights Reserved
 */
({
    getFilteredData : function(component) {
        let action = component.get("c.getDraftRequestOrders");
        action.setParams({
            recordId: component.get("v.recordId")
        });

        action.setCallback(this, $A.getCallback(function (response) {
            let state = response.getState();

            if (state === "SUCCESS") {
                let records =response.getReturnValue();
                records.forEach(function(record){
                    record.linkName = '/'+record.Id;
                });        
                component.set('v.sdata', records);
            } else if (state === "ERROR") {
                let errors = response.getError();
                if (errors && Array.isArray(errors) && errors.length > 0){
                    component.set('v.errors',errors[0].message);
                    console.error(errors[0].message);
                }

            } else if (state === "INCOMPLETE") {
                console.error("INCOMPLETE");
            }
        }));
        $A.enqueueAction(action);
    }
})