Sunday, 14 June 2020

ES6 Spread Notation for LWC


The spread operator is three dots (...) preceding an array.
The spread operator is a new way to add elements to an array without mutating.

Push Vs Spread 

push    - mutates the original data.
spread  - does not mutate the original data.


<template>
  <lightning-card title="HelloWorld" icon-name="custom:custom14">
      <div class="slds-m-around_medium">
          <template for:each={contacts} for:item="contact">
              <li key={contact.id}>
                  {contact.name}, {contact.title}
              </li>
          </template>
          <lightning-button variant="base" label="Base" title="Base action" onclick={handleClick} class="slds-m-left_x-small"></lightning-button>
      </div>
  </lightning-card>
</template>


import { LightningElement, track } from 'lwc';

export default class HelloWorld extends LightningElement {
    @track contacts = [
        {
            id: 1,
            name: 'Amy Taylor',
            title: 'VP of Engineering',
        },
        {
            id: 2,
            name: 'Michael Jones',
            title: 'VP of Sales',
        },
        {
            id: 3,
            name: 'Jennifer Wu',
            title: 'CEO',
        },
    ];
    lastId = 3;
    
    handleClick() {
        const id = this.lastId + 1;
        const contact = {
            id,
            name: 'New Name',
            title: 'New Title',
        };
        this.lastId = id;
        this.contacts = [...this.contacts, contact];
    }
}


Note : 
1.Recreates the array with the new value.
2.Refreshes reactive variables the same way a @track variable does when changing its value.


ex 2 :

<template>
    
    <lightning-datatable
                key-field="id"
                data={data}
                columns={columns}
                is-loading={tableLoadingState}>
            </lightning-datatable>

 <lightning-button variant="brand" label="Add row" title="Add row" onclick={addRow} class="slds-m-left_x-small"></lightning-button>
</template>

import { LightningElement, track } from 'lwc';
const columns = [
    { label: 'Label', fieldName: 'name', type:"text"},
    { label: 'Website', fieldName: 'website', type: 'text' },
    { label: 'Phone', fieldName: 'phone', type: 'text'  }
];
export default class App extends LightningElement {
    @track data = [{name:'Mylabel' , website:'google.com' ,phone :'74126478963',amount : 45  }];
    @track columns = columns;
    @track tableLoadingState = false;

    addRow(){
          const newdata = {            
            name: 'Mylabel2s',
            website:'2google.com',
phone :'74126478963',
amount : 45
        };  
      // spread Operator
        this.data = [...this.data ,newdata ];

    }
   
}

Saturday, 28 March 2020

Conditional rendering in Ligthing web component

To render a DOM element in a template only when certain conditions are met,we use conditional rendering.

1.Render element only when condition evaluates to true.

 syntax : <template if:true={propertyName}></template>

2.Render element only when condition evaluates to false.

 syntax : <template if:false={propertyName}></template>

Note :
1.LWC will not support conditional operators or expression
evolution methods in markup.
2.Directives are only allowed on a template element.

ex :
  <template>
    <lightning-card title="Conditional Rendering">
        <div class="slds-p-around_small">
        <lightning-input type="checkbox" label="Check" checked={flag} onchange={handleChange}>          </lightning-input>
            <br></br>
        <template if:false={flag}>
            <div class="slds-p-around_small">POSITIVE SCENARIO</div>
        </template>
        <template if:true={flag}>
            <div class="slds-p-around_small" >NEGATIVE SCENARIO</div>
        </template>
      </div>
    </lightning-card>
</template>

  import { LightningElement, track } from 'lwc';
  export default class ConditionalRendering extends LightningElement {
    @track flag = false;

    handleChange(event) {
        this.flag = event.target.checked;
    }
}

HTML5 Attributes in Lightning web components

HTML5 Attributes or data Attributes in LWC
================================

1.The data-* attributes is used to store custom data private to the page or application.
2.The data-* attributes gives us the ability to embed custom data attributes on all HTML elements.
3.The data-* attributes consists of two parts

a. The attribute name should not contain any uppercase letters,and must be at least one character long after the prefix "data-".
b. The attribute value can be any string.

Note : Custom attributes prefixed with "data-" will be completely ignored by the user agent.

ex 1 :

<button data-mylabel="html-demo" onclick={handleClick} class="slds-mleft_x-small"> CLICK </button>

import {LightningElement,track} from 'lwc';
export default class Attributes extends LightningElement{
   @track clickedLabel;
 
   handleClick(event){
     this.clickedLabel=event.target.dataset.mylabel;
   }
}

ex 2 :
<a onclick={handleClick} data-target-id="overview">Overview</a>

handleClick(event){
 let targetId=event.target.dataset.targetId;
}

ex 3 :
 we can use data- attributes to select an element.In LWC we use only querySelector or querySelectorAll for getting/selecting
 elements(s). 

 select the input and set the value.

<lightning-input data-my-id="myinput" class="second-class"></lightning-input>

this.template.querySelector("lightning-input[data-my-id=myinput]").value = "Some Value";

Friday, 28 February 2020

Shadow DOM in LWC

 DOM stands for Document Object Model.Lightning web component use the shadow DOM.
 
   The element in each lightning web component are encapsulated in a
   shadow tree.This part of the DOM is called a shadow tree because it's
   hidden from the document that contains it.The shadow tree affects how
   you work with css,events and the DOM.
 
   Shadow DOM is a web standard that encapsulates the elements of a component
   to keep styling and behavior consistent in any context.
   Since not all browsers that Salesforce supports implement shadow DOM, LWC
   uses a shadow DOM polyfill.
   A polyfill is code that allows a feature to work in a web browser.
 
   The Shadow DOM have three primary effects
   1.DOM access
   2.CSS isolation
   3.event propagation
 
   Shadow DOM basics :

 
   1.Shadow host : The regular DOM node that the shadow DOM is attached to.
                    it hosts the shadow root.
   2.Shadow root : The root node of the shadow tree.
   3.shadow tree : the DOM tree inside the shadow DOM.
   4.shadow boundary : the place where the shadow DOM ends,and the regular DOM begins.

Sunday, 26 January 2020

Lightning Web Component lifecycle hooks

A lifecycle hook is a callback method triggered at a specific phase of a component instance's lifecycle.

1.constructor()

-> Constructor is invoked when the component is created.
-> since flow is from parent to child, do not access child elements in the component body because they don't exist yet.
-> First Statement must be super() with no parameters.

2.connectedCallback()

-> Connectedcallback is invoked when the component is inserted into DOM.
-> since flow is from parent to child, do not access child elements in the component body because they don't exist yet.
-> we can access the Parent elements and modify them in this hook.

3.disconnectedCallback()

-> disconnectedCallback is invoked when component is removed from DOM.
-> This hook flows from parent to child.
-> it can fire more than once.

4.render()

-> This hook is used to override the standard rendering functionality.
-> It gets called after connectedCallback() and it returns a valid HTML template.
-> This hook flows from parent to child.
-> It can fire more than once.

5.renderCallback()

-> Called after component is rendered.
-> This hook flows from child to parent.
-> It can fire more than once.

6.errorCallback(error,stack)

-> This hook is called when the component throws an error in one of its hooks.
-> The Error argument is a javascript native error object and the stack argument is a string.
-> This method works like a javascript catch{} block for catching errors.


ex:
/* eslint-disable no-console */
import { LightningElement,api } from 'lwc';
import temp1 from './hooktemp1.html';
import temp2 from './hooktemp2.html';

export default class Lwchooks extends LightningElement {
    @api templateSelected='temp1';
    constructor(){
        super();
        console.log('Inside of Constructor');
    }
    connectedCallback(){
        console.log('Inside of connectedCallback');
    }
    disconnectedCallback(){
        console.log('Inside of disconnectedCallback');
    }
    handleTemplate(){
        if(this.templateSelected==='temp1'){
            this.templateSelected= 'temp2';
        }else{
            this.templateSelected='temp1';
        }
    }
    render(){
       console.log('Inside render');
       if(this.templateSelected==='temp1')
       // return tempalte 1
        return temp1;
       // return tempalte 2
        return temp2;
         
    }
    renderedCallback(){
        console.log('Inside renderedCallback');
    }
    errorCallback(error,stack){
        console.log('Inside error Callback'+ error + stack);
    }
}


<!--hooktemp1.html -->

<template>
    <div> Displayed Template 1 </div>
    <lightning-button label="Show Template 2" onclick={handleTemplate}></lightning-button>
</template>

<!--hooktemp2.html -->

<template>
    <div> Displayed Template 2 </div>
    <lightning-button label="Show Template 1" onclick={handleTemplate}></lightning-button>
</template>

Saturday, 25 January 2020

Lightning web Component Bundle Structure

1.Metadata (XML)
2.javascript
3.HTML
4.Optional CSS and more javascript

HTML Provides the structure for your component.

In LWC, the camel case name of the components are rendered as kebab-case(words separated by hypen) and that component must have a closing tag.

ex :  <template>
         <c-my-component></c-my-component>
      </template>

HTML attributes are in kebab case and its used in LWC for component rendering,calling from one component to another component,Set value attribute name to other component LWC.

Javascript defines the core business logic and event handling.

Js files in LWC are ES6 modules where everything declared in a module is local to the module.

CSS provides the look,feel and animation for your component.


ex :
 <!-- myComponent.html -->
 <template>
    <!-- your markup here -->
 </template>

 //myComponent.js
import { LightningElement, api} from 'lwc';
export default class myComponent extends LightningElement{
  @api prop1;
  @api prop2=false;
}

//myComponent.js-meta.xml

?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>45.0</apiVersion>
<isExposed> true </isExposed>
<masterLabel> LWC Demo </masterLabel>
<description> This is Lightning web component Demo </description>
<targets>
 <target>lightning__AppPage</target>
 <target>lightning__HomePage</target>
 <target>lightning__RecordPage</target>
 <target>lightningCommunity__Default</target>
 <target>lightningCommunity__Page</target>
 <target>lightning__UtilityBar</target>
 <target>lightning__Tab</target>
 <target>lightning__FlowScreen</target>
 <target>lighting__Inbox</target>
 <target>lightning__ChatMessage</target>
</targets>
<targetCongfigs>
 <targetConfig targets="lightning__AppPage, lightning_HomePage">
   <property name="prop2" type="Boolean" />
 </targetConfig>
 <targetConfig targets="lightning__RecordPage">
          <property name="prop1" type="String" />
          <objects>
              <object>Account</object>
              <object>Opportunity</object>
              <object>Warehouse__c</object>
          </objects>
      </targetConfig>
</targetConfigs>
</LightningComponentBundle>

The configuration file defines the metatdata values for the component,including the design configuration for the Lightning App Builder and Community Builder.

Configuration file tags :
=================

apiversion :
=========
A double value that binds the component to a salesforce API version.

description :
=========
A short description of the component, usually a single sentence.Appears in list views, like the list of Lightning Componnets in Setup,and as a tooltip in the Lightning App Builder and in Community Builder.

isExposed :
=========
A Boolean value. Expose the component in all orgs, and in Lightning App Builder and Community Builder.

To Make a component usable in a managed package, set isExposed to true.
To Make a component usable in Lightning App Builder and Community Builder set isExposed to true.

masterLabel :
=============
The title of the component .Appears in list views,like the list of Lightning Components in
Setup, and in the Lightning App Builder and in Community Builder.

Note : If you do not use masterLabel tag in the configuration file, your component name will
default as the label of the component.

targets :
=======
Specifies which type of lightning page the component
can be added to . If you want your component to appear in the
Lightning App Builder or in Community Builder, specify at least
one Lightning Page Type

ex :

<targets>
 <target>lightning__AppPage</target>
</targets>


lightning__AppPage

Enables a component to be used on the Lightning Page of type App Page.

lightning__HomePage

Enables a component to be used on the Lightning Experience Home Page.

lighting__RecordPage

Enables a component to be used on a Lightning record Page.

lighningCommunity__Page

Enables a component to be used on a Lightning community page in community builder.

lightningCommunity__Default

Used together with lightningCommunity__Page.

Enable a component that includes configurable properties to be used on a Lightning community page in community builder.When the component is selected on the page , the properties appear.


targetConfigs :
===============
Configure the component for different page types and define component properties.

Note : A component could have different properties on a record home page than
on the Salesforce Home page or an app page.

targetConfig :
==============
It is subtag of targetConfigs and used for different page type configuration.

Property :
===========
Specifies a public property of a component that can be set in Lightning App Builder App Manager,Lightning Flow Builder or
Community Builder. The component author defines the property in the component's javascript
class using the @api decorator.

ex :

<property name="picklistValue" type="String" datasource="Option One, Option Two, Option Three" />
<property name="stringValue" type="String" placeholder="Type something here..." />
<property name="numberValue" type="Integer" min="0" max="100" default="10" />

property tag supports different attributes such as datasource,default,description,label,max,min etc

name :

Reuired if you're setting properties for your component.The attribute name.This value must match the property name in the component's javascript class.

type : The attribute data type

label : Display as a label for the attribute in the tool.

deafult : The default value for the attribute.

description : Displays as an i-bubble for the attribute in the tool.

datasource : Renders a field as a picklist, with static values.Supported only if the type attribute is String.


objects :
=======
A set of one or more objects the component is supported for.
This tag set works only inside a parent targetConfig that's configured for lightning__RecordPage.
Specify the objects tag set only once inside a targetConfig set.
supports the object subtag.

object :
======
Define which objects the component is supported for.
Use one object tag for each supported object.
You can't use '*' to denote all objects.

Note :
targetConfigs is an optional tag, if you want to restrict the component
to be used for some particular object record page.

Wednesday, 1 January 2020

Application library events in lightning

Open a record create Page :
===========================

It is event which is fired to show the full Record create panel.

To display the record create a page for an object,set the object name
on the entityApiName attribute and fire the event.

recordTypeId is optional and, if provided,specifies the record type for the created
object. defaultFieldValues is optional and if povided, specifies values to use to
prepopulate the create record form.

ex :
createAccount : function(component,event,helper){
  var accountCreate = $A.get(e.force.createRecod');
  accountCreate.setParams({
  "entityApiName":"Account",
  "defaultFieldValues":{
    'Name':'Test Account'
  },
  "recordTypeId":RecTypeID
  });
}

Open a record edit Page :
===========================

editRecord : function(component, event, helper)
    var editRecordEvent = $A.get("e.force:editRecord");
    editRecordEvent.setParams({
      "recordId": component.get("v.contact.Id")
   });
    editRecordEvent.fire();
}

this will open an edit form with pre-populated values from contact record whose id we have passed in controller.

opened edit form is based on the page-layout associated with the record id.

Navigate to a record :
======================
1.force:navigateToList

To navigate to a list view, set the list view ID on the listViewId attribute and fire the event.

gotoList : function (component, event, helper) {
    var action = component.get("c.getListViews");
    action.setCallback(this, function(response){
        var state = response.getState();
        if (state === "SUCCESS") {
            var listviews = response.getReturnValue();
            var navEvent = $A.get("e.force:navigateToList");
            navEvent.setParams({
                "listViewId": listviews.Id,
                "listViewName": null,
                "scope": "Contact";
            });
            navEvent.fire();
        }
    });
    $A.enqueueAction(action);
}

@AuraEnabled
public static List<ListView> getListViews() {
    List<ListView> listviews =
        [SELECT Id, Name FROM ListView WHERE SobjectType = 'Contact'];
     // Perform isAccessible() check here
    return listviews;
}

2. force:navigateToObjectHome

Navigates to the object home specified by the scope attribute.


navHome : function (component, event, helper) {
    var homeEvent = $A.get("e.force:navigateToObjectHome");
    homeEvent.setParams({
        "scope": "myNamespace__myObject__c"
    });
    homeEvent.fire();
}

3.force:navigateToRelatedList

 Navigates to the related list specified by parentRecordId.

gotoRelatedList : function (component, event, helper) {
    var relatedListEvent = $A.get("e.force:navigateToRelatedList");
    relatedListEvent.setParams({
        "relatedListId": "Cases",
        "parentRecordId": component.get("v.contact.Id")
    });
    relatedListEvent.fire();
}

4. force:navigateToSobject

Navigates to an sObject record specified by recordId.


createRecord : function (component, event, helper) {
    var navEvt = $A.get("e.force:navigateToSObject");
    navEvt.setParams({
      "recordId": "00QB0000000ybNX",
      "slideDevName": "related"
    });
    navEvt.fire();
}

5. force:navigateToURL

 Navigates to the specified URL.

 1)   Using a relative URL.

   gotoURL : function (component, event, helper) {
    var urlEvent = $A.get("e.force:navigateToURL");
    urlEvent.setParams({
      "url": "/006/o"
    });
    urlEvent.fire();
}

2)   Using external website when the link is clicked.

navigate : function(component, event, helper) {
 
    //Find the text value of the component with aura:id set to "address"
    var address = component.find("address").get("v.value");
    var urlEvent = $A.get("e.force:navigateToURL");
    urlEvent.setParams({
      "url": 'https://www.google.com/maps/place/' + address
    });
    urlEvent.fire();
}