function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
David Bradburn UKDavid Bradburn UK 

LWC Related List Inline Editing with Dynamic Columns

I hope you can help. I'm wanting to create a LWC that uses the Datatable component with Inline Editing. but which get's the columns to display from the Lightning Page Parameters in the JS.Meta file Properties.

For instance, the Properties will have a field for inputting the fields we want to display in the related list in a comma deliminated fashion, and the passes these fields into the component / a dynamic piece of soql to be used in the Edtiable List.

All of the examples i have found have statically declared columns like below. But i really want these to be defined in the Lightning Builder Page so the component can be re-used on multiple objects and with different fields etc:

CLASS:
public with sharing class ContactController {

    @AuraEnabled(cacheable=true)
    public static List<Contact> getContactList() {
        return [SELECT Id, FirstName, LastName, Title, Phone, Email FROM Contact LIMIT 10];
    }
}

HTML: 
<template>
    <lightning-card title="Datatable Example" icon-name="custom:custom63">

        <div class="slds-m-around_medium">
            <template if:true={contact.data}>
                <lightning-datatable
                    key-field="Id"
                    data={contact.data}
                    columns={columns}
                    onsave={handleSave}
                    draft-values={draftValues}>
                </lightning-datatable>
            </template>
            <template if:true={contact.error}>
                <!-- handle Apex error -->
            </template>
        </div>
    </lightning-card>
</template>

JS: 
import { LightningElement, wire, track } from 'lwc';
import getContactList from '@salesforce/apex/ContactController.getContactList';
import { updateRecord } from 'lightning/uiRecordApi';
import { refreshApex } from '@salesforce/apex';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import FIRSTNAME_FIELD from '@salesforce/schema/Contact.FirstName';
import LASTNAME_FIELD from '@salesforce/schema/Contact.LastName';
import ID_FIELD from '@salesforce/schema/Contact.Id';


const COLS = [
    { label: 'First Name', fieldName: 'FirstName', editable: true },
    { label: 'Last Name', fieldName: 'LastName', editable: true },
    { label: 'Title', fieldName: 'Title' },
    { label: 'Phone', fieldName: 'Phone', type: 'phone' },
    { label: 'Email', fieldName: 'Email', type: 'email' }
];
export default class DatatableUpdateExample extends LightningElement {

    @track error;
    @track columns = COLS;
    @track draftValues = [];

    @wire(getContactList)
    contact;

    handleSave(event) {

        const fields = {};
        fields[ID_FIELD.fieldApiName] = event.detail.draftValues[0].Id;
        fields[FIRSTNAME_FIELD.fieldApiName] = event.detail.draftValues[0].FirstName;
        fields[LASTNAME_FIELD.fieldApiName] = event.detail.draftValues[0].LastName;

        const recordInput = {fields};

        updateRecord(recordInput)
        .then(() => {
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Success',
                    message: 'Contact updated',
                    variant: 'success'
                })
            );
            // Clear all draft values
            this.draftValues = [];

            // Display fresh data in the datatable
            return refreshApex(this.contact);
        }).catch(error => {
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Error creating record',
                    message: error.body.message,
                    variant: 'error'
                })
            );
        });
    }
}

Thanks in advance!!
David Bradburn UKDavid Bradburn UK
Ideally, i'd like to declare the Obkject and Fields etc in the JS-Meta file, like below. And have these pass into the class / JS etc: 
<?xml version="1.0" encoding="UTF-8"?>  
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="EditableRelatedList">  
    <apiVersion>45.0</apiVersion>  
    <isExposed>true</isExposed>  
    <targets>  
        <target>lightning__RecordPage</target>  
    </targets>  
    <targetConfigs>  
        <!-- Component UI Properties -->
        <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="parentFieldAPIName" type="String" label="Parent Field API Name" description="Enter the parent field API Name"/>  
            <property name="whereClause" type="String" label="WHERE Clause" description="Enter your WHERE clause (Not Required). Do not include 'WHERE'. Eg: firstName = 'David' AND lastName != 'Bradbury'"/> 
            <property name="fields" type="String" label="Fields" description="Enter the API Names of the fields you would like to use in this Related List seperated by a comma. Eg: FirstName, LastName, CustomField1__c, CustomField2__c "/> 
            <property name="errorMessage" type="String" label="Error Message" description="Enter your Error Message for when there are 0 records"/>
        </targetConfig>  
    </targetConfigs>  
</LightningComponentBundle>
Cheers!
 
ekansh parnamiekansh parnami
create a custom metadata type , put the comma seprated field names in record . import that metadata in your lwc component in .xml file like-
<targetConfigs>
        <targetConfig targets="lightning__HomePage, lightning__AppPage, lightning__RecordPage">
            <property name="metadataName" type="String" placeholder="Sobject Configuration Metadata Unique Name"/>
        </targetConfig>
get the values from wire method to apex call and by soql get the return values . use $metadataName to pass it to apex
JS-

@track tableCoulmn=[];
@wire(getsObjectInfo, { metadataName: '$metadataName' , filterList:null})
    results({ error, data }) {
        if (data) {
            
            for(var a of data.coulmns ){
                let coulmn= {label: a, value: a};
                this.tableCoulmn.push(coulmn);
            }
            } else if (error) {
            this.error = error;
            
        }

HTML - 
<template>
<div class={flexipageRegionWidth}>
            <lightning-datatable 
            key-field="Id" 
            data={tableData} 
            columns={columns}
            max-row-selection="1"
            resize-column-disabled>
        </lightning-datatable>
        </div>
<template>

apex- 
DataUpdateUISetting__mdt sobjectConfig = [SELECT Parent_Object__r.Custom_Filter_Setting__c,
                                                        Parent_Object__r.Fields_To_Display__c,
                                                        Parent_Object__r.SobjectAPIName__c,
                                                        Parent_Object__r.Where_Clause__c,
                                                        Parent_Object__r.Show_Edit_Button__c,
                                                        Parent_Object__r.Custom_Filter_Setting__r.Filter_Fields_To_Display__c,
                                                        Child_Object_1__r.Fields_To_Display__c,
                                                        Child_Object_1__r.SobjectAPIName__c,
                                                        Child_Object_1__r.Where_Clause__c 
                                                        FROM DataUpdateUISetting__mdt
                                                        WHERE DeveloperName =: metadataName];