1

I have a requirement where I need to dynamically format datatables inside tabs defined by a custom object used to assist in formatting my LWC component.

My component has a wire function that calls a function in my Apex Controller to retrieve basic information for setting up the component. This includes details such as the current record and data from the custom object that I am using to support my component. Below is the wire function.
Note:

  • data.documentsByTabMap is an Apex map, and data.documentsByTabMap[tabName] retrieves the map value indexed by the tab name. This map defines the tabs I need to render in my component, and the value determines which documents are inserted in the datatable for that tab.
  • documentForDatatable define one row of the datatable
  • objectFormatted is an object where I save the data from the datatable and the data returned by Apex. Although they are almost the same, not all data from the backend is saved in the datatable content.
@wire(setupComponent, {pId: '$recordId'})
formatDatatable({data, error}) {
    this.loading = true;
    if(data) {
        this.recordData = data.recordData;
        this.SObjectName = data.SObjectName;

        let documentIdToBeReplaced = 0;

        // format datatable for each tab
        for(let tabName in data.documentsByTabMap) {
            let documentListToConstruct = [];
            documentListToConstruct = data.documentsByTabMap[tabName];

            let dataForDatatable = [];
            for(let i = 0; i < documentListToConstruct.length; i++) {
                const documentForDatatable = {
                    // we don't have documentId at this point, but we need it to be the key-field on
                    // datatable component. We will replace this value when get the document from backend
                    documentId: String(documentIdToBeReplaced),
                    type      : documentListToConstruct[i].document.Nome_documento__c,
                    origin    : documentListToConstruct[i].documentOrigin,
                    status    : 'Unavailable',
                };

                documentIdToBeReplaced++;

                dataForDatatable.push(documentForDatatable);
            }

            const objectFormatted = {
                datatableContent: dataForDatatable,
                returnFromBack  : documentListToConstruct,
                key             : tabName
            }

            this.documentsByTabMap.push(objectFormatted);
        }

        this.getDocumentListFromBack();
    }
}

After that, I call an integration with another system to populate my datatable. Here is how I populate it. It's important to note that this process is working, but the datatable on the first tab doesn't show the data. When I use console.log on its datatable content, the data is present. The other tabs render without any problems.

    getDocumentListFromBack() {
        getDocumentList({
            pId           : this.recordId,
            pSObjectName  : this.SObjectName
        })
        .then((result) => {
            if(result.documentListToReturn.length === 0 && result.message.variant !== 'error') {
                this.documentListToShow = undefined;
                this.integrationDocumentsResult = undefined;
                this.sendMessage('There is no documents for this record.', '', 'info', 'sticky');

                return;
            }

            for(const forVersionedDocumentList of result.documentListToReturn) {
                let documentFind = false;
                const lastDocumentVersion = forVersionedDocumentList[forVersionedDocumentList.length - 1];

                // search on documentsByTabMap for a document that his type is equal than the document returned
                for(const forComponentTab of this.documentsByTabMap) {
                    for(const forDocumentOnDatatable of forComponentTab.datatableContent) {
                        if(forDocumentOnDatatable.type !== lastDocumentVersion.displayType) continue;

                        // if it's a document that don't need to be versioned and already
                        // has one entry for them it's created a new document with his info
                        if(notVersionedDocuments.includes(lastDocumentVersion.documentType)
                        && forDocumentOnDatatable.status === 'Available') {
                            const newDocumentOnDatatable = {
                                description      : lastDocumentVersion.metadata.description,
                                documentId       : lastDocumentVersion.documentId,
                                lastModifiedDate : lastDocumentVersion.creationDate,
                                modifiedBy       : lastDocumentVersion.metadata.modifiedBy,
                                name             : lastDocumentVersion.documentName,
                                origin           : forDocumentOnDatatable.origin,
                                presignedUrl     : forDocumentOnDatatable.presignedUrl,
                                status           : 'Available',
                                type             : forDocumentOnDatatable.type,
                                version          : 1,
                            };

                            forComponentTab.datatableContent.push(newDocumentOnDatatable);

                        } else {
                            forDocumentOnDatatable.description      = lastDocumentVersion.metadata.description;
                            forDocumentOnDatatable.documentId       = lastDocumentVersion.documentId;
                            forDocumentOnDatatable.lastModifiedDate = lastDocumentVersion.creationDate;
                            forDocumentOnDatatable.modifiedBy       = lastDocumentVersion.metadata.modifiedBy;
                            forDocumentOnDatatable.name             = lastDocumentVersion.documentName;
                            forDocumentOnDatatable.presignedUrl     = lastDocumentVersion.presignedUrl,
                            forDocumentOnDatatable.status           = 'Available';
                            forDocumentOnDatatable.version          = forVersionedDocumentList.length;
                        }

                        documentFind = true;

                        break;
                    }

                    console.log(forComponentTab.datatableContent);

                    if(documentFind) break;
                }
            }

            this.sendMessage(result.message.title, result.message.message, result.message.variant, result.message.mode);
        })
        .catch((error) => {
            this.sendMessage('An unexpected error occurred.', error.body.message, 'error', 'sticky');
        })
        .then(() => this.loading = false);
    }

Also there is my HTML code

            <lightning-tabset>
                <template lwc:if={documentsByTabMap} for:each={documentsByTabMap} for:item="forTab">
                    <lightning-tab label={forTab.key} key={forTab.key} value={forTab.key}>
                        <lightning-datatable
                            data={forTab.datatableContent}
                            columns={columns}
                            key-field="documentId"
                            hide-checkbox-column
                            onrowaction={handleRowAction}
                            default-sort-direction="asc"
                            sorted-direction={sortDirection}
                            sorted-by={sortedBy}
                            onsort={onHandleSort}
                            wrap-text-max-lines="3"
                        >
                        </lightning-datatable>
                    </lightning-tab>
                </template>
            </lightning-tabset>

Finally, here are the results for the component, the interface, and the console log. This is the result for the first tab. Please note that in the console, you can see that the status for the "Matrícula" document type (please ignore the name, it's in Portuguese and not relevant in this case) should be "Available," but in the UI, it is displayed as "Unavailable". component result for frist tab

Here is the result for the second tab. As you can see, it works as expected, with all documents having an Available status. component result for second tab

If something is unclear, please feel free to ask. I understand there's a lot of information, and I might not have explained everything clearly.

3
  • Hey, not sure, but the second key (documentId) in the first data table is 1 - not a string. Could you try making it "1"? Oct 30, 2023 at 17:18
  • Fixed, thank you Felix Oct 30, 2023 at 17:33
  • Yes, this worked! I put it as a response of my question but i can't mark it as a answer yet. Thanks! Oct 31, 2023 at 11:14

1 Answer 1

1

I follow the solution on answer of this question and it works for me

How to convey LWC's complex Reactive property back to markup?

Not the answer you're looking for? Browse other questions tagged .