[SalesForce] Flatten data to display it using lightning datatable in LWC

My wrapper class returns sObjects of type account and contact along with other fields, to my LWC. I am not able to display the data using lightning datatable as something like fieldName:'AccountId.Name' does not work.

I don't want to change the apex class or add any static javascript resource. I understand that I have to flatten the data but I am not sure how and where to do it in my code. I referred this and this solution but it's for lighting component and not LWC. Please guide. Thanks!


Data

Data


Javascript

const actions = [
    { label: 'View', name: 'view' },
    { label: 'Edit', name: 'edit' },
    { label: 'Delete', name: 'delete' },
];

const columns = [
    {
        type: 'action',
        typeAttributes: { rowActions: actions },
    },
    { label: 'Name', fieldName: 'AccountId.Name', type: 'text' },
    //{ label: 'Api Name', type: 'button', typeAttributes: { label:  {fieldName: 'apiName'}, variant: 'base' } },
    { label: 'AccountName', fieldName: 'Name', type: 'text' },
    { label: 'Role', fieldName: 'ContactRole', type: 'text' },
    { label: 'IsPrimary', fieldName: 'IsPrimary', type: 'boolean', editable: 'true' },
    { label: 'MDM ID', fieldName: 'MDM_ID', type: 'text' },
];


export default class ContactRelatedAccount extends NavigationMixin(LightningElement) {
    @api recordId;
    @track columns = columns;
    @track addresses;
    @track record = [];
    refreshTable;
    res;

    @wire(getAddress, { LeadID: '$recordId' }) wired(result) {
        this.refreshTable = result;
        if (result.data) {
            this.addresses = result.data;
        }
        if (result.error) {
            this.error = result.error;
        }
    }
}

Best Answer

you can prepare data before passing it to lightning-datatable

@wire(getAddress, { LeadID: '$recordId' }) wired(result) {
    this.refreshTable = result;
    if (result.data) {
        this.addresses = result.data.map((elem) => ({
                ...elem,
                ...{
                    'Account_Id': elem.AccountId.Id,
                    'Account_Name': elem.AccountId.Name,
                    'Contact_Id': elem.ContactID.Id,
                    'Contact_Name': elem.ContactID.Name,
                    'Contact_Title': elem.ContactID.Title
                    // and so on for other fields
                }
        }));
    }
    if (result.error) {
        this.error = result.error;
    }
}

after that set column with names of fields from result.data.map function

const columns = [
    {
        type: 'action',
        typeAttributes: { rowActions: actions },
    },
    { label: 'Account Id', fieldName: 'Account_Id', type: 'text' },
    { label: 'Account Name', fieldName: 'Account_Name', type: 'text' },
    { label: 'Contact Id', fieldName: 'Contact_Id', type: 'text' },
    { label: 'Contact Name', fieldName: 'Contact_Name', type: 'text' },
    { label: 'Contact Title', fieldName: 'Contact_Title', type: 'text' }
];