4

contactRelatedListLWC.js

import { LightningElement, track,api } from 'lwc';
import getContactListApex  from '@salesforce/apex/ContactController.getContacts';
const columns = [
    { label: 'First Name', fieldName: 'FirstName' }
];

export default class ContactRelatedListLWC extends LightningElement {
    @track data = [{'FirstName' : 'John'}];
    @track columns = columns;

    connectedCallback() {
        this.getContactListJS();
    }

    getContactListJS(){
        getContactListApex().then(result => {
            [].concat(result).forEach((obj) => {
                let tempContactObj = {};
                tempContactObj.FirstName = obj.FirstName + 'aaa';
                this.data.push(tempContactObj);
                console.log(this.data.length); //This prints the actual length as expected but only one record displayed in the UI.
            });
        }).catch(error => {
            this.error = error;
        });
    }    
}

Apex class:

public class ContactController {

    @AuraEnabled
    public static List<Contact> getContacts(){
        return [SELECT Id,FirstName FROM Contact LIMIT 5];
    } 
}

contactRelatedListLWC.html:

<template>
    <div style="height: 300px;">
        <lightning-datatable
            key-field="FirstName"
            data={data}
            columns={columns}>
        </lightning-datatable>
    </div>
</template>

I am querying contacts in Apex controller and passing the value to LWC and in LWC, I am changing firstname and appending with some dummy text.

Records returned from Server are not displayed but only the record that I hard-coded in JS is displayed.

What is wrong with my approach here?

NOTE: My question might seem like a duplicate to this (How to change wired data list after get data from imperative apex method) but I have gone through it and this question is not about changing the value of response returned from Server call.

6

Currently lightning datatable has a bug - it does not rerender data when an object in the array data changes or by using push to modify data, so you need to explicitly reassign data for datatable to rerender. For better understanding you can check this playground link

Try below:

getContactListJS() {
    getContactListApex().then(result => {
        this.data = [...result].map(record => {
            record.FirstName = record.FirstName + 'aaa';
            return record;
        });
    }).catch(error => {
        this.error = error;
    });
}
2

To add to @salesforce-sas's answer, I'm not sure I would classify this as a bug in datatable, per se, but rather how LWC's tracked and api properties work in general. If you have an object or array as a property and you only update the content then LWC doesn't notice the changes and does not trigger re-rendering (or wire calls etc.).

There are two different solutions to this, depending on the use case:

  1. Explicitly replace the tracked or api property value, as is the case in salesforce-sas's answer, with the updated content
  2. If you are using an object (not an array - so this doesn't apply in this question's scenario) then you can explicitly initialize the object in its declaration so the nested properties to be tracked (or made "reactive") are enumerated. By doing the latter you inform the LWC compiler that you want changes to the declared nested properties (and only those ones) to be considered as reactive.

The first solution, which is applicable here, has been covered in the previous answer. The second solution (relevant in other use cases) looks like the following.

In the LWC, declare the tracked/api property with dummy object containing the reactive sub-properties:

@track
data = {
    example1: undefined,
    example2: "some default"
}

In the update code just assign to the sub-properties:

this.data.example1 = result.data.something;

Use of the this.data property or its content elsewhere, such as in the template or in parameters to wired services etc. will then operate as you expect. On the other hand, if you omit the initialization with a dummy (or miss out explicit declaration of a sub-property in that dummy in the property declaration) then the component won't react to changes to the relevant sub-properties within this property. Of course, you can always fall back on solution 1.

  • 1
    It is actually a bug only, Salesforce core support has accepted it and working to resolve it. Pls check the playground link I gave in my answer and see that although html is rerendered, datable does not. Go to js and uncomment a line by checking comment and then even datatable starts rerendering – salesforce-sas Sep 25 at 10:39
  • Thanks for posting the other possible solution. – javanoob Sep 25 at 12:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.