• GCW Labs
  • NEWBIE
  • 4 Points
  • Member since 2016

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 1
    Questions
  • 8
    Replies
In LWC I'm rebuilding an array based on some filter parameters, and depending on the amount of data there is some lag. For example, set a filter, there is a delay of a couple seconds, then the filter value changes and the new list displays. I'm trying to show a spinner in these scenarios, but I need to hide the spinner after the array rerenders. There seems to be a catch-22 in how the renderedCallback() function works. Here are some examples. The HTML is always the same.

HTML

<template if:true={showSpinner}>
    <div class="slds-grid slds-grid_vertical-align-center slds-align_absolute-center" style="height:100%;">
        <lightning-spinner class="slds-is-relative"
                           alternative-text="Loading"
                           size="medium"
                           variant="brand">
        </lightning-spinner>
    </div>
</template>


<template if:false={showSpinner}>
    <template for:each={filteredRecords} for:item="rec">

              <!--display rec info here-->
    </template>
</template>


Example 1

allRecords = [];
filteredRecords = [];
showSpinner = false;

connectedCallback() {
    // set allRecords here;   
}

renderedCallback() {
   // renderedCallback runs once after a couple of seconds delay
}

handleFilterChange(event) {
   let filter = event.target.value;

   let tempRecords = [];

   for (let rec of allRecords) {
      if (rec.field === filter) {
         tempRecords.push(rec);
      }
   }

    this.filteredRecords = tempRecords;

}


Example 2

allRecords = [];
filteredRecords = [];
showSpinner = false;

filterRender = false;

connectedCallback() {
    // set allRecords here   
}

renderedCallback() {

   // renderedCallback runs twice, once immediately which turns off the spinner, and then again as in the first example after a couple of seconds when the list rerenders
   this.showSpinner = false;
}

handleFilterChange(event) {

   this.showSpinner = true;
   let filter = event.target.value;

   let tempRecords = [];

   for (let rec of allRecords) {
      if (rec.field === filter) {
         tempRecords.push(rec);
      }
   }

    this.filteredRecords = tempRecords;
}



Example 3

allRecords = [];
filteredRecords = [];
showSpinner = false;

filterRender = false;

connectedCallback() {
    // set allRecords here   
}

renderedCallback() {

   // renderedCallback runs twice again, but in the first run filterRender is already set to true, so again it turns off the spinner right away
   if (this.filterRender === true) {
      this.showSpinner = false;
      this.filterRender = false;
   }
}

handleFilterChange(event) {

   this.showSpinner = true;
   let filter = event.target.value;

   let tempRecords = [];

   for (let rec of allRecords) {
      if (rec.field === filter) {
         tempRecords.push(rec);
      }
   }



   this.filterRender = true;
   this.filteredRecords = tempRecords;
}



When renderedCallback runs seems to be arbitrary. When I’m not setting the spinner to false in renderedCallback() it runs once after a few seconds. If I do set the spinner, it runs twice but there is no way to flag the second run as the one in which the spinner should be disabled.

Note that if in all instances, the filteredList is already rebuilt, it’s just a delay as it’s rendered in the HTML file. So I can’t even check the status of the list to see if the spinner should be disabled.

 
Parent Component Html
<template>
<template if:true={overlayVisible}>
        <div class="overlay" id="overlay" onclick={closeNav}>
        </div>
    </template>
      <lightning-layout>
 <lightning-layout-item padding="around-small" class="frstRowLeft minPadding">
<span class="span-menu" onclick={openNav}><img src={menu} alt="Menu bar">
   </span>
     </lightning-layout-item>
</lightning layout>
<template if:true={navVisible}>
        <c-sidebar item={navVisible} overlay={overlayVisible}></c-sidebar>
    </template>
<template>
Parent Component JS
@api navVisible = false;
  @api overlayVisible = false;
openNav() {
        this.navVisible = true;
        this.overlayVisible = true;
    }
    closeNav() {
        this.navVisible = false;
        this.overlayVisible = false;
    }
when I click on image sidebar open then I navigate to another page when I navigate to another page i want to close the Sidebar but it is not it is navigating to another page successfully

child component Html
<li onclick={navigateCase}>
                <a href="#" onmouseover={chngToWhiteCase} onmouseout={chngToBlackCase}>
                    <template if:false={showWhiteCaseIcon}>
                        <div class="listImg"><img src={caseicbla} alt="Cases"></div><span>Cases</span>
                    </template>
                    <template if:true={showWhiteCaseIcon}>
                        <div class="listImg"><img src={caseicwht} alt="Cases"></div><span>Cases</span>
                    </template>
                </a>
            </li>
            <li>

Child Component JS
@api item;
  @api overlay;
navigateCase() {
        console.log('item value',this.item);
        console.log('overlay vale'+this.overlay);
        this[NavigationMixin.Navigate]({
            type: 'comm__namedPage',
            attributes: {
                pageName: 'casetab'
            },
        });
        this.overlay=false;
        this.item = false;
        console.log('item value',this.item);
        console.log('overlay vale'+this.overlay);
        this.template.querySelector("c-hrwdcommunityheader").closenav();
    }



 
Hi friends,

I am trying to deploy code to prod, but I am running into issues getting my test class to reference my code to provide the required coverage to deploy.  Can I please have some help?  When I run the test, it passes in Apex Test Execution, but the code coverage is still showing 0%.  It's like I'm missing something to connect the Test to the Class.

Apex Class
public class eVolveServiceRequestClass {

    public id eVolveServiceRequestId {get;set;}
    public List<ESR_Signing_Party__c> geteVolveServiceRequestComp(){
        List<ESR_Signing_Party__c> esp;
        esp = [SELECT Name__c, Phone__c, Email__c, Country__c, Time_Zone_PL__c FROM ESR_Signing_Party__c 
               WHERE eVolve_Service_Request__c =: eVolveServiceRequestId AND RecordTypeId =: '0122C00000091NsQAI'];
        return esp;
    }

}

Test Class
@isTest
private class TestEvolveServiceRequest {
    
    @isTest static void setupTestData()
    { 
        Account acc = new Account(
            Name = 'Test Account');
        insert acc;
        
        Contact con = new Contact(
            FirstName = 'Test', LastName = 'Contact', AccountId = acc.Id  );
        insert con;
        
        
        eVolve_Service_Request__c esr = new eVolve_Service_Request__c(
            Signing_Party_Type__c = 'Seller', Status__c = 'New', Contact_Name__c = con.Id, Signing_Date_Requested_Start__c = system.today()+5);
        insert esr;
        
        
        ESR_Signing_Party__c sp = new ESR_Signing_Party__c(Name__c = 'Test Party',
                                                           Phone__c = '123-456-7890', Email__c = 'test@email.com', 
                                                           Country__c = 'United States of America', State__c = 'TX',
                                                           Time_Zone_PL__c = 'Acre Time (UTC-5)', eVolve_Service_Request__c = esr.Id, RecordTypeId = '0122C00000091NsQAI');
        insert sp;
    }
    
    @isTest
    static void testcheckeVolveServiceRequestClass()
        
    {
        
        ESR_Signing_Party__c sp = [select id from ESR_Signing_Party__c where Phone__c = '123-456-7890'][0];
        
        try
        {
            insert   sp;
        }
        catch(Exception ex)
        {
            system.assert(ex.getMessage().contains('The ID is already attached to the record via GAB connector'));
        }
        
        
    }
}

Thank you in advance,
  • October 31, 2020
  • Like
  • 0
In LWC I'm rebuilding an array based on some filter parameters, and depending on the amount of data there is some lag. For example, set a filter, there is a delay of a couple seconds, then the filter value changes and the new list displays. I'm trying to show a spinner in these scenarios, but I need to hide the spinner after the array rerenders. There seems to be a catch-22 in how the renderedCallback() function works. Here are some examples. The HTML is always the same.

HTML

<template if:true={showSpinner}>
    <div class="slds-grid slds-grid_vertical-align-center slds-align_absolute-center" style="height:100%;">
        <lightning-spinner class="slds-is-relative"
                           alternative-text="Loading"
                           size="medium"
                           variant="brand">
        </lightning-spinner>
    </div>
</template>


<template if:false={showSpinner}>
    <template for:each={filteredRecords} for:item="rec">

              <!--display rec info here-->
    </template>
</template>


Example 1

allRecords = [];
filteredRecords = [];
showSpinner = false;

connectedCallback() {
    // set allRecords here;   
}

renderedCallback() {
   // renderedCallback runs once after a couple of seconds delay
}

handleFilterChange(event) {
   let filter = event.target.value;

   let tempRecords = [];

   for (let rec of allRecords) {
      if (rec.field === filter) {
         tempRecords.push(rec);
      }
   }

    this.filteredRecords = tempRecords;

}


Example 2

allRecords = [];
filteredRecords = [];
showSpinner = false;

filterRender = false;

connectedCallback() {
    // set allRecords here   
}

renderedCallback() {

   // renderedCallback runs twice, once immediately which turns off the spinner, and then again as in the first example after a couple of seconds when the list rerenders
   this.showSpinner = false;
}

handleFilterChange(event) {

   this.showSpinner = true;
   let filter = event.target.value;

   let tempRecords = [];

   for (let rec of allRecords) {
      if (rec.field === filter) {
         tempRecords.push(rec);
      }
   }

    this.filteredRecords = tempRecords;
}



Example 3

allRecords = [];
filteredRecords = [];
showSpinner = false;

filterRender = false;

connectedCallback() {
    // set allRecords here   
}

renderedCallback() {

   // renderedCallback runs twice again, but in the first run filterRender is already set to true, so again it turns off the spinner right away
   if (this.filterRender === true) {
      this.showSpinner = false;
      this.filterRender = false;
   }
}

handleFilterChange(event) {

   this.showSpinner = true;
   let filter = event.target.value;

   let tempRecords = [];

   for (let rec of allRecords) {
      if (rec.field === filter) {
         tempRecords.push(rec);
      }
   }



   this.filterRender = true;
   this.filteredRecords = tempRecords;
}



When renderedCallback runs seems to be arbitrary. When I’m not setting the spinner to false in renderedCallback() it runs once after a few seconds. If I do set the spinner, it runs twice but there is no way to flag the second run as the one in which the spinner should be disabled.

Note that if in all instances, the filteredList is already rebuilt, it’s just a delay as it’s rendered in the HTML file. So I can’t even check the status of the list to see if the spinner should be disabled.

 
I have a custom form which automatically computes and displays the total of three fields. This is specifically an edit form wherein upon load, current value of the SummaryText__c field must be displayed. Its value, however, must change depending on field change of each fields: Number1__cNumber2__c , Number3__c.

Upon loading the form, current value for SummaryText__c does not have any value. But when I change values of Number1__cNumber2__c and , Number3__c, the current sum is reflecting.

As my initial solution, I used connectedCallback() to assign value on the initial display for SummaryText__c field. The value being assigned came from the getter method which fetches the current SummaryText__c value.

I was hoping that this would resolve my issue, but there's still no value displaying for SummaryText__c field on load of the custom form.

How can I fix this?

Here are the current codes I am working on:

customItemEditFormLWC.js
import { LightningElement, track, api, wire } from 'lwc';
import { getRecord, getFieldValue } from 'lightning/uiRecordApi';
import SUMMARY_FIELD from '@salesforce/schema/CustomObj__c.SummaryText__c';

const fields = [SUMMARY_FIELD];

export default class customItemEditFormLWC extends LightningElement {
    @track summaryInt = 0;
    @track displaySum;
    

    @wire(getRecord, { recordId: '$recordId', fields })
    customRec;
    custSumInit
    num1Field = 0;
    num2Field = 0;
    num3Field = 0;

    connectedCallback() {
        this.displaySum = this.summaryInitialValue;
    }

    @api
    get summaryInitialValue() {
        this.custSumInit = getFieldValue(this.customRec.data, SUMMARY_FIELD)
        if(typeof this.custSumInit === "undefined")
        {
            this.custSumInit = '';
        }
        console.log('custSumInit value: ' + this.custSumInit);
        return this.custSumInit; 
    }

    handleNumber1Change(event) {
        this.num1Field = event.target.value;
        console.log('this.num1Field' + this.num1Field);
        this.computeSum();
        console.log('computeSum:' + this.computeSum());
    }

    handleNumber2Change(event) {
        this.num2Field = event.target.value;
        console.log('this.num2Field' + this.num2Field);
        this.computeSum();
        console.log('computeSum:' + this.computeSum());
    }

    handleNumber3Change(event) {
        this.num3Field = event.target.value;
        console.log('this.num3Field' + this.num3Field);
        this.computeSum();
        console.log('computeSum:' + this.computeSum());
    }

    computeSum() {                      
        this.summaryInt = (parseInt(this.num1Field) || 0) + (parseInt(this.num2Field) || 0) + (parseInt(this.num3Field) || 0)                                                         
        console.log('this.summaryInt' + this.summaryInt); 
        var summaryText = '';                                                 
        summaryText = this.summaryInt;
        if(this.summaryInt !== null) {
            this.displaySum = summaryText + ' ' + 'Item';
            console.log('this.displaySum' + this.displaySum);
        }                           
        else {
            this.displaySum = '0 Item'; 
        }
        this.customRec.SummaryText__c = this.displaySum;
        console.log('this.customRec.SummaryText__c' + this.customRec.SummaryText__c); 
        return this.summaryInt;
    }

}
customItemEditFormLWC.html
<template>   
    <lightning-record-edit-form object-api-name="CustomObj__c" record-id={recordId} onsuccess={handleSuccess}>
        <lightning-messages></lightning-messages>
        <div class="slds-grid slds-wrap"> 
            <div class="slds-col slds-size_2-of-2">     
                <lightning-input-field field-name="Number1__c" onchange={handleNumber1Change}>
                </lightning-input-field>
            </div> 
            <div class="slds-col slds-size_2-of-2">     
                <lightning-input-field field-name="Number2__c" onchange={handleNumber2Change}>
                </lightning-input-field>
            </div>  
            <div class="slds-col slds-size_2-of-2">     
                <lightning-input-field field-name="Number3__c" onchange={handleNumber3Change}>
                </lightning-input-field>
            </div>  
            <div class="slds-col slds-size_2-of-2">
                <label>Item Summary</label>
                <div>{displaySum}</div>
        </div> 
        </div>  
    </lightning-record-edit-form>  
</template>


 

I am creating a trigger which upon creation of a lead, searches for any contacts with a matching email, and if found - convert the lead, and set the ContactId on the lead. I am just having some trouble figuring out how to create a map, I think it should be <LeadId, ContactId> and then pass this to the Database.leadconvert class to set the contactId.
Forgive me for my code - admin trying to be a dev. Thank you for any help!

trigger convertLead on Lead (before insert) {

    Set<String> formLeads = new Set<String>();
    // Loop through leads, store in set when FORM == TRUE
    for(Lead l : Trigger.New) {
        if(l.Form_Submission_ADMIN_USE_ONLY__c == True) {
            l.Description = 'Trigger ran';
            formLeads.add(l.email);  
        }      
    }  

    // List of contacts - Select contacts when email IN emailstocompare
    List<Contact> matchingCons = [SELECT Id, Email FROM Contact 
                                    WHERE Email IN :formLeads];
    // Add cons to set
    Set<Id> conIds = new Set<Id>();
    // loop through contacts, add to set 
    for(Contact cons:matchingCons) {
        conIds.add(cons.Id);
    }

    /* START Convert Lead Stuff */
    LeadStatus convertStatus = [SELECT MasterLabel FROM LeadStatus 
                                WHERE IsConverted = true LIMIT 1];
    List<Database.LeadConvert> leadsConvert = new List<Database.LeadConvert>();
    /* END Convert Lead Stuff */

    // if lead and contact match
    if(conIds.size()>0) {

        Map<Id, Set<Id>> leadtoConvert = new Map<Id, Set<Id>>();
        // construct map lead id to contact id - set in SetContactId method
        for(Lead l : Trigger.New) {
            leadtoConvert.put(l.Id, conIds);

            // convert lead
            Database.LeadConvert lc = new Database.leadConvert();
            lc.setLeadId(l.Id);
            lc.setConvertedStatus(convertStatus.Masterlabel);
            lc.SetContactId(leadtoConvert.get(l.Id));

            database.LeadConvertResult lcr = Database.convertLead(lc); 
            System.assert(lcr.isSuccess());
        }


    }       

    // loop through contacts, do update

}
 

 

In my sample LWC page, I replicated the standard Edit button in Case object, then placed it inside a modal. Record update working so far, but I notice that footer containing Cancel and Save buttons are not fixed. Every time I scroll the custom form, footer also moves with it which is kind of weird.

I placed the footer outside lightning-record-edit-form but Save button is no longer working. I tried to put it back again inside the tag, and it works. Looks like it works only inside it. I really want to maximize update feature of lightning-record-edit-form.

Is there any way wherein I can place it inside lightning-record-edit-form and still achieve a fixed modal footer?

HTML file
<template>

    <div class="slds-theme_default">
    <template if:true={displayModal}>  
    <div class="edit-modal" style="height: 640px;">  
    <section role="dialog" tabindex="-1" aria-labelledby="modal-heading-01" aria-modal="true" aria-describedby="modal-content-id-1" class="slds-modal slds-fade-in-open slds-modal_medium">      
    <div class="slds-modal__container"> 
    <header class="slds-modal__header">
        <button class="slds-button slds-button_icon slds-modal__close slds-button_icon-inverse" title="Close" onclick={closeModal}>
            <lightning-icon icon-name="utility:close" size="medium"></lightning-icon>
            <span class="slds-assistive-text">Close</span>
        </button>
        <h2 id="modal-heading-01" class="slds-text-heading_medium slds-hyphenate">edit record</h2>
    </header>        
    <div class="slds-modal__content slds-var-p-around_medium" id="modal-content-id-1">
        <lightning-record-edit-form object-api-name="Case" 
                                    onsuccess={handleSuccess}
                                    record-id={recordId}>

           
            <div class="slds-grid slds-wrap"> 
                <div class="slds-col slds-size_1-of-2">                             
                    <lightning-input-field field-name="AccountId"> 
                    </lightning-input-field> 
                </div> 
                <div class="slds-col slds-size_1-of-2"> 
                    <lightning-input-field field-name="Status"> 
                    </lightning-input-field> 
                </div> 
                <div class="slds-col slds-size_1-of-2">                             
                    <lightning-input-field field-name="Type"> 
                    </lightning-input-field> 
                </div> 
                <div class="slds-col slds-size_1-of-2">                             
                    <lightning-input-field field-name="Origin"> 
                    </lightning-input-field> 
                </div>
                //....and other fields...didn't include, quite long

            </div>      
            <lightning-button class="slds-var-m-top_small" 
                              type="submit" 
                              label="Update"> 
                            </lightning-button>                           

        </lightning-record-edit-form>
    </div>
    </div>    
    </section>    
    </div>
    </template>    
    </div>
</template>

JS FILE
import { LightningElement, track, api } from 'lwc'; 
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
 
export default class CaseEditPage extends LightningElement { 
 
    @api recordId; 
    @track displayModal = true; 

    handleSuccess( event ) { 
         
        const toastEvent = new ShowToastEvent({ 
            title: 'Case Updated', 
            message: 'Case Updated Successfully!!!', 
            variant: 'success' 
        }); 
        this.dispatchEvent( toastEvent ); 
 
    }

}

 
I am attempting to pass an object to a child component onclick, however, the result is always an empty object. 

My parent component is pulling a custom list from apex and returning an array of objects. I am iterating through the list and setting each iteration with a data attribute "data-lead". 
 
<template>
    <div data-card="birthdayCard" class="sectionCard cardClosed">
        <div class="sectionHeader" onclick={toggleView}>
            <p class="sectionTitle">Birthdays</p>
        </div>
            <div data-id="birthdaySection" class="slds-m-around_medium main drop-down closed">
                    <template for:each={viewableLeads} for:item="lead">
                        <div key={lead.id} class="previewHeadline" data-lead={lead} onclick={selectLead}>
                            <p class="leadItem">{lead.Name} <span class="sectionName">Birthday</span></p>
                            <div class="subInfo">8/04/1994 - Closed on 4/5/12</div>
                        </div>
                    </template>
                    <template if:false={max}>
                        <p class="btn loadMoreButton" onclick={loadMore}>Load More</p> 
                    </template>
            </div>
            <div>
                <c-lead-details selected-item={currentLead}></c-lead-details>
            </div>
    </div>
</template>
I then have my JS controller
import { LightningElement, wire , track} from 'lwc';
import getbdayopps from '@salesforce/apex/WorkdayAura.getbdayopps';

export default class bData extends LightningElement{
    bdayLeads
    closed = true
    count = 9
    @track max = false
    size 
    @track viewableLeads
    @track error
    @track currentLead = {}
    constructor(){
        super()
        getbdayopps()
        .then(result => {
            this.bdayLeads = result
            this.viewableLeads = result.slice(0,this.count)
            this.size = result.length
        })
        .catch(err => {
            this.bdayLeads = undefined
        })


    }

    loadMore(){
        this.count += 10
        this.viewableLeads = this.bdayLeads.slice(0,this.count);
        if(this.count >= this.size){
            this.max = true;
        }
    }

    toggleView(evt){
        let birthday = this.template.querySelector(JSON.parse(JSON.stringify('[data-id="birthdaySection"]')))
        let card = this.template.querySelector(JSON.parse(JSON.stringify('[data-card="birthdayCard"]')))
        let classList = birthday.classList.value.split(" ")

        if(classList.includes('closed')){
            birthday.classList.remove("closed")
            card.classList.remove("cardClosed")
            this.closed = false
        }else{
            birthday.classList.add("closed")
            card.classList.add("cardClosed")
            this.closed = true
        }
    }
    
    selectLead(event){
        this.currentLead = event.target.dataset.lead
    }

    
}
finally, the child component.
import { LightningElement, api } from "lwc";

export default class ChildDynamicRecordForm extends LightningElement {
  @api selectedItem;
 
}
So on click, i am triggering "selectLead" which sets the variable currentLead to event.target.dataset.lead, which should be the object. however the child component is only receiving an empty object. Im not sure if im doing this incorrectly, but any help would be greatly appreciated.