Decorators in LWC | Salesforce Developer Guide

Lightning Web Components (LWC) is a framework provided by Salesforce to develop fast, responsive, and reusable web components for their platform. One of the key features of LWC is its support for decorators, which are used to add functionality to a component or its members. In this blog post, we will explore what decorators are and how they can be used in LWC. 

What are Decorators?

Decorators are a way to modify or enhance the behavior of a component or its members. In LWC, decorators are applied to class properties or methods using the @decoratorName syntax. Decorators can be used to add functionality like validation, caching, memorization, and event handling to a component or its members. 

Built-in Decorators:

LWC comes with several built-in decorators, which can be used to add common functionality to a component. Some of the most commonly used built-in decorators include: 

@track 

The @track decorator is used to mark a property as reactive. When a reactive property changes, the component is automatically re-rendered.

DecoratorLwc.js

import { LightningElement, track } from 'lwc'; 
export default class DecoratorLwc extends LightningElement { 
     @track welcomeMessage = {"message" : "Hey!"}; 
     showWelcomeMessage() 
     {
          this.welcomeMessage.message = 'Hey! Welcome to SalesforceBlue :)';
     } 
}

DecoratorLwc.html

<template> 
<lightning-card title="DecoratorLwc" >
<p class="slds-p-horizontal_small"> {welcomeMessage.message} </p> 
<lightning-button variant="brand" label="Click Me"  title="label" onclick={showWelcomeMessage} slot="actions">
</lightning-button>
</lightning-card> 
</template>

You can see the updated message being displayed, which wouldn't be the case if we didn't decorate the welcomeMessage property with @track.

dont miss out iconDon't forget to check out:  Handle Events in LWC | All You Need to Know

Limitation of the track decorators

  1. You cannot expose these properties to the app builder.
  2. You cannot pass properties from other components.

@api

The @api decorator is used to mark a property or method as public and to expose it to other components.

apiDecoratorExampleParent.html

<template>
    <!-- Call child component -->
    <c-api-decorator-example-child greeting-message={greetingMessageFromParent}>
    </c-api-decorator-example-child>
</template>
apiDecoratorExampleParent.js
import { LightningElement } from 'lwc';
export default class ApiDecoratorExampleParent extends LightningElement {
    greetingMessageFromParent = 'Hello! This is an example for @api decorator';
}

apiDecoratorExampleChild.html

<template>
    <h2>{greetingMessage}</h2>
</template>
 apiDecoratorExampleChild.js
import { LightningElement, api } from 'lwc';
export default class ApiDecoratorExampleChild extends LightningElement {
    @api greetingMessage;
}

@wire

The @wire decorator is used to wire a component to a Salesforce Apex method or an external data source. When data changes, the component is automatically re-rendered. 

There are two ways we can use @wire to call apex:-

  1. Wire a property

This approach can be used when we do not want to process the data which is returned from the server(i.e., apex) and we just want to display it on the UI or store it in a component property for some other purpose. Below is sample code using the cable property in LWC. In this component, all child contact records related to the account are loaded and displayed in a table in the user interface.

wireDecoratorExample.html

<template>
    <!-- Display child contact records -->
    <table class="slds-table slds-table_bordered slds-border_left slds-border_right">
        <thead>
          <tr class="slds-line-height_reset">
            <th class="" scope="col">
              <div class="slds-truncate" title="Name">Name</div>
            </th>
            <th class="" scope="col">
              <div class="slds-truncate" title="Email">Email</div>
            </th>
            <th class="" scope="col">
                <div class="slds-truncate" title="Phone">Phone</div>
              </th>
          </tr>
        </thead>
        <tbody>
          <template for:each={listContact.data} for:item="contactRecord">
              <tr key={contactRecord.Id}>
                  <td>{contactRecord.Name}</td>
                  <td>{contactRecord.Email}</td>you 
                  <td>{contactRecord.Phone}</td>
              </tr>
          </template>
        </tbody>
      </table>
</template>
wireDecoratorExample.js
import { LightningElement, api, wire } from 'lwc';
import fetchChildContact from '@salesforce/apex/WireDecoratorExampleController.fetchChildContactRecords';
export default class WireDecoratorExample extends LightningElement {
    @api recordId;
    @wire(fetchChildContact, { accountId: '$recordId' })
    listContact;
}

dont miss out iconCheck out another amazing blog by Rahul here: All You Need to Know About DupeCatcher Salesforce

2. Wire a function

This approach is used when there is a need to process the data that is returned from the apex. The returned data is provided to the callback function.

Let’s modify the above sample code to use a wired function instead of wired property

// wireDecoratorExample.html
<template>
    <!-- Display child contact records -->
    <table class="slds-table slds-table_bordered slds-border_left slds-border_right">
        <thead>
          <tr class="slds-line-height_reset">
            <th class="" scope="col">
              <div class="slds-truncate" title="Name">Name</div>
            </th>
            <th class="" scope="col">
              <div class="slds-truncate" title="Email">Email</div>
            </th>
            <th class="" scope="col">
                <div class="slds-truncate" title="Phone">Phone</div>
              </th>
          </tr>
        </thead>
        <tbody>
          <template for:each={listContact} for:item="contactRecord">
              <tr key={contactRecord.Id}>
                  <td>{contactRecord.Name}</td>
                  <td>{contactRecord.Email}</td>
                  <td>{contactRecord.Phone}</td>
              </tr>
          </template>
        </tbody>
      </table>
</template>
// wireDecoratorExample.js
import { LightningElement, api, wire } from 'lwc';
import fetchChildContact from '@salesforce/apex/WireDecoratorExampleController.fetchChildContactRecords';
export default class WireDecoratorExample extends LightningElement {
    @api recordId;
    listContact;
    @wire(fetchChildContact, { accountId: '$recordId' })
    wiredContacts({ error, data }) {
        if (data) {
            this.listContact = data;
        } else if (error) {
            this.listContact = undefined;
        }
    }
}

Custom Decorators: In addition to the built-in decorators, developers can create their own custom decorators to add specific functionality to their components. For example, a developer might create a custom decorator to handle caching of data, or to add event handling to a component. 

To create a custom decorator, the developer defines a function that takes a target object (the class) and a property key (the name of the property or method being decorated) as arguments. The function can then modify the behavior of the property or method as needed. 

Conclusion: Decorators are a powerful feature of LWC that allow developers to add functionality to components and their members in a reusable and flexible way. By using built-in decorators and creating custom decorators, developers can create components that are more responsive, efficient, and easier to maintain. 

Responses

Popular Salesforce Blogs