1

Getting my feet wet in Lightning Web Components, and I'm trying to follow the developer guide, but I'm completely drawing a blank on how contact data is populated with @api contact;

I deployed the following to my source org: https://github.com/trailheadapps/lwc-recipes/tree/master/force-app/main/default/lwc/contactListItem

HTML:

<!-- contactListItem.html -->
<template>
    <a href="#" onclick={selectHandler}>
        <lightning-layout vertical-align="center">
            <lightning-layout-item>
                <img src={contact.Picture__c}></img>
            </lightning-layout-item>
            <lightning-layout-item padding="around-small">
                <p>{contact.Name}</p>
            </lightning-layout-item>
        </lightning-layout>
    </a>
</template>

JS:

// contactListItem.js
import { LightningElement, api } from 'lwc';

export default class ContactListItem extends LightningElement {
    @api contact;

    selectHandler(event) {
        // Prevents the anchor element from navigating to a URL.
        event.preventDefault();

        // Creates the event with the contact ID data.
        const selectedEvent = new CustomEvent('selected', { detail: this.contact.Id });

        // Dispatches the event.
        this.dispatchEvent(selectedEvent);
    }
}

ERROR:

afterRender threw an error in 'c:contactListItem' [Cannot read property 'Name' of undefined]

Searching for additional documentation, I keep getting returned Salesforce API documentation...

Any resource recommendations?

4

This lwc is called in the eventWithData lwc. Here it is:

the html file

<template>
    <lightning-card title="EventWithData" icon-name="standard:logging">
        <template if:true={contacts.data}>
            <lightning-layout class="slds-m-around_medium">
                <lightning-layout-item>
                    <!-- c-contact-list-item emits a non-bubbling event so each element must have a listener-->
                    <template for:each={contacts.data} for:item="contact">
                        <c-contact-list-item
                            key={contact.Id}
                            contact={contact}
                            onselect={handleSelect}
                        ></c-contact-list-item>
                    </template>
                </lightning-layout-item>
                <lightning-layout-item class="slds-m-left_medium">
                    <template if:true={selectedContact}>
                        <img
                            src={selectedContact.Picture__c}
                            alt="Profile photo"
                        />
                        <p>{selectedContact.Name}</p>
                        <p>{selectedContact.Title}</p>
                        <p>
                            <lightning-formatted-phone
                                value={selectedContact.Phone}
                            ></lightning-formatted-phone>
                        </p>
                        <p>
                            <lightning-formatted-email
                                value={selectedContact.Email}
                            ></lightning-formatted-email>
                        </p>
                    </template>
                </lightning-layout-item>
            </lightning-layout>
        </template>
        <template if:true={contacts.error}>
            <c-error-panel errors={contacts.error}></c-error-panel>
        </template>
        <c-view-source source="lwc/eventWithData" slot="footer">
            Child-to-parent communication using a custom event that passes data
            to the parent component. Click an item in the list to see the recipe
            in action.
        </c-view-source>
    </lightning-card>
</template>

the js file

import { LightningElement, wire, track } from 'lwc';
import getContactList from '@salesforce/apex/ContactController.getContactList';

export default class EventWithData extends LightningElement {
    @track selectedContact;

    @wire(getContactList) contacts;

    handleSelect(event) {
        const contactId = event.detail;
        this.selectedContact = this.contacts.data.find(
            contact => contact.Id === contactId
        );
    }
}

this snippet of the eventWithData lwc below shows how the public attribute (@contact) is populated.

<template for:each={contacts.data} for:item="contact">
     <c-contact-list-item
           key={contact.Id}
           contact={contact}
           onselect={handleSelect}>
     </c-contact-list-item>
</template>

as you can see, for each iteration over the list(contacts.data), contact={contact} updates the public proprety due to the one way binding. That is possible because a parent component has access to the public attributes of its child components.

Hope that is helpful

  • While I appreciate your answer, this doesn't answer my question at all, so I'm not sure why this is getting upvotes, unless I am missing something... my question is in regards to a different example on the same page... and revolves particularly around @api contact, which this answer does not address at all. – S.B. Jun 3 at 0:19
  • Hi @S.B I've edited my answer, have it a look – dibocor Jun 3 at 1:40

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.