0

I have LWC which was deployed almost 2 months before. Before WI 21 updates, it was working correctly but after installing critical updates, its not calling controller class methods from wire service. This issue is observed in all environments including production

As per below link, I have enabled Apex Class permission at profile level:

https://admin.salesforce.com/blog/2020/critical-update-ensure-users-have-access-to-auraenabled-methods

https://releasenotes.docs.salesforce.com/en-us/winter21/release-notes/rn_lc_apex_with_sharing_cruc.htm

but even after adding controller class to profile, LWC is still not working.

In browser console, I am observing below message:

beaconLib.BeaconLibrary.js:formatted:766 {InstrumentationResult : ( RECEIVED = 9 , SUCCESS -> LOG = 9 , Topic = AILTN ) , TracingResponse : ( AsyncResults ) , TelemetryResponse : ( AsyncResults ): {…}}

above message was never observed earlier. Problem is wired service is not even calling controller class method at all. There is no debug log I am getting.

In order to investigate the issue, instead of wired service, I am calling controller class method on a button(Imperatively) and its making server call. So it looks like Wired Service is not getting called again if I provide input from UI. It calls only once when page loads.

Code is mentioned on below link:

How to pass lightning-input-field value as a parameter to controller class method in Lightning Web Component

Below is modified JS where I added wired service which makes server call:

import {
        LightningElement,
        wire,
        track,
        api
    } from 'lwc';
    import {
        ShowToastEvent
    } from 'lightning/platformShowToastEvent';
    import refreshObjList from '@salesforce/apex/ReassignSObjectHelper.refreshObjList';
    
    export default class MassReassignSObjectParent extends LightningElement {
    
    
        @track items = []; //it contains all the records.
        @track sObjects; //data to be display in the table
        @track error;
        objType = '';
        owner = '';
        @wire(refreshObjList, {
        objType: '$objType',
        owner: '$owner'
    })
    wiredCallback(result) {
        console.log('Calling Wired'); // When Page loads. This gets called. but if I provide objType& owner from UI then wired does not call at all
        this.items = [];
        this.sObjects = '';
        //this.allSelectedRows = [];
        //this.assignRecords =[];
        this._wiredResult = '';
        this._wiredResult = result;
        _wiredResult
        console.log('Setting Wired Result Data' + this._wiredResult);
        if (result.data) {
            console.log('Result count' + result.length);
            //this.items = result.data;
            let nameUrl;
            let ownerText;
            let currentPage;
            this.items = result.data.map(row => {
                    /*I'm Commenting this part for now. as it display data in table based onm the result I want to see. This part is not commented in real. Wanted to show only Basic wire service which is not getting called at all.
                    nameUrl = `/${row.Id}`;
                    ownerText = `${row.Owner.Name}`;
                    currentPage = Math.ceil(recCount++/ this.pageSize);
                        return {
                            ...row,
                            nameUrl,
                            ownerText,
                            currentPage
                        }*/
                    }) 
                    this.totalRecountCount = this.items.length; 
                    console.log('Total Record Count:' + this.totalRecountCount); 
                    this.totalPage = Math.ceil(this.totalRecountCount / this.pageSize); 
                    console.log('Total Page to be displayed:' + this.totalPage);
                    this.page = 1;
                    this.startingRecord = 1;
                    this.sObjects = this.items.slice(0, this.pageSize);
                    this.endingRecord = this.pageSize;
                    clearInterval(this._interval);
                    console.log('Ending Record page size is:' + this.endingRecord);
                
                if (this.totalRecountCount == 0) {
                    //Display No Result Message when click on Serach Button after completing wire event
                    this.isServerCallComplete = true;
                }


            }
            else if (result.error) {
                this.items = undefined;
                
                this.dispatchEvent(
                    toastMessage('error', 'dismissable', 'Error', 'Exception Occured While Retrieving Records.Please check error logs for more details')
                );
            }
        }
    
        handlePickChange(event) {
            this.objType = event.target.value;
            console.log('objType:' + objType);
        }
        handleChange(event) {
            this.owner = event.target.value[0];
            console.log('owner:' + owner);
        }
        //this method is fired when retrieve records button is clicked
        handleSearchClick(event) {
    
            console.log('Clicikng on Search:');
            const val = event.detail.value;
            console.log('Search Val is:' + val);
            this.template.querySelectorAll('lightning-input-field').forEach(element => {
                console.log('Element is:' + element.detail);
                element.reportValidity();
            });
            if (this.items.length > 0) {
                this.sObjects = this.items.slice(0, this.pageSize);
                this.endingRecord = this.pageSize;
                console.log('Ending Record page size is:' + this.endingRecord);
                // this.sObjects = this.records;
            } else {
                console.log('No Results:' + this.isServerCallComplete);
                if (this.isServerCallComplete) {
                    console.log('Server Call Complete Displaying No Result Message');
                    
                    this.dispatchEvent(
                        toastMessage('info', 'dismissable', 'Search Result', 'No Records Found')
                    );
                }

            }
           /* Shift logic to wired service
           refreshObjList({
                    objType: objType,
                    owner: owner
                })
                .then(result => {
                    this.sObjects = result;
                })
                .catch(error => {
                    this.error = error;
                });*/
    
        }
    
            handleResetClick(event) {
                const inputFields = this.template.querySelectorAll(
                    'lightning-input-field'
                );
                if (inputFields) {
                    inputFields.forEach(field => {
                        field.reset();
                    });
                }
            }
    }

only changes I made in the code is instead of calling controller class method on button, I am using wired service here.Controller Class method is cacheable.

Has anyone observed the issue after critical updates for LWC?

6
  • @wire methods works in user context. can you please check and ensure that users have FLS on the fields and objects @wire methods are calling. – maniac coder Oct 19 '20 at 15:52
  • @maniaccoder FLS is correct on both fields an object. Problem is when I load components, wire service calls only once. But as soon as I pass parameter from UI, it does not get call. This did not happen earlier. Its not even calling controller class method even when page is loaded. – Dhananjay Patil Oct 19 '20 at 16:01
  • Is it consistent across other sandboxes? can you try to deduce to smaller version of code. like helloworld may be, which will help to understand is it SF issue or something is missed at your side. – Ysr Shk Oct 19 '20 at 16:35
  • Yes its consistent everywhere. below is the link where i posted code earlier when I was new in LWC.Instead of calling it on button(implicitly), I am using wire service now. so that based on input field selection, it displays results. Let me know if the code helps.I have removed with sharing from my controller class.Rest of the code is same salesforce.stackexchange.com/questions/310434/… – Dhananjay Patil Oct 19 '20 at 16:41
  • Can you check if Apex class permission is also available in the profiles ? releasenotes.docs.salesforce.com/en-us/winter20/release-notes/… – Nagendra Singh Oct 20 '20 at 6:51
1

You are probably facing a stale cache. When using wire property with apex methods, the wire property does not always do a server trip-

If an Apex method is marked with @AuraEnabled(cacheable=true), when it’s invoked imperatively or via @wire, a client-side Lightning Data Service cache is checked before issuing the network call to invoke the Apex method on the server. However, data provisioned by Apex is not managed by Lightning Data Service. If you use @wire to call an Apex method, to refresh stale data, call refreshApex().

To refresh Apex data provisioned via a wired Apex method, call refreshApex(). The function provisions the data using the configuration bound to the @wire and updates the cache.

When the wire service provisions data via a Lightning Data Service wire adapter like getRecord, it provisions new values when they’re available. However, when the wire service provisions data via an Apex method, it doesn’t provision new values, so you must call refreshApex().

Using refreshApex should resolve the issue - https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.apex

2
  • I use refreshApex when I update the data. Here I did not post the complete code but when Update the records, I use refreshApex to call wireService to update the fresh data. Just wanted to ask you what is you recommendation about defining variable with propert track objType, track owner which I did not define earlier? Can you please suggest about the variable scope? – Dhananjay Patil Oct 20 '20 at 12:00
  • instead of a property, you could use a setter/getter. When the setter is called, you can call refreshApex to get the latest data ( this will happen asynchronously, so use a spinner if you need to). – Nagen Sahu Oct 20 '20 at 12:03
0

Currently My Component in application is below:

<template>
    <lightning-card>
        <div class="slds slds-p-around--medium">
            <lightning-card>
                <div class="app slds-p-around_x-large">
                    <div class="slds-p-top--small slds-text-title">This screen allows you to transfer the records
                     </div>
                    <div class="slds-card__header slds-grid">
                        <div class="slds-card slds-m-around--medium">
                            <lightning-card variant="narrow" icon-name="standard:topic">
                                <h1 slot="title">Find records that match the following criteria</h1>
                            </lightning-card>
                        </div>
                    </div>
                </div>
            </lightning-card>
            <lightning-card>
                <lightning-record-edit-form object-api-name="Transfer_SObject_Record__c" onsuccess={handleSuccess}>
                    <div class="slds-m-around_medium">
                        <div class="slds-form-element">
                            <lightning-input-field field-name='Type__c' value={objType} onchange={handlePickChange}
                                required>
                            </lightning-input-field>
                        </div>
                        <div class="slds-form-element">
                            <lightning-input-field field-name='Owner__c' value={owner} onchange={handleChange} required>
                            </lightning-input-field>
                        </div>
                        <div class="slds-m-top_medium">
                            <lightning-button variant="brand" label="Search" title="Search" onclick={handleSearchClick}
                                class="slds-m-left_x-small">
                            </lightning-button>
                            <lightning-button variant="brand" label="Reset" title="Reset" onclick={handleResetClick}
                                class="slds-m-left_x-small">
                            </lightning-button>
                        </div>
                    </div>
                </lightning-record-edit-form>
            </lightning-card>
            <lightning-card>
                <template if:true={sObjects}>
                    <template for:each={sObjects} for:item="sObj">
                        <p key={sObj.Id}>{sObj.OwnerId}</p>
                    </template>
                </template>
                <template if:true={error}>
                    <!--   <c-error-panel errors={error}></c-error-panel> -->
                    {error}
                </template>
            </lightning-card>
        </div>
    </lightning-card>
</template>

JS:

import {
        LightningElement,
        wire,
        track,
        api
    } from 'lwc';
    import {
        ShowToastEvent
    } from 'lightning/platformShowToastEvent';
    import refreshObjList from '@salesforce/apex/ReassignSObjectHelper.refreshObjList';
    
    export default class MassReassignSObjectParent extends LightningElement {
    
    
        @track items = []; //it contains all the records.
        @track sObjects; //data to be display in the table
        @track error;
        @wire(refreshObjList, {
        objType: '$objType',
        owner: '$owner'
    })
    wiredCallback(result) {
        console.log('Calling Wired'); // When Page loads. This gets called. but if I provide objType& owner from UI then wired does not call at all
        this.items = [];
        this.sObjects = '';
        //this.allSelectedRows = [];
        //this.assignRecords =[];
        this._wiredResult = '';
        this._wiredResult = result;
        _wiredResult
        console.log('Setting Wired Result Data' + this._wiredResult);
        if (result.data) {
            console.log('Result count' + result.length);
            //this.items = result.data;
            let nameUrl;
            let ownerText;
            let currentPage;
            this.items = result.data.map(row => {
                    /*I'm Commenting this part for now. as it display data in table based onm the result I want to see. This part is not commented in real. Wanted to show only Basic wire service which is not getting called at all.
                    nameUrl = `/${row.Id}`;
                    ownerText = `${row.Owner.Name}`;
                    currentPage = Math.ceil(recCount++/ this.pageSize);
                        return {
                            ...row,
                            nameUrl,
                            ownerText,
                            currentPage
                        }*/
                    }) 
                    this.totalRecountCount = this.items.length; 
                    console.log('Total Record Count:' + this.totalRecountCount); 
                    this.totalPage = Math.ceil(this.totalRecountCount / this.pageSize); 
                    console.log('Total Page to be displayed:' + this.totalPage);
                    this.page = 1;
                    this.startingRecord = 1;
                    this.sObjects = this.items.slice(0, this.pageSize);
                    this.endingRecord = this.pageSize;
                    clearInterval(this._interval);
                    console.log('Ending Record page size is:' + this.endingRecord);
                
                if (this.totalRecountCount == 0) {
                    //Display No Result Message when click on Serach Button after completing wire event
                    this.isServerCallComplete = true;
                }


            }
            else if (result.error) {
                this.items = undefined;
                
                this.dispatchEvent(
                    toastMessage('error', 'dismissable', 'Error', 'Exception Occured While Retrieving Records.Please check error logs for more details')
                );
            }
        }
    
        handlePickChange(event) {
            this.objType = event.target.value;
            console.log('objType:' + objType);
        }
        handleChange(event) {
            this.owner = event.target.value[0];
            console.log('owner:' + owner);
        }
        //this method is fired when retrieve records button is clicked
        handleSearchClick(event) {
    
            console.log('Clicikng on Search:');
            const val = event.detail.value;
            console.log('Search Val is:' + val);
            this.template.querySelectorAll('lightning-input-field').forEach(element => {
                console.log('Element is:' + element.detail);
                element.reportValidity();
            });
            if (this.items.length > 0) {
                this.sObjects = this.items.slice(0, this.pageSize);
                this.endingRecord = this.pageSize;
                console.log('Ending Record page size is:' + this.endingRecord);
                // this.sObjects = this.records;
            } else {
                console.log('No Results:' + this.isServerCallComplete);
                if (this.isServerCallComplete) {
                    console.log('Server Call Complete Displaying No Result Message');
                    
                    this.dispatchEvent(
                        toastMessage('info', 'dismissable', 'Search Result', 'No Records Found')
                    );
                }

            }
           /* Shift logic to wired service
           refreshObjList({
                    objType: objType,
                    owner: owner
                })
                .then(result => {
                    this.sObjects = result;
                })
                .catch(error => {
                    this.error = error;
                });*/
    
        }
    
            handleResetClick(event) {
                const inputFields = this.template.querySelectorAll(
                    'lightning-input-field'
                );
                if (inputFields) {
                    inputFields.forEach(field => {
                        field.reset();
                    });
                }
            }
    }

If you can see above code, I have declared input type field value as objType & owner but in wire property, I am directly passing those values.

In my JS if declare those variable like @track objType & @track owner then it resolves my issue.

I am confused now because earlier before winter 21 release, this was working & wire service was getting called without defining variable in JS but now suddenly I am not sure what has been updated recently(at JS maybe) due to which I have mandatory declare those variable.

Can someone please help me here?

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.