Saturday, January 4, 2020

Decorators in Lightning Web Components

We have 3 Decorators in Lightning Web Components.

1) @api
2) @track
3) @wire

The function of the Decorators is to add functionality to property or function.

How to decorate a property?

@decoratorName propertyName='propertyValue';

How to decorate a method?

@decoratorName

getMethodName(){

return somevalue;

}

Now, let us understand all the three decorators.

@api

1) When we want to expose a public property, we decorate it with @api.

2) Public Property is reactive and if the value of a reactive property is changed, the component is rerendered, so when a component is rerendered, all the expressions used in the template are reevaluated once again.

3) When we use the @api decorator, we must import it explicitly from lwc as shown below.

import { LightningElement, api } from 'lwc';

4) Parent component can make use of the Public Property.

5) A component that declares a public property can set only its default value.

6) A parent component that uses the child component in its markup can set the child component’s public property value.

Note:

A property can have only one decorator at a time.

Now, let us understand @api with an example.

childComp.html

<template>
    {childMessage}
</template>

childComp.js

import { LightningElement, api } from 'lwc';

export default class ChildComp extends LightningElement {

    @api childMessage='Hi I am from child';
}

parentComp.html

<template>
    <div>
        <b>First Call to child component</b>
        <c-child-comp></c-child-comp>
    </div>
    <div>
        <b>Second call to child comp</b>
        <c-child-comp child-message="From Parent"></c-child-comp>
    </div>
 
</template>

parentComp.js

import { LightningElement } from 'lwc';

export default class ParentComp extends LightningElement {
 
}

LightningApplication:

<aura:application>
<c:parentComp></c:parentComp>
</aura:application>

Output:

Decorators in Lightning Web Components

@track

 1) Private reactive property.

2) Reactive here means if there is a change in javascript property the component will rerender and all the expressions used in the template are reevaluated once again.

3) Private Property can be used only in the component where it is defined.

4) When we use the @track decorator, we must import it explicitly from lwc as shown below.

import { LightningElement, track } from 'lwc';

Now, let us understand with an example.

In the below example the value of the property "fname" will change according to input the user enters and as @track is a reactive property and whenever a change is noticed in "fname"  the component will rerender and display the updated value but as soon as we remove @track from the property "fname" the value change will be noticed in "fname" but the component will not be rendered and the old value will be displayed.

webComp.html

<template>
    Name is:  - {fname}
    <br />
    <lightning-input type="text" value={fname} onchange={handleChange} ></lightning-input>
</template>

webComp.js

/* eslint-disable no-console */
import {
    LightningElement,
    track
 } from 'lwc';

 export default class webcomp4 extends LightningElement {
    @track fname = "Farukh Haider";
    handleChange(event) {
        this.fname = event.target.value;
        console.log('Name change ' + this.fname);
    }

 }


Before Spring ’20, to make the component rerender when a user entered a fname, you had to decorate the fields with @track. Now if we remove the @track property as well there will not be any change in output.

@wire

1) @wire is used to read Salesforce data.

2) It is reactive i.e when it provisions the data the components rerender.

3) It is use to call an apex method.

We have to use default import syntax to import an Apex method as shown below in  Javascript Controller.

Syntax:

import apexMethodName from '@salesforce/apex/Namespace.Classname.apexMethodReference';

apexMethodName—This identifies the Apex method.

apexMethodReference—The name of the Apex method to import.

Classname—The name of the Apex class.

Namespace—If the class is in the same namespace as the component, don’t specify a namespace. If the class is in a managed package, We have to specify the namespace of the managed package.

To call an Apex method, a Lightning web component can do the following:

1) Wire a property
2) Wire a function
3) Call a method imperatively

Wire an Apex Method to a Property:

import apexMethod from '@salesforce/apex/Namespace.Classname.apexMethod';
@wire(apexMethod, { apexMethodParams })
propertyOrFunction;

apexMethodParams—An object with parameters for the apexMethod, if needed.

propertyOrFunction—A private property or function that receives the stream of data from the wire service. If a property is decorated with @wire, the results are returned to the property’s data property or error property. If a function is decorated with @wire, the results are returned in an object with a data property or an error property.

wireExample.html

<template>
    <div >
        <p>Displaying Contact Data</p>
        <template if:true={contacts.data}>
            <template for:each={contacts.data} for:item="contact">
                <p key={contact.Id}>{contact.Name}</p>
            </template>
        </template>
        <template if:true={contacts.error}>
           
        </template>
    </div>

</template>

wireExample.js

import { LightningElement, wire } from 'lwc';
import getContactList from '@salesforce/apex/FetchContact.getContactList';

export default class wireExample extends LightningElement {
    @wire(getContactList) contacts;

}

FetchContact.cls

public with sharing class FetchContact {
    @AuraEnabled(cacheable=true)
    public static List<Contact> getContactList() {
        return [
            SELECT Id, Name
            FROM Contact
            LIMIT 5
        ];
    }
}

wireTestingApp.app

<aura:application>
<c:wireExample></c:wireExample>
</aura:application>

Output:

wire in lwc
For details on how to wire apex method to a function and how to call a method imperatively please visit below blog posts.



8 comments: