[SalesForce] Bind a property from a controller – LWC

I recently started to work with LWC, I want to bind a certain field from the controller and use it in my component

My LWC is on the Case object, I have a controller which returns an array of related email messages. What I want to do is to use the 'Incoming' field on my component:

import { LightningElement, api, track, wire } from 'lwc';
import getAllEmailsForRecord from '@salesforce/apex/getRelatedEmails.getAllEmailsForRecord'; 

export default class ShowRelatedRecords extends LightningElement {
    @api recordId;
    @track record;
    @track error;

    @wire(getAllEmailsForRecord, { caseId: '$recordId' }) 
    emails; 

    get incoming() {
        return this.emails.data.fields.Incoming.value;
    }
}

Html:

<template for:each={emails.data} for:item="email">
<lightning-layout-item key={email.Id} size="12">
<div  class="slds-p-around_x-small" >
   <lightning-badge label={incoming}></lightning-badge>
</div>
....

Controller:

public without sharing class getRelatedEmails {
@AuraEnabled(Cacheable=true)
    public static EmailMessage[] getAllEmailsForRecord(Id caseId){
        return [SELECT Id,TextBody, IsExternallyVisible ,Subject,FromAddress,ToAddress,Incoming FROM EmailMessage WHERE ParentId = : caseId];
    }  
}

The result is that the LWC does not load and when I open the chrome debugger I see the following error:

Error: Uncaught (in promise) TypeError: Cannot read property 'Incoming' of
undefined
at i.get incoming [as incoming]

Best Answer

You are in a loop <template for:each={emails.data} for:item="email"> which means below is how you need to access data for an instance of the record in the data array. Here email is the indidual record attribute which you have declared through for:item="email

 <lightning-badge label={email.Incoming}></lightning-badge>

You are trying to run an expression function on a list of records this.emails.data.fields.Incoming.value but data your data is an array so you need to access specific node of array inside the template if

Solution 2:

Create a child component and put all the contents inside for loop there

Child Component markup:

<template>
    <p>{email.TextBody}</p>
    <div  class="slds-p-around_x-small" >
        <lightning-badge label={incoming}></lightning-badge>
     </div>
</template>

JS File:

import { LightningElement,api} from 'lwc';

    export default class EmailRecord extends LightningElement {
        @api email;
        get incoming() {
            return this.email.Incoming;
        }   

    }

In the parent component where you are getting data change the markup(html template like this) where c-email-record is your child component

<template>

<template for:each={emails.data} for:item="email">
    <lightning-layout-item key={email.Id} size="12">
    <c-email-record email={email}></c-email-record>
    </lightning-layout-item>
</template>    
</template>

within this child component js you can do whatever manipulation of data you want to and then show the UI accordingly

Related Topic