1

I have a wired function in an LWC that populates an array (records) on success returning an address for each array value.

@wire(searchSomething, { searchSomething: '$searchObject'})  
   wiredContacts({ error, data }) {  
     this.noRecordsFlag = 0;  
     if(this.searchObject.businessName != ''){
        if (data) {  
            console.log('----Result Lookup---- ', JSON.stringify(data))
          this.records = data; 
          this.showOptions = this.records.length == 0 ? false : true;  
        } else if (error) {  

          console.log('----error--- ', JSON.stringify(error));
          this.error = error;
        }  
      }
   } 

On the template I have:

<template if:true={records}>  
      <div class="slds-box custom-spacing">
        <template for:each={records} for:item="record"> 
          
            <div key={record.businessName} data-id={record.businessName} class="options-padding" onclick={handlelookupselect}>
              {record.businessName}</div>
        </template>  
      </div>
    </template>  

I have been asked to display the full address of the business. Now I can easily do that by doing something like:

<template if:true={records}>  
      <div class="slds-box custom-spacing">
        <template for:each={records} for:item="record"> 
          
            <div key={record.businessName} data-id={record.businessName} class="options-padding" onclick={handlelookupselect}>
              {record.businessName} {record.city} {record.state} {record.country}</div>
        </template>  
      </div>
    </template>  

But I would like to handle that in a getter since the business could be in U.S. or Europe and I may have to display the state or not depending on where the business and I dont want to muddy up my HTML with conditionals and one does not seem to have expressions in LWC templates.

Being new to LWC, I would ideally like to do something like:

<template if:true={records}>  
      <div class="slds-box custom-spacing">
        <template for:each={records} for:item="record"> 
          
            <div key={record.businessName} data-id={record.businessName} class="options-padding" onclick={handlelookupselect}>
              {record.businessNameAndAddress}</div>
        </template>  
      </div>
    </template>

Where businessNameAndAddress would have the name of the business along with the address with the logic of having state value or not already computed in JS.

Would the getter need to loop through the array, concatenate the business with address, and then add that to a new field to each row?

For example:

 @api
    get businessNameAndAddress(){
        this.records.forEach(function (element) {

if (element.country = 'USA'){
  element.businessNameAndAddress = element.businessName +', '+element.city+', '+element.state+' '+element.country;
}
else{
element.businessNameAndAddress = element.businessName +', '+element.city+' '+element.country;
}

});
    }

Is this the best way?

  • 2
    Looping though the array and adding the computed value as a new field in each row should be the right way to do it. However, instead of trying to use getter, do it in the wired function itself. – arut Sep 29 at 3:51
  • The wire's return will be a read-only value. As such you can't add stuff to these objects. I recommend you create a 'wrapper' object with two properties, the record (as 'details') and the businessNameAndAddress, and store these in the 'this.records' array instead. Any current use of 'record' would be replaced by 'record.details' and you would access the business name and address using 'record.businessNameAndAddress'. I 100% agree you should do this in the wire's handler function, wiredContacts. – Phil W Sep 29 at 7:38
4

The results of a wire are always read-only. You either have to clone the data or you need to use a wrapper. For simplicitly, I recommend using a wrapper in this case.

You can create the wrapper instances in the wire handler function, like:

@wire(searchSomething, { searchSomething: '$searchObject'})  
   wiredContacts({ error, data }) {  
     this.noRecordsFlag = 0;  
     if(this.searchObject.businessName != ''){
        if (data) {  
            console.log('----Result Lookup---- ', JSON.stringify(data))
          this.records = data.map(record => {
              return {
                  details: record,
                  businessNameAndAddress: getBusinessNameAndAddress(record)
          }); 
          this.showOptions = this.records.length == 0 ? false : true;  
        } else if (error) {  
          console.log('----error--- ', JSON.stringify(error));
          this.error = error;
        }  
      }
   } 

Now all you have to do is update your template to replace use of 'record' with 'record.details', and to access the address using 'record.businessNameAndAddress':

<template if:true={records}>  
    <div class="slds-box custom-spacing">
        <template for:each={records} for:item="record"> 
            <div key={record.details.businessName} data-id={record.details.businessName} class="options-padding" onclick={handlelookupselect}>
              {record.businessNameAndAddress}</div>
        </template>  
    </div>
</template>
| improve this answer | |

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.