Tag: LWC Code

  • Communication between Lightning Web Components Guide

    Communication between Lightning Web Components Guide

    Here is our third article in the series on LWC. In the previous two, we delved into the principles of building and using components, as well as the basic tenets of markup and its features in LWC. In this article, we will explore communication between LWC components, so let’s get started.

    As a Lightning web component (LWC) developer, you may need to transfer data between components in cases where components are parent-child or unrelated. In this article, we will look at three ways to transfer data between LWC components:

    • Using the “@api” annotation.

    • Using dispatch event.

    • Using the Lightning message channel message service.

    So let’s go!

    “@api” Annotation Properties

    Let’s take a look at the “@api” annotation. This annotation is used to define public properties and methods in a component that can be accessed by other components. This is especially useful when transferring data between parent and child components. We can define a public property in the child component using the “@api” annotation and set its value in the parent component. For example, we can define a public property in the child component as follows.

    import { LightningElement, api } from 'lwc'; 
    export default class ChildComponent extends LightningElement { 
         @api message; 
    }

    In the parent component, we can set the value of the ‘message’ property for the child component as follows:

    <template> 
         <c-child-component message="Hello World"></c-child-component> 
    </template>
    In this example, we pass the ‘Hello World’ value from the parent component to the child component using the ‘@api’ annotation.

    Let’s also consider the use of ‘@api’ with functions. They allow invoking specific functionality of a component from outside, from other components or templates. This is a powerful tool for communication between components and exchanging data and actions.

    You can declare a method in your LWC component and annotate it with ‘@api’. This allows the method to become public and accessible for invocation from other components.

    import { LightningElement, api } from 'lwc'; 
    export default class MyComponent extends LightningElement { 
         @api myMethod(param) { 
              console.log('Received parameter:', param); 
         } 
    }
    In another LWC component, you can reference the component containing a method annotated with “@api” and call that method.
    <template> 
         <c-my-component></c-my-component> 
         <lightning-button label="Call Method" onclick={callMethod}></lightning-button> 
    </template> 
    import { LightningElement } from 'lwc'; 
    export default class AnotherComponent extends LightningElement { 
         callMethod() { 
              const myComponent = this.template.querySelector('c-my-component'); 
              if (myComponent) { 
                   myComponent.myMethod('Hello from AnotherComponent'); 
                   } 
              } 
    }

    In the example provided above, when the button is pressed on the parent component, the child component receives a specific text as a parameter and outputs it to the console.

    The use of “@api” allows you to publicly export the functionality of your component and facilitate interaction with other components. Remember that adhering to security practices and robust design is crucial for effective communication between components.

    Dispatch Event

    Another way of communication between components is through dispatch events, which are used to transmit data between components that are not necessarily related. They can be used for data exchange between parent and child components, sibling components, or even components that do not belong to the same hierarchy.

    Let’s consider an example of a simple form where the user enters some data and clicks the ‘Submit’ button.
    We can create a special event in the form component triggered when the user clicks the ‘Submit’ button. The event can contain the data entered by the user, which can then be passed to another component for further processing. Here is how we can create a special event in the form component:
    import { LightningElement } from 'lwc'; 
    export default class FormComponent extends LightningElement { 
         handleSubmit() { 
              const data = { name: this.template.querySelector('input[name="name"]').value, email: this.template.querySelector('input[name="email"]').value }; 
              const event = new CustomEvent('submitform', { detail: data }); 
              this.dispatchEvent(event); 
              } 
    }

    In this example, we create a special event named ‘submitform’ and pass it to an object containing the user-entered data. Then, we use the dispatchEvent method to trigger the event.

    In another component, we can listen for the ‘submitform’ event and process the received data. Here is how we can listen for the event and handle the data:

    import { LightningElement } from 'lwc'; 
    export default class ResultComponent extends LightningElement { 
          connectedCallback() { 
               this.addEventListener('submitform', this.handleFormSubmit.bind(this)); 
          } 
          handleFormSubmit(event) { 
               const data = event.detail; 
               console.log(`Name: ${data.name}, 
               Email: ${data.email}`); 
          } 
    }

    In this example, we use the addEventListener method to listen for the ‘submitform’ event. When the event is triggered, the ‘handleFormSubmit’ method is called, and we retrieve the data passed in the event using the ‘detail’ property. This approach is useful when components do not belong to the same hierarchy.

    dont miss out iconDon’t forget to check out: LWC Interview Question – Part 2

    Another way to handle events is by using the ‘on’ directive in the HTML file where the child component is invoked.

    To capture this event in the parent component using the ‘on’ directive, you can do the following:

    • In the HTML file of the parent component, add the child component and include the ‘on’ directive:

    <template> 
        <div> 
            <c-my-child-component onsubmitform={handleFormSubmit}></c-my-child-component> 
        </div> 
    </template>
    • In the ‘on’ directive, specify the event name (in this case, onsubmitform) and the name of the function that will handle the event (in this case, handleFormSubmit). In the JavaScript file of the parent component, define the handleFormSubmit function:

    handleFormSubmit(event) { 
         const data = event.detail; 
         console.log(`Name: ${data.name}, Email: ${data.email}`); 
    }
    • In the handleFormSubmit function, you can access the event properties and perform any necessary actions based on the data in the event.

    Note that when using the ‘on’ directive, the event handling function must be defined in the JavaScript file of the parent component.

    One of the advantages of using the ‘on’ directive is that it allows you to handle events more declaratively. By including the ‘on’ directive in the HTML file, you can see which events are being handled and which functions handle them, making code understanding and maintenance easier.

    However, using the ‘on’ directive can also make the code less flexible. If you need to handle the same event in multiple components, you will need to define the event-handling function in the JavaScript file for each element. Conversely, if you use event listeners in the JavaScript file of the parent component, you can define the event handling function once and reuse it in multiple components.

    In general, both approaches have their advantages and drawbacks, and the choice between them depends on the specific requirements of your project.

    Let’s also discuss the use of the “bubbles” and “composed” parameters in our dispatchEvent.

    Bubbles

    The ‘bubbles’ parameter is used when dispatching events in Lightning (LWC) to control whether the event ‘bubbles’ through the DOM hierarchy. Event bubbling is a mechanism where, after processing an event on a specific element, it then propagates up to parent elements for possible further handling.

    In LWC, events typically bubble by default, similar to standard browser events. This means that if you dispatch an event from a child component, it will travel up through the hierarchy of parent components, allowing higher-level components to listen for the event and respond to it if they choose to do so. This natural event propagation can simplify the communication between components, enabling a parent component to respond to actions taken by its child components.

    Composed

    The ‘composed’ parameter is another attribute used when dispatching events in LWC, and it determines whether the event can cross the boundary of the shadow DOM. Shadow DOM is a fundamental concept in web components that encapsulates a component’s styles, structure, and functionality.

    If the ‘composed’ parameter is set to true when dispatching an event, then this event can leave the boundaries of the shadow DOM and be processed by elements outside it. This can be useful if you want to communicate between components that are not directly related through the component hierarchy. However, setting the ‘composed’ parameter to true can also lead to event handling in unexpected places if not used carefully.

    On the other hand, if ‘composed’ is false, the event remains within the bounds of the shadow DOM. This can provide better isolation and control over event handling, restricting interaction between components and preventing event processing outside the designated area.

    These parameters, ‘bubbles’ and ‘composed,’ provide flexibility in how events propagate and are handled in Lightning web components. Understanding their behavior can help you develop more efficient and effective strategies for communication between your components, promoting modular and maintainable code. For a more detailed understanding of their behavior and recommendations, we recommend referring to the official Salesforce documentation.

    Lightning Message Channel

    Additionally, for communication between components, there is the Lightning Message Service (LMS) — an event-driven architecture that allows for message exchange with publishing and subscribing, enabling communication between unrelated components. LMS uses a ‘message channel’ to define communication between components. Components can publish messages on a specific message channel, and other components can subscribe to this channel to receive messages.

    Let’s consider an example of a shopping cart application where users can add items from multiple components. We can use LMS to communicate between components and update the cart when an item is added or removed.

    Here is how we can use LMS to achieve this:
    • First, we need to create a message channel that will be used for communication between components. We can create a message channel using the ‘messageChannel’ module in LWC.

    • In Visual Studio Code, navigate to ‘messageChannels,’ create a new file, name it appropriately, and add ‘.messageChannel-meta.xml’ at the end.

    • In the file, place the following XML:

    <?xml version="1.0" encoding="UTF-8"?> 
    <LightningMessageChannel xmlns="http://soap.sforce.com/2006/04/metadata"> 
         <masterLabel>cartChannel</masterLabel> 
         <isExposed>true</isExposed> 
         <description>Message Channel for cart updates</description> 
         <lightningMessageFields> 
              <name>cartItems</name> 
              <description>Items in the cart</description> 
              <type>Text</type> 
         </lightningMessageFields> 
    </LightningMessageChannel>
    • Next, we need to create a publisher component that will publish messages on the ‘cartChannel.’ Let’s assume we have a product list component where the user can add items to their cart. We can create a special event in the product list component that is triggered when the user adds an item to their cart. The event can contain details of the item added by the user, which can then be passed to the publisher component.

    import { LightningElement, wire } from 'lwc'; 
    import { publish, MessageContext } from 'lightning/messageService'; 
         import CART_CHANNEL from '@salesforce/messageChannel/cartChannel__c'; 
         export default class ProductListComponent extends LightningElement { 
              @wire(MessageContext) messageContext; handleAddToCart(event) { 
                   const data = { name: event.detail.name, price: event.detail.price }; 
                   const message = { data: data }; 
                   publish(this.messageContext, CART_CHANNEL, message); 
                   } 
         }
    

    In this example, we use the ‘publish’ method to publish a message on the ‘cartChannel.’ We pass the message context, message channel, and message itself as parameters to the ‘publish’ method.

    Finally, we need to create a subscriber component that will listen for messages on the ‘cartChannel’ and update the cart accordingly.

    import { LightningElement, wire } from 'lwc'; 
    import { subscribe, MessageContext, unsubscribe } from 'lightning/messageService'; 
    import CART_CHANNEL from '@salesforce/messageChannel/cartChannel__c'; 
    export default class CartComponent extends LightningElement { 
         @wire(MessageContext) messageContext; 
         subscription; 
         connectedCallback() { 
              // Subscribe to the CART_CHANNEL this.subscription = subscribe( this.messageContext, CART_CHANNEL, (message) => { this.handleMessage(message); 
              } 
              ); 
         } 
    handleMessage(message) { 
         // Extract and handle data from the message const data = message.data; 
         // Update the cart with the data received from the message 
         } 
    disconnectedCallback() { 
         // Unsubscribe from the message channel when the component is disconnected unsubscribe(this.subscription); 
         } 
    }
    In this example, we use the ‘subscribe’ method to subscribe to the ‘cartChannel’ and listen for messages. When a message is received, the ‘handleMessage’ method is called, and we extract the data from the message using the ‘data’ property.

    That’s it! We have used LMS to communicate between unrelated components and update the cart each time an item is added or removed. Going forward, we can create more components that publish messages on the channel with information about adding products to the cart and using the same channel.

    In conclusion, LMS can be a resource-intensive method of communication, and its usage should be avoided where possible. 

    For example, the use of the “@api” annotation is ideal for passing data between parent and child components, as it offers a direct way to access the properties and methods of the child component.

    dont miss out iconCheck out another amazing blog by Sparkybit here: Salesforce User Stories: Salesforce Adoption Experience of FinTech Leaders Globally

    On the other hand, events are useful for communication in the reverse direction, from child components to parent components. Additionally, with event listeners, we can simultaneously notify multiple components about changes in the state of our component.

    The Lightning Message Service is recommended for data exchange between unrelated components that do not belong to the same hierarchy. It is also useful when a component needs to send a message to multiple components subscribed to the same message channel.

    Lightning Web Components Developer Guide Part 3: To sum up

    Carefully consider the use case and choose the appropriate communication method to ensure optimal performance and efficient data transmission between components.

    So, if you are a Salesforce developer and have not yet explored the LWC framework, we strongly recommend giving it a try. With its powerful features and ease of use, it quickly becomes the preferred framework for building Lightning web components on the Salesforce platform.

    In the next, final article of the series, we plan to delve into the communication of components with Salesforce and Apex, exploring their methods, advantages, disadvantages, and providing recommendations for their application.

    Sparkybit, Salesforce consulting and development company. We make Salesforce perform at its best by fitting it to Clients’ custom business needs. 9 years of sharpened expertise, 25+ successful long-term projects globally.

    contact@sparkybit.com

    Copyright belongs to Sparkybit GmbH, Im Dörener Feld 3, 33100, Paderborn, Germany.
    2023 © Sparkybit. All rights reserved.

  • Fetching and Displaying Data in Salesforce Lightning Web Components: A Step-by-Step Guide Salesforce

    Fetching and Displaying Data in Salesforce Lightning Web Components: A Step-by-Step Guide Salesforce

    Salesforce Lightning Web Components (LWC) is a framework provided by Salesforce to develop web applications easily. You know how to build cool things with building blocks? LWC is like those blocks for websites and apps.

    I have found a way to represent real-time information from Objects to UI easily. To achieve this, I followed a three-step flow. I’ll help you walk through these steps in an easy manner so that even a beginner can fetch and display data from Objects to UI.

    The scenario that is followed for the below example is that we want to fetch feeds from Custom Feed Object and display on UI.

    The Three-step Guide is:

    Create Apex Controller

    a. Apex Controller is like a middleman between Object (Salesforce’s Database) and LWC component. We have created a controller named FeedController.

    b.Include a method (in our case getFeeds()) in order to fetch data.

    c. Don’t forget to add `@AuraEnabled(cacheable=true)` to enable Lightning component access and caching.

    public with sharing class FeedController {
         @AuraEnabled(cacheable=true)
         public static List<Feed__c> getFeeds() {
              return [SELECT Id, Name, Post_Content__c, Post_Image__c, 
              CreatedDate FROM Feed__c];
         }
    }

    dont miss out iconDon’t forget to check out: Introduction to Lightning Web Components (LWC): A Beginner’s Guide to Building Dynamic Salesforce User Interfaces

    Create LWC Component

    a. Let’s create LWC component (feedPage in our case).

    b.Import getFeeds method in our feedPage.js file.

    import getFeeds from 
    `@salesforce/apex/FeedController.getFeeds`;

    c. Use @wire decorator to establish connection between Apex Controller and our component.

    import { LightningElement, track, wire } from 'lwc';
    import getFeeds from '@salesforce/apex/FeedController.getFeeds';
    export default class FeedPage extends LightningElement {
         @track feeds;
         @wire(getFeeds)
         wiredFeeds({ error, data }) {
              if (data) {
                   this.feeds = data;
              } 
              else if (error) {
                   console.error('Error fetching feeds:', error);
              }
         }
    }
    

    Display on UI

    With the data being fetched, now it’s time that we finally display it on our UI. This part will be handled by the feedPage.html file in our case. Show all feeds by using a for loop.

    <template>
    <ul if:true={feeds}>
    <template for:each={feeds} for:item="dataItem">
    <li key={dataItem.Id}>
    <!-- Display data item details here -->
    </li>
    </template>
    </ul>
    <p if:false={feeds}>No data found.</p>
    </template>

    Important Admin configurations that are needed for your component to work properly on Builder of Digital Experience are listed below:

    1. Enable Guest User Access.

    2. Add a Sharing Rule in Sharing Settings.

    3. Go to Profile < Settings < Builder and enable FeedController class.

    4. Drag your component on the Builder’s Page.

    5. Check your component, it will be fetching data and displaying the same.

    You have learned how to fetch and display data from Object to UI in Experience Cloud using Builder.

    dont miss out iconCheck out another amazing blog by Nayan here: Decorators in Salesforce

    Conclusion

    In this guide, all the concepts related to fetching the data and displaying the data on UI webpages are shown with practical examples. In the above example we have a custom Feed Object ( Feed___c ) which in return has different fields like Name, Post_Content__c, Post_Image__c, Creator etc. Our objective was to fetch Feeds from Feeds Object and show it on our UI using LWC Component.

    Author – Nayan Kaslikar