Tuesday, August 13, 2019

Navigation from one LWC to another LWC

Sometimes we need to navigate to some other pages (record page, home page, components etc) in lightning, the same applies to Lightning Web Component as well.
For navigation from one LWC to the other, we need to create a lightning component (aura - component), which would implement isUrlAddressable interface and embed the other 
LWC inside this aura-component.

For an instance, on click of a button on cmp1, we need to navigate to the LWC cmp2 -

We will create an aura component - navAuraCmp, which will embed cmp2 :

--------------------- navAuraCmp.cmp --------------------------

<aura:component implements="lightning:isUrlAddressable">
<!-- implementing isUrlAddressable interface -->
    <aura:attribute name="recId" type="String"/>
    <aura:handler name="init" value="{!this}" action="{!c.init}"/>
    <aura:handler name="change" value="{!v.pageReference}" action="{!c.reInit}" />
<!-- for the data to refresh everytime a new recId is passed -->
             Id ==> {!v.cmp2}
             <c:cmp2 recId="{!v.recId}"></c:cmp2>
</aura:component>

------------------- navAuraCmpController.js -----------------

({
init: function(component, event, helper) {
        var myPageRef = component.get("v.pageReference");
        var rId = myPageRef.state.c__recId;
        component.set("v.recId", rId);
    },
    
    reInit : function(component, event, helper) {
        $A.get('e.force:refreshView').fire();
    }
})


-------------------------- cmp1 --------------------------
.html:

<template>
 <td>
 <div>
 <p style="width:130px"></p>
  <lightning-button value={item.Id} onclick={aButton} label="Click me">
  </lightning-button>
 </div>
 </td>
</template>

.js:

import { LightningElement, track, wire, api } from 'lwc';
import { NavigationMixin } from 'lightning/navigation';
//import NavigationMixin in the LWC
export default class cmp1 extends NavigationMixin(LightningElement) {

aButton(event){
        var val = event.target.value;
        console.log(" --->>> -- "+val);
        
        this[NavigationMixin.Navigate]({
            type: "standard__component",
            //when navigating to a component

            attributes: {
              componentName: "c__navAuraCmp"
              //c__<aura_component_name>
        },
        state: {
                              //state is used to pass the data
             c__recId: val
                             //the attribute <recId> on the navAuraCmp
       }
       });
    }
}

-------------------------- cmp2 --------------------------
.html:

<template>
{recId}
</template>

.js:

import { LightningElement, track, wire, api } from 'lwc';
export default class cmp2 extends LightningElement {
    @api
    //getter method
    get recId() {
        return this._recId;
    }
    //setter method
    set recId(value) {
       if(value){
            this._recId = value;
       }else{
            this._recId = undefined;
       }
}

Wednesday, August 7, 2019

Communication from Child Lightning Web Component to the Parent LWC through event

Lightning Web Components work in similar ways as the Lightning Components, where data is sent from Parent component to the Child, discussed here and also from the Child to the Parent through events.

The scenario in discussion here is : We have some Account records in a table on the Child component, we need the Name of the selected Account on the Parent component.

--------------- Child LWC ---------------

.html :

<template>
 <lightning-card title="Child CMP" icon-name="custom:custom4">
                
  <table class="slds-border_top slds-border_bottom slds-border_right slds-border_left slds-table slds-table_bordered slds-table_striped slds-table_cell-buffer slds-table_fixed-layout">
                        
   <thead  >
     <tr class= "slds-line-height_reset" style="width:5000px">
       <th scope="col" style="background-
       color:rgb(84,105,141);width:120px">
       <div class="Greetingdetail1"   title="">
        <p style="color:white;">Select</p></div></th>
       <th scope="col"   style="background-
        color:rgb(84,105,141);width:120px">
       <div class="Greetingdetail1"   title="">
       <p style="color:white;">Account Name</p></div></th>
    </tr>
   </thead>

 <template for:each={fetchedAccounts} for:item='item'>
  <tbody key={item.value}>
   <tr >    
    <td>
     <lightning-input type="radio" name={item.Name} 
     value={item.Id} onclick={eventtrigger}></lightning-input>
    </td>
    <td style="width:1px;white-space:nowrap;">
    <div class="Greetingdetail" title="" >
     <p style="width:120px">{item.Name}</p>
    </div>
    </td>
   </tr>
  </tbody>
 </template>
 </table>
 </lightning-card>
</template>

.js :

import { LightningElement, wire, track, api } from 'lwc';
import accounts from '@salesforce/apex/AccountHandler.fetchAccounts';
//fetchAccounts is the method on AccountHandler class
export default class ChildLWC extends LightningElement {

    @track fetchedAccounts = [];
    @wire(accounts,{})
    records({error,data}){
     if(data){
         for(var i=0; i<data.length; i++){
            this.fetchedAccounts.push(data[i]);
        }
      if(error){
        this.fetchedAccounts= [];
      }
     }
    }

 @track dataOnChild;
 eventtrigger(event){
     var data = event.currentTarget.name;
     // eslint-disable-next-line no-console
     console.log("-->> "+ data);
     this.dispatchEvent(new CustomEvent
      ('childevent', {detail: data})
     );
 //childevent is the name of the event getting fired to send the
   //Account Name of the selected record
 //Note: Always use the lower-case letters for the event name.
 }

}


--------------- Parent LWC ---------------

.html :

<template>
    <lightning-card title="ParentLWC" icon-name="custom:custom3">
<lightning-card icon-name="custom:custom92">
 <b><h1>
  <lightning-formatted-text value={dataFromChild}>
  </lightning-formatted-text>
 </h1></b>
    </lightning-card>
    <div>
        <c-child-L-W-C onchildevent={getDataFromChild}>
        </c-child-L-W-C>
 <!-- add "on" before the event name on child component 
 the getDataFromChild method is called when the event is registered on the Parent componenet -->
    </div>
   </lightning-card>
</template>

.js :

import { LightningElement, track, wire } from 'lwc';
export default class ParentLWC extends LightningElement {
@track dataFromChild;
    getDataFromChild(event){
        // eslint-disable-next-line no-console
        console.log("-->> "+event.detail);
        this.dataFromChild = event.detail;
    }
}

Details available at:
https://developer.salesforce.com/docs/component-library/documentation/lwc/events_create_dispatch

Tuesday, August 6, 2019

Parent to Child communication in Lightning Web Components

The first being data-flow from Parent to the child :
In our scenario, we have one parent, say parentLWC, and the other child, say childLWC.

-------------------- parentLWC -------------------- 

.html :

<template>
<lightning-input label="VALUE" value={donchild} onchange={setValue}>
</lightning-input>
        <template if:true={donchild}>

<!-- the first donchild is the attribute on child which gets value from the value on parent {donchild}. Remember to make the attribute in lower-cases only -->

<c-child-L-W-C donchild={donchild}></c-child-L-W-C>
         </template>
</template>

.js :

import { LightningElement, track, wire } from 'lwc';
export default class HelloWorld extends LightningElement {

     @track donchild;
     setValue(event) {
        this.donchild = event.target.value;
        // eslint-disable-next-line no-console
        console.log("-->data>>> "+this.donchild);
    }
}

-------------------- childLWC -------------------- 

.html :

<template>
        <lightning-card title="Child CMP" icon-name="custom:custom14">
            {donchild}
        </lightning-card>
</template>

.js :

import { LightningElement, track, api } from 'lwc';
export default class ChildLWC extends LightningElement {

    @api //annotate with @api to fetch the attribute value
    get donchild() { //getter method
        return this._donchild;
    }

  set donchild(value) { //setter method
  if(value){
      // eslint-disable-next-line no-console
      console.log("-- "+value);
      this._donchild = value;
  }
  else{
      this._donchild = undefined;
  }
 }
}

More Documentation available at : https://developer.salesforce.com/docs/component-library/documentation/lwc/lwc.create_components_data_binding