Refresh a Related List and Record Page using getRecordNotifyChange in Lightning Web Component | LWC Stack ☁️⚡️


In this blog you will learn to update the record page and related list using getRecordNotifyChange(recordIds). 

Fetch record updates for the specified record IDs and refresh the Lightning Data Service cache, providing your wires with the latest record data. Call this function to notify Lightning Data Service that a record has changed outside its mechanisms, such as via imperative Apex or Visualforce, or by calling User Interface API via a third-party framework.

To ensure that getRecordNotifyChange() is called after the record update via Apex, use the async/await pattern or a Promise chain.

#getRecordNotifyChange #uiRecordApi #LWC

I have created a custom data table with inline editing for contacts and while updating the contacts I am calling getRecordNotifyChange(recordIds) to update the data in the related lists as well. 


Benefits of using getRecordNotifyChange(recordIds)

  • Update list of record Ids you've updated.
  • It will only refresh records you ask for instead of complete page like force:refreshView event.
  • Better performance.
  • Faster as compare to the force:refreshView AURA event.
Note : One thing which I feel is missing in it, it will not bring new records to the local cache. For example if you've create a new record so using force:refreshView you may refresh the whole page and get the new records also in the related list but using getRecordNotifyChange() you can just update existing records in the related list.
Hopefully it will have that update also in upcoming releases. 

HTML
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<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
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import { LightningElement, wire, api } from "lwc";
import getContacts from "@salesforce/apex/ContactController.getContacts";
import { refreshApex } from "@salesforce/apex";
import { ShowToastEvent } from "lightning/platformShowToastEvent";
import updateContacts from "@salesforce/apex/ContactController.updateContacts";
import { getRecordNotifyChange } from "lightning/uiRecordApi";

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 ContactsForAccount extends LightningElement {
  @api recordId;
  columns = COLS;
  draftValues = [];

  @wire(getContacts, { accId: "$recordId" })
  contact;

  async handleSave(event) {
    const updatedFields = event.detail.draftValues;

    // Prepare the record IDs for getRecordNotifyChange()
    const notifyChangeIds = updatedFields.map((row) => {
      return { recordId: row.Id };
    });
    console.log("###RecordIds : " + JSON.stringify(notifyChangeIds));
    try {
      // Pass edited fields to the updateContacts Apex controller
      const result = await updateContacts({ data: updatedFields });
      console.log(JSON.stringify("Apex update result: " + result));
      this.dispatchEvent(
        new ShowToastEvent({
          title: "Success",
          message: "Contact updated",
          variant: "success"
        })
      );

      // Refresh LDS cache and wires
      getRecordNotifyChange(notifyChangeIds);

      // Display fresh data in the datatable
      refreshApex(this.contact).then(() => {
        // Clear all draft values in the datatable
        this.draftValues = [];
      });
    } catch (error) {
      console.log("###Error : " + JSON.stringify(error));
    }
  }
}


Apex
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public with sharing class ContactController {
   @AuraEnabled(cacheable=true)
    public static Contact getSingleContact() {
        return [
            SELECT Id, FirstName, LastName, Title, Phone, Email
            FROM Contact
            WITH SECURITY_ENFORCED
            LIMIT 1
        ];
    }
    @AuraEnabled(cacheable=true)
    public static List<Contact> getContacts(String accId) {
        return [
            SELECT AccountId, Id, FirstName, LastName, Title, Phone, Email
            FROM Contact
            WHERE AccountId = :accId
            WITH SECURITY_ENFORCED
        ];
    }
    @AuraEnabled
    public static string updateContacts(Object data) {
    List<Contact> contactsForUpdate = (List<Contact>) JSON.deserialize(
         JSON.serialize(data),
         List<Contact>.class
    );
    try {
        update contactsForUpdate;
        return 'Success: contacts updated successfully';
    }
    catch (Exception e) {
        return 'The following exception has occurred: ' + e.getMessage();
    }
}
}


Output


Checkout complete video tutorial below

 If you have any question please leave a comment below.

If you would like to add something to this post please leave a comment below.
Share this blog with your friends if you find it helpful somehow !

Thanks
Happy Coding :)

Post a Comment

1 Comments

  1. Hello, thanks for the videos! Is this required if it's not a related record? If I have a simple custom object, create the record with a lightning component. The child component should only render the values, when the status of the record has been updated to completed. Do I need to use getRecordNotifyChange?

    ReplyDelete