This is the latest series of posts I am doing on a new Pluralsight course I created titled, “Communicate Between Salesforce Lightning Web Components”.
Working with Public Properties
Public properties can be used to pass data from a parent component to one or more children components. For Lightning Web Components (LWC), data is passed from the parent to the child using the @api decorator.
Decorators are used in JavaScript to wrap one piece of code with another. That is why they are called decorators. The @ symbol is placed before the name of the decorator and for LWC the @api decorator is a special decorator used to expose public properties or methods.
When used with a property, these properties/fields are reactive. This means whenever the value of the property changes, the component is automatically rerendered. For this reason, each property can be associated with only one decorator. This also applies when a method is decorated.
Displaying Products
In this post, I will be working with nested components used to search for and display products. The parent or container component will be named displayProducts. The code for this component is seen below:
<!-- displayProduct.html -->
<template>
<div class="slds-card slds-var-p-around_x-small">
<lightning-input
label="Search Key"
type="text"
onchange={handleSearchKeyChange}
class="search-bar"
></lightning-input>
<template if:true={products.data}>
<template if:true={products.data.length}>
<div class="content">
<template for:each={products.data}
for:item="product">
<!-- Product Tile Component here-->
<c-product-tile
key={product.Id}
product={product}
onselected={handleProductSelected}
class="slds-var-m-around_x-small">
</c-product-tile>
</template>
</div>
</template>
<template if:false={products.data.length}>
<p>No products matching your selection</p>
</template>
</template>
<template if:true={products.error}>
<p>Error when getting product data</p>
</template>
</div>
</template>
// displayProducts.js
import { LightningElement, wire } from 'lwc';
import { publish, MessageContext } from 'lightning/messageService';
import PRODUCT_SELECTED_MESSAGE from '@salesforce/messageChannel/ProductSelected__c';
// getProducts() method in ProductController Apex class
import getProducts from '@salesforce/apex/ProductController.getProducts';
export default class DisplayProducts extends LightningElement {
searchKey = '';
// Load context for Lightning Messaging Service
@wire(MessageContext) messageContext;
//Publish ProductSelected message
handleProductSelected(event) {
publish(this.messageContext, PRODUCT_SELECTED_MESSAGE, {
productId: event.detail
});
}
// Load the list of available products.
@wire(getProducts, { searchKey: '$searchKey' })
products;
handleSearchKeyChange(event) {
this.searchKey = event.target.value.toLowerCase();
}
}
Things to notice in the bolded portion of the displayProducts.html file above:
- Since a search may return multiple products, a child component named productTile will be used to display just one product as a tile.
- An iterator will be used to display as many instances of this child component as there are records returned.
- I am passing the product id through the key attribute and the actual product data through the product attribute.
Here is the HTML and JS for the productTile component.
<!-- producTile.html -->
<template>
<a onclick={handleClick}>
<div class="content">
<img
src={pictureUrl}
class="product slds-align_absolute-center"
alt="Product picture"
/>
<div>
<p class="title slds-align_absolute-center">{name}</p>
<p class="slds-align_absolute-center">
MSRP:
<lightning-formatted-number
format-style="currency"
currency-code="USD"
value={msrp}
class="price"
maximum-fraction-digits="0">
</lightning-formatted-number>
</p>
</div>
</div>
</a>
</template>
// productTile.js
import { LightningElement, api } from 'lwc';
export default class ProductTile extends LightningElement {
_product;
pictureUrl;
name;
msrp;
@api
get product() {
return this._product;
}
set product(value) {
this._product = value;
this.pictureUrl = value.Picture_URL__c;
this.name = value.Name;
this.msrp = value.MSRP__c;
}
handleClick() {
const selectedEvent = new CustomEvent('selected', {
detail: this.product.Id
});
this.dispatchEvent(selectedEvent);
}
}
Things to notice in the bolded portion of the productTile.js file above:
- api was added to the list of modules to be imported.
- Below that will be private variables used for the product data passed from the parent component.
- Data will be passed to the child through getter and setter functions, which need to be annotated with the @api decorator, in order to make them public.
The end result of all of this is a component that looks like this:

The code and explanations in this post is just a sample of all that is covered in the Pluralsight course, “Communicate Between Salesforce Lightning Web Components”. Check that out if you are interested in learning more about how LWC’s communicate.