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?

1 Answer 1

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

2
  • 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.
    Commented Jun 3, 2019 at 0:19
  • Hi @S.B I've edited my answer, have it a look
    – dibocor
    Commented Jun 3, 2019 at 1:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .