How to pass data from parent to child in lwc
Topics
In order to reuse the modularity in lightning web components, develoeprs create reusable components. These components can be used inside other components.
When a component is embeded in another component, the embeded component become a child component and the embedding component acts like a parent component.
A parent component parent can :
- Set public properties on child components
- Call methods on child components
- Listen for any events fired by the child components
A child component parent can :
- Read, but not change, public properties in parent components
- Call methods on parent components
- Listen for some, but not necessarily all, events bubbled up by components that it contains.
How to pass data from parent to child in lwc
There are two ways you can pass data from parent to child in lightning web components(lwc). The first and most preferred way is to pass the value as attribute from the parent component. The second method is by using javascript to set the public property on the child component.
1. Pass data from parent to child by using HTML attributes
To pass data from a parent component to a child component in lwc:
- Define a public property in the child component, e.g. @api name
- Reference the public property as attribute in the parent component to pass data to child.
A sample code for passing data from parent to child in lwc is given below.
//Parent.html
<template>
<c-child-component name="Decodeforce"></c-child-component>
</template>
//ChildComponent.js
import { LightningElement,api } from 'lwc';
export default class ChildComponent extends LightningElement {
@api name;
}
Note : You may explore lwc:spread if you are passing multiple parameters from parent to child in lwc.
2. Pass data from parent to child using public property on child
To set a value on a child element using JavaScript, first, find the child component using the query selector, then set its public variable.
Below is a JavaScript function that sets the "name" property, as demonstrated in the previous example.
//ParentComponent.js
import { LightningElement, api } from 'lwc';
export default class ParentComponent extends LightningElement {
handleUpdateChild(){
template.querySelector('c-child-component').name = 'Decodeforce';
}
}
Calling methods on child from parent
To invoke a method on child from parent, declare the javascript method on the child component with @api decorator (public property).
In our previous example, to set the name property on the child component from the parent component.
- Define a method in the child component with @api property
- Query the child component instance by template.querySelector('component-name')
- Invoke the method on the child component instance from parent
How to pass data from child to parent using custom events
Use custom events to send data from child to parent components in lwc. LWC uses browsers native event mechanisam to send data.
To send data via custom event:
- Define a custom event in the child component
- Dispatch the event from child component
- Parent event can handle the event using oneventname attributes in the html
Create and dispatch custom event in child component
Define a javascript method to handle the onclick event from a button. The javascript method to create and dispatch custom event.
//ChildComponent.html
<template>
<button onclick={handleSendMessage}>Send Message</button>
</template>
// childComponent.js
import { LightningElementm, api } from 'lwc';
@api name;
export default class ChildComponent extends LightningElement {
handleSendMessage() {
const eventDetail = { message: 'Hello from Child!' };
const customEvent = new CustomEvent('message', { detail: eventDetail });
this.dispatchEvent(customEvent);
}
}
Handle events in parent component
In the parent component, listen to the event from the child and handle them in the onEventName javascript method.
//parentComponent.html
<template>
<c-child-component onmessage={handleMessage}></c-child-component>
<p>{messageFromChild}</p>
</template>
//parentComponent.js
import { LightningElement, track } from 'lwc';
export default class ParentComponent extends LightningElement {
messageFromChild = '';
handleMessage(event) {
this.messageFromChild = event.detail.message;
}
}
A practical example - Shopping cart
Let's consider a simple scenario of a shopping cart where we have a parent component representing the shopping cart and a child component representing individual items in the cart.
The parent component is a container for shopping cart and it display the total price of all items in the cart.
The child component is the contained component that display the individual item with quantity, description and price. The child component gets its data from the parent component.
Sample code
1. shoppingCart (Parent component)
//shoppingCart.html
<template>
<h1>Your cart</h1>
<hr/>
<c-shopping-cart-item
cart-items={cartItems}>
</c-shopping-cart-item>
<p>Total : $ {totalPrice}</p>
<template>
//shoppingCart.js
import { LightningElement } from 'lwc';
export default class ShoppingCart extends LightningElement {
cartItems = [ { "name": "Item 1", "quantity": 2, "price": 15, "id": "item1" }, { "name": "Item 2", "quantity": 1, "price": 50, "id": "item2" } ];
get totalPrice(){
let totalPrice = 0;
this.cartItems.forEach((item) => {
totalPrice += item.price;
});
return totalPrice;
}
}
2. shoppingCartItem (Child component)
//shoppingCartItem.html
<template>
<template for:each={cartItems} for:item="item">
<div class="slds-grid slds-gutters" key={item.id}>
<div class="slds-col">
<span class="slds-p-around_xx-small">{item.quantity}</span>
<span class="slds-p-around_xx-small">x</span>
<span class="slds-p-around_xx-small">{item.name}</span>
</div>
<div class="slds-col">
<span>$ {item.price}</span>
</div>
</div>
</template>
</template>
//shoppingCartItem.js
import { LightningElement,api } from 'lwc';
export default class ShoppingCartItem extends LightningElement {
@api cartItems;
}
Complete source code with slds styling can be found here on github https://github.com/decodeforce/salesforce/tree/main/lwc-practice/Shopping%20Cart