[SalesForce] Dynamic Column and Data in lwc Datatable

I need to display a wrapper in LWC Datatable. One of the attributes of the wrapper is sObject. I'll basically pass the object name and field name to display in the data table dynamically. Based on the fields name, I need to display them as columns.

Example: I can pass the fields of Accounts or Contact and the record will be assigned to the sObject variable. Now I need to display my data in datatable.

Wrapper:

public class SubmittedRecordsWrapper{
        @AuraEnabled public String comments;
        @AuraEnabled public sobject rec;
    }

HTML:

    @track columns = [{
                label: 'Comment',
                fieldName: 'comments',
                type: 'text',
                initialWidth: 290,
                wrapText: true,
                editable: true
            },
            {
                label: 'Name',
                fieldName: 'rec.Name',
                type: 'text',
                initialWidth: 290,
                wrapText: true,
                editable: false
            },
{
                label: 'Custom Field',
                fieldName: 'rec.Custom__c',
                type: 'text',
                initialWidth: 290,
                wrapText: true,
                editable: false
            }]

In the console log, I can see the data. I know I need to flatten the data. But I'm not sure how can I flatten it dynamically

Best Answer

AFAIK, the . (or merge syntax) is not recognized in the fieldName property. To solve your problem (i.e., to flatten out the data), you should use map or forEach methods of JS array (or any other functional JS methods) to loop through the array (i.e. the data received from apex call) and create a new array as per your requirement. Check out this & this. Google search would provide you with a lot of code examples of these JS methods.


If you are clear about the format in which the data is expected by the lighting data table, you can skip reading this below content. Otherwise, read the following:

If the data table's column definition is defined as follows:

columns = [
        { label: 'Comment', fieldName: 'comments'   },
        { label: 'Name', fieldName: 'Name' },
        { label: 'Custom Field', fieldName: 'Custom__c' }
    ]

Then, the data is expected in the following format:

data = [
    {
        id: 'a',
        comments: 'Comment1',
        Name: 'Name1',
        Custom__c: 'Test1'
    },
    {
        id: 'b',
        comments: 'Comment2',
        Name: 'Name2',
        Custom__c: 'Test2'
    }
]

The key point to note here is the 1-on-1 exact mapping between fieldName property in the column definition and the key attribute in each of the object element of JS array data. [id: 'a', comments: 'Comment1' etc. are key-value pairs within each object element, where id, comments represent the key.]. This mapping is the utmost basic requirement for the lightning data table, based on which it gets constructed and rendered.

Now, when apex method is called (imperatively or via wire adapter) from the lightning web component, the result is received as JS array of objects. Something similar to the format shown below.

(3) [{...}, {...}, {...}]
 0: {comments: "a", rec: { Name: "10", Custom__c: 'Test1'}}
 1: {comments: "b", rec: { Name: "20", Custom__c: 'Test2'}}
 2: {comments: "c", rec: { Name: "30", Custom__c: 'Test3'}}
  length: 3

Please note that this is only a possible format based on the assumptions made from the details in your post. Depending on how you are returning the data to the component, the data structure could be a bit more complex than the above mentioned. As mentioned earlier in this answer, you may use the functional JS methods on this array to get the required format of data.

Related Topic