Skip to main content

Communication between Lightning Web Components. How many can we use?

About Us
Published by JET BI
13 November 2023
609

Introduction 

Communication between components is crucial to creating responsive and dynamic applications. There are different ways to communicate between Lightning Web Components (LWC), depending on the relationship between the components or event being communicated. For each method, we'll look at a really simple example, focusing on information that only applies to that specific method. By the end of this article, you will have a better understanding of how to communicate between LWC.
 

What are the ways to communicate between components in LWC?
 

There are 3 ways to communicate between components in LWC:

  • Parent-to-Child communication is used when the Parent component's HTML file includes a Child component and we need to pass data from the Parent component to the Child component or call a function in the Child component.
  • Child-to-Parent communication is used when we need to pass data from the Child component to the Parent component.
  • Communication between unrelated components is used to exchange data between components that don’t have a common parent component.
  1. Parent-to-Child communication

To enable Parent-to-Child communication, the child component must have a public property or function declared using the @api decorator.

Pass data to a Child property

child.js

import { LightningElement, api } from 'lwc';


export default class Child extends LightningElement {
  @api childVar;
}


child.html

<template>
</template>


parent.html

<template>
  <c-child child-var={parentVar}></c-child>
</template>


parent.js

import { LightningElement } from 'lwc';


export default class Parent extends LightningElement {
  parentVar = 'Hello!';
}

 

Call a Child function

To call a child function, it is necessary to take into account that this can only be done after the child's component has entered the DOM. So in this example I am using the renderedCallback method.

child.js

import { LightningElement, api } from 'lwc';


export default class Child extends LightningElement {
  @api
  childFunction() {
    return 'Hello!';
  }
}


child.html

<template>
</template>


parent.js

import { LightningElement } from 'lwc';


export default class Parent extends LightningElement {
  renderedCallback() {
    let childCmp = this.template.querySelector('c-child');
    let result = childCmp.childFunction();
  }
}


parent.html

<template>
<c-child></c-child>
</template>

 

          2. Child-to-Parent communication

The Child component cannot directly pass data to the Parent component using property, so this can be done by dispatching a custom event from the Child component, and the Parent component must listen for this event. 

Child-to-Parent

child.js

import { LightningElement } from 'lwc';


export default class Child extends LightningElement {
  renderedCallback() {
    this.childFunction();
  }


  childFunction() {
    this.dispatchEvent(new CustomEvent('childevent', {
      detail: {
        childVar: 'Hello!',
      }
    }));
  }
}


child.html

<template>
</template>

 

parent.js

import { LightningElement } from 'lwc';


export default class Parent extends LightningElement {
  parentFunction(event) {
    let result = event.detail.childVar;
  }
}


parent.html

<template>
  <c-child onchildevent={parentFunction}></c-child>
</template>

 

Child-to-Grandparent

When we have a chain of nested components, we often need to pass data from a child component to the grandparent component. So we need to configure Event Propagation using the bubbles property set to true in dispatchEvent on the intermediate components (in our case, it is the Parent component).

child.js

import { LightningElement } from 'lwc';


export default class Child extends LightningElement {
  renderedCallback() {
    this.childFunction();
  }


  childFunction() {
    this.dispatchEvent(new CustomEvent('childevent', {
      detail: {
        childVar: 'Hello!',
      }
    }));
  }
}


child.html

<template>
</template>


parent.js

import { LightningElement } from 'lwc';


export default class Parent extends LightningElement {
  parentFunction(event) {
    this.dispatchEvent(new CustomEvent('parentevent', {
      bubbles: true,
      detail: event.detail
    }));
  }
}


parent.html

<template>
  <c-child onchildevent={parentFunction}></c-child>
</template>

 

grandparent.js

import { LightningElement } from 'lwc';


export default class Grandparent extends LightningElement {
  grandparentFunction(event) {
    let result = event.detail.childVar;
  }
}


grandparent.html

<template>
  <c-parent onparentevent={grandparentFunction}></c-parent>
</template>

 

3. Communication between unrelated components

To communicate between unrelated components Lightning Message Service (LMS) should be used. LMS is a publish and subscribe (pub-sub) service.

First of all, create a Message Channel. To do this, create a messageChannels folder in your project in VSCode. In the folder, create MyMessageChannel.messageChannel-meta.xml file with the content below and deploy it to your org.

MyMessageChannel.messageChannel-meta.xml

<?xml version="1.0" encoding="UTF-8" ?>
<LightningMessageChannel xmlns="http://soap.sforce.com/2006/04/metadata">
  <masterLabel>MyMessageChannel</masterLabel>
  <isExposed>true</isExposed>
  <description>Sends messages to unrelated components</description>
  <lightningMessageFields>
    <fieldName>value</fieldName>
    <description>The value to send to a component</description>
  </lightningMessageFields>
</LightningMessageChannel>

 

Then create 2 unrelated components. The first has an input field and publishes value from the field via the Message Channel. The second subscribes to this Message Channel and displays the value.

component1.html

<template>
  <lightning-input onchange={sendMessage}></lightning-input>
</template>


component1.js

import { LightningElement, wire } from 'lwc';
import { publish, MessageContext } from 'lightning/messageService';
import MY_MESSAGE_CHANNEL from '@salesforce/messageChannel/MyMessageChannel__c';


export default class Component1 extends LightningElement {
  @wire(MessageContext)
  messageContext;


  sendMessage(event) {
    const payload = {
      value: event.target.value,
    };
    publish(this.messageContext, MY_MESSAGE_CHANNEL, payload);
  }
}


component2.html

<template>
  <p>{value}</p>
</template>

 

component2.js

import { LightningElement, wire } from 'lwc';
import { subscribe, MessageContext } from 'lightning/messageService';
import MY_MESSAGE_CHANNEL from '@salesforce/messageChannel/MyMessageChannel__c';


export default class Component1 extends LightningElement {
  value;
  subscription;


  @wire(MessageContext)
  messageContext;


  connectedCallback() {
    this.subscribeToMessageChannel();
  }


  subscribeToMessageChannel() {
    this.subscription = subscribe(
      this.messageContext,
      MY_MESSAGE_CHANNEL,
      (message) => this.handleMessage(message)
    );
  }


  handleMessage(message) {
    this.value = message.value;
  }
}

 

Conclusion

We've covered Parent-to-Child, Child-to-Parent and unrelated components communications. I hope the examples above have helped you gain a clearer understanding of how to communicate between Lightning Web Components.

If you need any help, don’t hesitate to contact us. Leave a request and we will help you!


Egor Glyakov
Salesforce Developer
image
Expertise
Question to the expert
image

We have available resources to start working on your project within 5 business days

1 UX Designer

image

1 Admin

image

2 QA engineers

image

1 Consultant

image

Steps following request submission

schema

icon

After receiving your request, we analyze it and we offer free online meeting slots (via email) so that we can discuss your needs in as much detail as possible

icon

We begin gathering all necessary requirements to create comprehensive estimates, including timelines, resource allocations, risk assessments, and underlying assumptions.

icon

Once all preparations are in place, we will initiate the project and move forward with the planned tasks