Decorators in Lightning Web Component(LWC)
Published: 2021-10-24 07:09:31


## Decorators in Lightning Web Component(LWC)
The Lightning Web Components programming model has three decorators that add functionality to property or function. Decorators dynamically alter the functionality of a property or function. The ability to create decorators is part of ECMAScript, but these three decorators are unique to Lightning Web Components.

-   **@api**:  It is used to expose a variable or functions publically and make properties reactive.
-   **@track**:  It is used to make variable private but reactive. Tracked properties are also called private reactive properties.
-   **@wire**: To read Salesforce data, Lightning web components use a reactive wire service. When the wire service provisions data, the component rerenders. Components use @wire in their JavaScript class to specify a wire adaptor or an Apex method.

Here are three decorators in LWC in more details:
### @api

Public properties are **reactive**. If the value of public property changes, the component rerenders. To expose a public property, decorate a field with  **@api**. Public properties define the API for a component.

To expose a public method, decorate it with  **@api**. Public methods are part of a component’s API. To communicate down the containment hierarchy, owner and parent components can call JavaScript methods on child components. 
**To use @api we have to import it first** from lwc.
**Import @api decorator from lwc**
```javascript
import { LightningElement, api } from 'lwc';
```
Let's have a look at example:
This is a child component named as childComp
```html
<--  childComp.html  -->
<template>
  <div  class="label-class">
    <h1>{headerLabel}</h1>
  </div>
</template>
```
```javascript
// childComp.js
import { LightningElement, api } from  'lwc';
export  default  class  ChildComp  extends  LightningElement {
@api headerLabel = 'This Label is from ChildComp.js';
}
```
```css
/* childComp.css */
.label-class{
background-color:  white;
}
```
Now if we call this from other lwc component like below
```html
<-- parentComp.html -->
<template>
	<c-child-comp></c-child-comp>
</template>
```
and if you run parentComp.html then the output would be simply
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2j3kcuiw5byrlrkko0nx.png)
But in childComp we have @api attribute so we can change it from parentComp like this:
```html
<-- parentComp.html -->
<template>
	<c-child-comp header-label="Hey! Im changed" ></c-child-comp>
</template>
```
**Here we have are calling headerLabel in kebab case like "header-label" if we don't use kebab case it will through error.**
Now if you refresh the parentComp, the output would be
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oxl01ym0tlplt5d5uqnu.png)

### @track

Fields are reactive. If a field’s value changes, and the field is used in a template or in a getter of a property that’s used in a template, the component rerenders and displays the new value.

When a field contains an object or an array, there’s a limit to the depth of changes that are tracked. To tell the framework to observe changes to the properties of an object or to the elements of an array, decorate the field with **@track** .
Note: we can't access **@track** properties from outside as they are private and only accessible within its component only.
**To use @track we have to import it first** from lwc.
**Import @track decorator from lwc**
```javascript
import { LightningElement, track} from 'lwc';
```
Let's have a look at example:
This is a component named as childComp
```html
<--  childComp.html  -->
<template>
	<div class="slds-m-around_medium">
	 <p>Hello, {greeting}!</p>
	<lightning-input label="Name" value={greeting} onchange={changeHandler}></lightning-input>
	</div>
</template>
```
```javascript
// childComp.js
import { LightningElement, track} from  'lwc';
export  default  class  ChildComp  extends  LightningElement {
@track greeting = 'Hello World';

  changeHandler(event) {
	this.greeting = event.target.value;
  }
  
}
```
**Note:** You can use "greeting" variable without @track but is always recommended to use @track in case you are showing variable in html as it make it reactive so whenever it changes in js the changes will also be visible in html.

### @wire

To read Salesforce data, Lightning web components use a reactive wire service. When the wire service provisions data, the component rerenders. Components use @wire in their JavaScript class to specify a wire adapter or an Apex method.

We need to import the`` @salesforce/apex`` scoped module into JavaScript controller class.
```javascript
import apexMethodName from  '@salesforce/apex/Namespace.Classname.apexMethodReference';
```
Here is list of important point of importing apex method:

-   **apexMethodName**  : An imported symbol that identifies the Apex method.
-   **apexMethodReference**  : The name of the Apex method to import.
-   **Classname**  : The name of the Apex class.
-   **Namespace**—The namespace of the Salesforce organization. Specify a namespace unless the organization uses the default namespace (c), in which case don’t specify it.

Example:
```java
public with sharing class  AccountHelper {
@AuraEnabled(cacheable=true)
	public static List<Account> getAccountList() {
		return [SELECT  Id, Name, Type, Rating, Phone FROM  Account];
	}
}
```
**Note:** ApexMethod should be annotated with ``@AuraEnabled`` and if you use ``cacheable=true``you can't mutate data in your apex method.

 **Synta for Invoking Apex Method in LWC js** 
```javascript
import apexMethod from  '@salesforce/apex/Namespace.Classname.apexMethod';
@wire(apexMethod, { apexMethodParams })
propertyOrFunction;
```

**Usage:**
```javascript
/* childComp.js */
import { LightningElement, wire } from  'lwc';
import getAccountList from  '@salesforce/apex/AccountHelper.getAccountList';
export  default  class  ChildComp  extends  LightningElement {
	@wire(getAccountList) accounts;
}
```
```html
<-- childComp.html -->
<template>
  <lightning-card title="Account List From Apex" icon-name="custom:custom63">
	<div class="slds-m-around_medium">
		<template if:true={accounts.data}>
			<template for:each={accounts.data} for:item="acc">
				<p key={acc.Id}>{acc.Name}</p>
			</template>
		</template>
			<template if:true={accounts.error}>{accounts.error}</template>
	</div>
</lightning-card>
</template>
```

Don't worry we will learn more about @wire and @api in upcoming articles till then you can refer to [official link](https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.reference_decorators).