Saturday 6 July 2019

Events in Lightning web components (LWC) | Communicate with Events


In this post we will talk about how to use the lightning web component events to communicate between components. Events in Lightning web components are built on DOM Events, a collection of APIs and objects available in every browser. Here we will be see how to the events using the CustomEvent interface and publish-subscribe utility.

Component Communication through events

There are typically 3 approaches for communication between the components using events.

  1. Communication using Method in LWC ( Parent to Child )
  2. Custom Event Communication in Lightning Web Component (Child to Parent )
  3. Publish Subscriber model in Lightning Web Component ( Two components which doesn't have a direct relation )
NOTE:- If you want to communicate the Lightning web component with Visualforce page then we can use Lightning Message Service (LMS).


Option 1) Communication using Method in LWC (Parent to Child)

In Aura framework, we can call the method of Child Component from the Parent Component with the help of <aura:method>  (Please check this post for <aura:method in aura). In LWC also we can do the same. In LWC Aura Methods Become JavaScript Methods.

For this we have use the @api decorator to make the children properties / method public available so parent can be able to call it directly using JavaScript API. For example create one public method (which we need to access in parent component) in ChildComponent with @api decorator like below

ChildComponent 
@api
changeMessage(strString) {
     this.Message = strString.toUpperCase();
}
To access the above child method in parent component we can do like that.

ParentComponent
this.template.querySelector('c-child-component').changeMessage(event.target.value);
The querySelector() method is a standard DOM API that returns the first element that matches the selector


Lets take one example to pass value from parent component to child component.
  1. Create one child Component to show message from parent component. 
    childComp.html
    <template>
        Message Will Come here from Parent Component :- {Message}
    </template>
  2. Create javaScript method in child component to assign value on child attribute.            childComp.js
    import { LightningElement, track, api } from 'lwc';
    export default class ChildComponent extends LightningElement {
        @track Message;
        @api
        changeMessage(strString) {
             this.Message = strString.toUpperCase();
        }

    }
  3. Create one Parent Component to call child component. 
    ParentComponent.html
    <template>
        <lightning-card title="Parent to Child Demo">
            <lightning-layout>

                <lightning-layout-item flexibility="auto" padding="around-small"  >
                    <lightning-input label="Enter the Message" onchange={handleChangeEvent}></lightning-input>
                </lightning-layout-item>
              
                <lightning-layout-item flexibility="auto" padding="around-small">
                    <c-child-Comp></c-child-Comp>
                </lightning-layout-item>
              
            </lightning-layout>
        </lightning-card>   
    </template>
  4. Now Create JavsScript method in Parent component to call child method with "this.template.querySelector".
    ParentComponent.js
    import { LightningElement } from 'lwc';

    export default class ParentComponent extends LightningElement {
        handleChangeEvent(event){
            this.template.querySelector('c-child-Comp').changeMessage(event.target.value);
        }

    }
  5. Update your meta.js file to make this component available for App, home page.
    ParentComponent.js
    <?xml version="1.0" encoding="UTF-8"?>
    <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="parentComponent">
        <apiVersion>45.0</apiVersion>
        <isExposed>true</isExposed>
        <targets>
            <target>lightning__AppPage</target>
            <target>lightning__RecordPage</target>
            <target>lightning__HomePage</target>
        </targets>
    </LightningComponentBundle>

Output :






Option 2) Custom Event Communication in Lightning Web Component (Child to Parent)

We already talk about Event in Aura. Lets talk about Lightning Web Components (LWC), here Custom Event is used to make the communication from Child Component to Parent Component. With LWC we can create and dispatch the custom event.

  1. Create and Dispatch an Event

    • Create Event : We can use the customEvent() constructor to create an event. In constructor we need to pass custom event name and detail of the event.

      new customEvent(eventName, props);

    • Dispatch Event : We have to dispatch an event at with EventTarget.dispatchEvent() method.

        this.dispatchEvent(new customEvent(eventName, props);
  2. Handle an Event : There are two ways to listen to an event

    • Declarative via html markup : We need to add “on” prefix in the event name in Parent Component during calling of Child Component for Declaratively event listener.
       ParentComponent
          <template>
                <c-child-component oneventName={listenerHandler}></c-child-component >
           </template>

    • JavaScript using addEventListener method : We can explicitly attach a listener by using the addEventListner method in the parent component like below :
       ChildComponent
      this.template.addEventListener('eventName', this.handleNotification.bind(this));

Lets take one example for "Declarative via html markup"
  1. Create one child component component from where we will raise a event
    1. Create child html file to get value from user.
      childComp.html
      <template>
          <lightning-card title="Child Component">
              <div class="slds-m-around_medium">
                  <lightning-input name="textVal" label="Enter Text" onchange={handleChange}></lightning-input>
              </div>
          </lightning-card>
      </template>
    2. Now update Child Comp javaScript file to raise a CustomEvent with text value
      childComp.js
      import { LightningElement } from 'lwc';

      export default class ChildComp extends LightningElement {

         handleChange(event) {
              event.preventDefault();
              const name = event.target.value;
              const selectEvent = new CustomEvent('mycustomevent', {
                  detail: name
              });
             this.dispatchEvent(selectEvent);

          }
      }
  2. Create one Parent component where we will handle the event
    1. Now create parent component. We need to add prefix as “on” before the custom event name and in parent component we need to invoke the event listener as handleCustomEvent using onmycustomevent attribute.
      ParentComponent.html
      <template>
          <div class="slds-m-around_medium">
              Value From Child :  {msg}
              <c-child-comp onmycustomevent={handleCustomEvent}></c-child-comp>
          </div>
      </template>
    2. Now update parent component javaScript file and add handleCustomEvent method.
      ParentComponent.js
      import { LightningElement , track } from 'lwc';

      export default class ParentComponent extends LightningElement {
          @track msg;
          handleCustomEvent(event) {
              const textVal = event.detail;
              this.msg = textVal;
          }

      }
   
Output :-



Lets see how we can use  "JavaScript using addEventListener method | Attaching event Listener Programmatically"
  1. We can use the same above sample and do below change in parent component
    1. Update parent component JavaScript like below.
      ParentComponent.js
      import { LightningElement , track } from 'lwc';

      export default class ParentComponent extends LightningElement {
          @track msg;
        
          constructor() {
              super();   
              this.template.addEventListener('mycustomevent', this.handleCustomEvent.bind(this));
          }

          handleCustomEvent(event) {
              const textVal = event.detail;
              this.msg = textVal;
          }
      }
    2. Remove onmycustomevent attribute from child component tag. like below
      ParentComponent.html
      <template>
          <div class="slds-m-around_medium">
              Value From Child :  {msg}
              <c-child-comp ></c-child-comp>
          </div>
      </template>
    3.  Set the bubbles: true while raising the event like below
      childComp.js
      import { LightningElement } from 'lwc';

      export default class ChildComp extends LightningElement {

         handleChange(event) {
              event.preventDefault();
              const name = event.target.value;
              const selectEvent = new CustomEvent('mycustomevent', {
                  detail: name ,bubbles: true
              });
            this.dispatchEvent(selectEvent);
          }
      }

Event Propagation: When an event is fired the event is propagated up to the DOM. Event propagation typically involves two phases event bubbling and event capturing. The most commonly used event propagation phase for handling events is event bubbling. In this case the event is triggered at the child level and propagates up to the DOM. Where as event capturing phases moves from top to bottom of the DOM. This phase is rarely used for event handling.

The below picture shows the event phases both in capture and bubbles phase. In LWC we have two flags which determines the behavior of event in event bubbling phase.
  1. bubbles A Boolean value indicating whether the event bubbles up through the DOM or not. Defaults to false.
  2. composed A Boolean value indicating whether the event can pass through the shadow boundary. Defaults to false.





reference: https://developer.salesforce.com/docs/component-library/documentation/lwc/events_propagation


Option 3) Publish Subscriber model in Lightning Web Component


Application Events in aura become a Publish-Subscribe Pattern in Lightning web components. We use an library called pubsub to achieve the communication between two components which doesn't have a direct relation to each other. This works like a typical publish subscribe model. Where an event is subscribed by a component and handled when another component which fires/publishes the event within the same scope.


Please use this link to get the pub sub utility code. Pubsub module support below three method
  1. Register 
  2. UnRegister
  3. Fire

Follow below step for Pub Sub module
  1. Import Pub Sub file from here.

  2. Register the Event

    1.  Add JavaScript Code in Component to register and unregister the event. In this JS file, invok registeredListener() and unregisterAllListeners() in the respective methods such as connectedCallback() and disconnectedCallback().
      MyComponent.js
      import { registerListener, unregisterAllListeners} from 'c/pubsub';
      export default class MyComponent extends {

          @track Message;
          connectedCallback() {
              registerListener('messageFromSpace', this.handleMessage, this);
          }
         
          handleMessage(myMessage) {
              this.Message = myMessage;
              //Add your code here
          }
         
          disconnectCallback() {
              unregisterAllListeners(this);
          }
      }
  3. Fire the event

    1.  Fire the event from other Component. In that js file, We need to trigger the event with name and value. Remember, we also need to send the page reference attribute as current page reference for successful communication
      OtherComponent.js
      import {  fireEvent } from 'c/pubsub';
      import { CurrentPageReference } from 'lightning/navigation';
      export default class OtherComponent extends LightningElement {
           @track myMessage;
           @wire(CurrentPageReference) pageRef;

           sendMessage() {
                fireEvent(this.pageRef, 'messageFromSpace', this.myMessage);
           }
      }


Please check below post on Lightning Web Components:-

Check our YouTube Channel for more recording in Lightning Web Components. 

Thanks,
Amit Chaudhary

19 comments:

  1. It is very good post and very clear concepts.

    ReplyDelete
  2. Simple, straight forward and excellent article.. Excellent article, it helped me a ton...
    Please help to share your thoughts on shadow dom, sloting html, with bubbling, without bubbling etc.,

    ReplyDelete
  3. Perfect example of LWC component communication patterns..

    ReplyDelete
  4. This comment has been removed by the author.

    ReplyDelete
  5. Thank you for sharing this article, Grupio is the best conference app for our users. It is helping them with their events and connect with the people they need to. Their app is easy to use and highly intuitive. They are constantly updating it with new features and improvements. Visit them today to see what's new!

    ReplyDelete
  6. If you are looking for a event management company in Perth, Australia or you need a perth function venue for any special day. Please go through our website.

    ReplyDelete
  7. Congratulations! Your blog is always very inspiring.
    active passive Components

    ReplyDelete
  8. Your car could be stolen if you don't keep this in mind!

    Imagine that your car was taken! When you visit the police, they inquire about a specific "VIN decoder"

    A VIN decoder is what?

    Similar to a passport, the "VIN decoder" allows you to find out the date of the car's birth and the identity of its "parent" (manufacturing facility). You can also find out:

    1.Type of engine

    2.Automobile model

    3.The DMV's limitations

    4.Number of drivers in this vehicle

    You'll be able to locate the car, and keeping in mind the code ensures your safety. The code can be checked in the database online. The VIN is situated on various parts of the car to make it harder for thieves to steal, such as the first person's seat on the floor, the frame (often in trucks and SUVs), the spar, and other areas.

    What happens if the VIN is intentionally harmed?

    There are numerous circumstances that can result in VIN damage, but failing to have one will have unpleasant repercussions because it is illegal to intentionally harm a VIN in order to avoid going to jail or calling the police. You could receive a fine of up to 80,000 rubles and spend two years in jail. You might be held up on the road by a teacher.

    Conclusion.

    The VIN decoder may help to save your car from theft. But where can you check the car reality? This is why we exist– VIN decoders!

    ReplyDelete
  9. Бонусы и поощрений в БК 1хбет существенно повышает привлекательность компании в глазах игроков. Весьма выгодные предложения доступны как новеньким, и пользователям, уже имеющим опыт работы на платформе. В числе внушительного набора бонусной программы очень легко потеряться. Каждый промокод 1хбет обеспечивает право на определенные преференции - промокод для 1 икс бет.

    ReplyDelete
  10. БК MelBet пользуется большой известностью на отечественном рынке: -Деятельность организации лицензирована; - Игрокам предоставлен впечатляющий список ставок - в формате live и предматчевых; - Здесь нет задержек с выплатами. Линия ставок неописуемо презентабельна. Для того, чтобы получить выгодный бонус на совершение ставок, надо всего только использовать промокод MelBet RS777. Получить промокод вы можете на ставку или на депозит. Каждое предложение имеет свои особенности отыгрыша - Мелбет промокод на сегодня.

    ReplyDelete
  11. В 2023 году промокод 1хбет предоставляющий максимальный бонус - 1XFREE777. Бонусные денежные средства начисляются автоматически на отдельный счет и их сразу же вы можете использовать для игры - promokod 1xbet.

    ReplyDelete
  12. Nice blog shared with us. PrintMagic offers affordable online custom event tickets in several different sizes, styles, security features and printing options. Our personalized event tickets come in 3 premium card stocks of Standard Gloss Cover-100lb, Premium Gloss, Thick Gloss. Size ranges of 7 sizes - 2" x 5.5", 2" x 7", 2.75" x 5.5", 2.75" x 8.5", 3.5" x 11", 3.5" x 8.5", 4.25" x 11" in 2 orientation styles of horizontal and vertical full color printing.

    ReplyDelete