1

I am trying to get my @wire getRelatedListRecords to refresh when insert a Contact related to an Account. Currently when I insert a new Contact, my wire method does not return the new record to be displayed. I have tried both getRecordNotifyChange and refreshApex and neither seem to make a difference. Also it seems like refreshApex is being deprecated for non-apex usage (https://help.salesforce.com/s/articleView?id=release-notes.rn_lwc_modules.htm&type=5&release=238). Here is my code:

wireTest.html

<template>
    <lightning-card title="wireGetRelatedListRecords">
        <template if:true={records}>
            <div class="slds-m-around_medium">
                <template for:each={records} for:item="rec">
                    <p key={rec.fields.Id.value}>
                        {rec.fields.Name.value}
                    </p>
                </template>
            </div>
        </template>
    </lightning-card>
    <c-wire-test-child child-callback={onResult}></c-wire-test-child>
</template>

wireTest.js

import { LightningElement, wire, track } from 'lwc';
import { getRelatedListRecords } from 'lightning/uiRelatedListApi';
import { refreshApex } from '@salesforce/apex';

export default class WireTest extends LightningElement {
    
    error;
    @track records = [];
    @track contactData;

    @wire(getRelatedListRecords, {
        parentRecordId: '00100000000000000',
        relatedListId: 'Contacts',
        fields: ['Contact.Name','Contact.Id'],
        sortBy: ['Contact.Name']
    })listInfo(result) {
        this.contactData = result;
        if (result.data) {
            this.records = result.data.records;
            this.error = undefined;
        } else if (result.error) {
            this.error = result.error;
            this.records = undefined;
        }
    }

    onResult = () => {
        console.log('am I getting here');
        refreshApex(this.contactData);
        console.log('should have called refreshApex');
    }
}

wireTestChild.html

<template>
    <lightning-button variant="brand" label="Insert Contact" title="Insert Contact" onclick={btnClick}></lightning-button>   
</template>

wireTestChild.js

import { LightningElement, api, wire } from 'lwc';
import {
    getRecordCreateDefaults,
    generateRecordInputForCreate,
    createRecord,
    getRecordNotifyChange
} from 'lightning/uiRecordApi';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import CONTACT_OBJECT from '@salesforce/schema/Contact';

export default class WireTestChild extends LightningElement {
    @api childCallback;
    contRecordInput;
    contactId;

    @wire(getRecordCreateDefaults, { objectApiName: CONTACT_OBJECT })
    contactCreateDefaults;

    recordInputForCreate() {
        if (!this.contactCreateDefaults.data) {
            return undefined;
        }

        const contactObjectInfo = this.contactCreateDefaults.data.objectInfos[
            CONTACT_OBJECT.objectApiName
        ];
        const recordDefaults = this.contactCreateDefaults.data.record;
        const recordInput = generateRecordInputForCreate(
            recordDefaults,
            contactObjectInfo
        );
        return recordInput;
    }

    btnClick()
    {
        this.contRecordInput = this.recordInputForCreate();

        this.contRecordInput.fields.FirstName = 'Fooey';
        this.contRecordInput.fields.LastName = 'Test';
        this.contRecordInput.fields.AccountId = '001000000000000';
        this.contRecordInput.fields.Email = '[email protected]';
        this.contRecordInput.fields.LeadSource = 'LeadSource';

        createRecord(this.contRecordInput)
            .then(contact => {
                this.childCallback();
                this.contactId = contact.id;
                // I am assuming to notify the Account Id since that's where I am grabbing the related records
                //getRecordNotifyChange([{recordId: '001000000000000'}]);
                this.dispatchEvent(
                    new ShowToastEvent({
                        title: 'Success',
                        message: 'Contact created',
                        variant: 'success',
                    }),
                );
            })
            .catch(error => {
                this.dispatchEvent(
                    new ShowToastEvent({
                        title: 'Error creating record',
                        message: error.body.message,
                        variant: 'error',
                    }),
                );
            });
    }
}
22
  • 1
    Does this answer your question? How to refresh wired service getRecord manually?
    – Phil W
    Jul 20, 2022 at 21:11
  • 3
    @PhilW I have updated. Also I am reading that refreshApex is deprecated for any non-apex usage (help.salesforce.com/s/…) Jul 21, 2022 at 12:42
  • 1
    This looks right to me. Sorry, someone else needs to chip in at this point. Maybe there's an issue with the uiRelatedListApi?
    – Phil W
    Jul 21, 2022 at 13:28
  • 1
    I checked with the product team and unfortunately, I don't have any good solution to share as of Summer '22. There's a "refresh view" module that may be in pilot in Winter '23 (forward-looking statement). It may address this is use case.
    – POZ
    Jul 27, 2022 at 15:20
  • 1
    Seems like you need your own apex method at least in the short term...
    – Phil W
    Jul 28, 2022 at 19:11

2 Answers 2

4

Starting from Spring '23 you now have access to the RefreshView API (Beta) that allows to cover this exact use case.

We've shared a basic example of the Refresh API in our LWC Recipes sample app (see Refresh View tab).

Back to your original question, you could write the following code. Note that these two components no longer need to be parent/child thanks to the Refresh API. They could be two different Lightning App Builder components.

wireTest.html

<template>
    <lightning-card title="wireGetRelatedListRecords">
        <template lwc:if={records}>
            <div class="slds-m-around_medium">
                <template for:each={records} for:item="rec">
                    <p key={rec.fields.Id.value}>{rec.fields.Name.value}</p>
                </template>
                <template lwc:if={hasNoRecords}>
                    <p>No records found</p>
                </template>
            </div>
        </template>
    </lightning-card>
</template>

wireTest.js

import { LightningElement, wire } from 'lwc';
import { getRelatedListRecords } from 'lightning/uiRelatedListApi';
import { refreshApex } from '@salesforce/apex';
import {
    registerRefreshHandler,
    unregisterRefreshHandler
} from 'lightning/refresh';

export default class WireRefreshList extends LightningElement {
    error;
    records = [];
    contactData;
    refreshHandlerID;

    connectedCallback() {
        this.refreshHandlerID = registerRefreshHandler(
            this,
            this.refreshHandler
        );
    }

    disconnectedCallback() {
        unregisterRefreshHandler(this.refreshHandlerID);
    }

    refreshHandler() {
        refreshApex(this.contactData);
    }

    @wire(getRelatedListRecords, {
        parentRecordId: '0017d00001IwY00AAF',
        relatedListId: 'Contacts',
        fields: ['Contact.Name', 'Contact.Id'],
        sortBy: ['Contact.Name']
    })
    listInfo(result) {
        this.contactData = result;
        if (result.data) {
            this.records = result.data.records;
            this.error = undefined;
        } else if (result.error) {
            this.error = result.error;
            this.records = undefined;
        }
    }

    get hasNoRecords() {
        return this.records?.length === 0;
    }
}

wireTestChild.html

<template>
    <lightning-card title="wireRefreshAction">
        <div class="slds-var-m-horizontal_medium">
            <lightning-button
                label="Insert Contact"
                title="Insert Contact"
                onclick={btnClick}
            ></lightning-button>
        </div>
    </lightning-card>
</template>

wireTestChild.js

import { LightningElement, wire } from 'lwc';
import {
    getRecordCreateDefaults,
    generateRecordInputForCreate,
    createRecord
} from 'lightning/uiRecordApi';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import CONTACT_OBJECT from '@salesforce/schema/Contact';
import { RefreshEvent } from 'lightning/refresh';

export default class WireRefreshButton extends LightningElement {
    contRecordInput;
    contactId;

    @wire(getRecordCreateDefaults, { objectApiName: CONTACT_OBJECT })
    contactCreateDefaults;

    recordInputForCreate() {
        if (!this.contactCreateDefaults.data) {
            return undefined;
        }

        const contactObjectInfo =
            this.contactCreateDefaults.data.objectInfos[
                CONTACT_OBJECT.objectApiName
            ];
        const recordDefaults = this.contactCreateDefaults.data.record;
        const recordInput = generateRecordInputForCreate(
            recordDefaults,
            contactObjectInfo
        );
        return recordInput;
    }

    btnClick() {
        this.contRecordInput = this.recordInputForCreate();

        this.contRecordInput.fields.FirstName = 'Fooey';
        this.contRecordInput.fields.LastName = 'Test';
        this.contRecordInput.fields.AccountId = '0017d00001IwY00AAF';
        this.contRecordInput.fields.Email = '[email protected]';
        this.contRecordInput.fields.LeadSource = 'LeadSource';

        createRecord(this.contRecordInput)
            .then((contact) => {
                this.dispatchEvent(new RefreshEvent());
                this.contactId = contact.id;

                this.dispatchEvent(
                    new ShowToastEvent({
                        title: 'Success',
                        message: 'Contact created',
                        variant: 'success'
                    })
                );
            })
            .catch((error) => {
                this.dispatchEvent(
                    new ShowToastEvent({
                        title: 'Error creating record',
                        message: error.body.message,
                        variant: 'error'
                    })
                );
            });
    }
}
8
  • Thank you for sharing this @POZ can't wait to try it out Feb 14, 2023 at 15:27
  • @POZ I'm trying to implement RefreshView API where the refresh event needs to be published from an Aura component and the event needs to be handled by an LWC. I'm pretty sure that I've got the LWC set up correctly to handle the event, but when I take the action that should trigger the event getting published I'm finding that I'm not hitting the handler in my LWC. I think it's likely that there's something wrong on the firing side. This is what I'm trying from the Aura component: this.dispatchEvent(new RefreshEvent()); Mar 30, 2023 at 16:46
  • That's great news! I was able to try it out with the above code. I couldn't find 'Refresh View' in the latest LWC Recipes though, in the installed app or in github. Have I missed it somewhere?
    – MikeA
    Apr 22, 2023 at 11:18
  • 1
    @MikeA this would the "DispatchRefreshEvent" recipe under the the "Refresh View" tab (sorry, the name is not obvious).
    – POZ
    May 2, 2023 at 13:25
  • 1
    @POZ I think I know what the issue is, without LWS enabled you need to do things differently for the RefreshView API with Winter24 - help.salesforce.com/s/…
    – Tony White
    Sep 17, 2023 at 22:29
0

Example from @POZ didn't work for me without returning Promise from the refresh handler. I.e. it should be

refreshHandler() {
    return refreshApex(this.contactData);
}

You must log in to answer this question.

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