Project: Components That Talk to Each Other
By the end of this lesson, you'll be able to:
- Combine @api and CustomEvent to build a working parent/child component set
- Wire a list component and a detail component together through a shared parent
- Apply the immutable update pattern to keep the whole system correctly reactive
Prerequisites: "Sibling Communication with Lightning Message Service"
What We're Building
Three components working together:
contactManager— the parent, holding the list of contacts and the currently selected one.contactList— a child that receives the full contact array via@apiand dispatches aselectevent when a row is clicked.contactDetail— a child that receives the selected contact via@apiand displays it.
Building contactList.js
import { LightningElement, api } from 'lwc';
export default class ContactList extends LightningElement {
@api contacts;
handleRowClick(event) {
const selectedId = event.currentTarget.dataset.id;
this.dispatchEvent(new CustomEvent('select', { detail: selectedId }));
}
}
<template>
<template for:each={contacts} for:item="contact">
<p key={contact.Id} data-id={contact.Id} onclick={handleRowClick}>
{contact.Name}
</p>
</template>
</template>
Building contactDetail.js
import { LightningElement, api } from 'lwc';
export default class ContactDetail extends LightningElement {
@api contact;
}
<template>
<template if:true={contact}>
<p>{contact.Name}</p>
<p>{contact.Email}</p>
</template>
<template if:false={contact}>
<p>Select a contact to see details.</p>
</template>
</template>
Wiring It Together in contactManager.js
import { LightningElement } from 'lwc';
export default class ContactManager extends LightningElement {
contacts = [
{ Id: '1', Name: 'Ada Lovelace', Email: 'ada@example.com' },
{ Id: '2', Name: 'Grace Hopper', Email: 'grace@example.com' },
];
selectedContact;
handleSelect(event) {
const selectedId = event.detail;
this.selectedContact = this.contacts.find(c => c.Id === selectedId);
}
}
<template>
<c-contact-list contacts={contacts} onselect={handleSelect}></c-contact-list>
<c-contact-detail contact={selectedContact}></c-contact-detail>
</template>
Data flows down from the parent to contactList via @api contacts, a click fires a select CustomEvent back up, the parent finds the matching record and passes it down to contactDetail — the complete loop this whole module has been building toward.
Exercise
Trace the data flow, as a comment: when a user clicks a contact row, list every step from that click to contactDetail showing the right contact.
Show hint
Follow the event up, then the data back down.
Exercise
Challenge: extend contactManager so contacts is initially empty and a "Load Contacts" button populates it. Describe, without full code, what changes and why the update remains reactive.
Show hint
Think about how the array gets replaced, not mutated.
Project: Components That Talk to Each Other Quiz
My Notes
Log in to keep private notes on this lesson.
Questions about this lesson
No questions yet — be the first to ask.
Log in to ask a question about this lesson.
Summary
A hands-on capstone combining everything this module covers: a Contact Manager parent coordinating a Contact List child (passing data down) and a Contact Detail child (receiving a selection back up).