Tuesday, December 10, 2019

Generate Random String in Apex

public static String generateRandomString() {
        final String chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
        String randStr = '';
        while (randStr.length() < 5) {
           Integer idx = Math.mod(Math.abs(Crypto.getRandomInteger()), chars.length());
           randStr += chars.substring(idx, idx+1);
        }
    system.debug('Value----'+randStr); 


    }

Thursday, November 21, 2019

Get current user Info :

Lightning Controller : var currentUserId = $A.get("$SObjectType.CurrentUser.Id");

Apex : User userObj = [SELECT Id, Name, UserName FROM User WHERE Id =:userInfo.getUserId()];

Friday, November 15, 2019


Assign Tasks to different members in a Queue using RoundRobin technique

Integer IntrandomNumber = Integer.valueof((Math.random() * 1000));
for{
 Group grp = [SELECT Id, Name, Type, (SELECT Id, UserOrGroupId,   GroupId FROM GroupMembers) FROM Group WHERE DeveloperName ='<Name_of_queue>' AND Type =: 'Queue' LIMIT 1];

  if(grp != null && grp.GroupMembers != null &&       !grp.GroupMembers.isEmpty()){
  Integer userIndex = Math.mod(IntrandomNumber,       grp.GroupMembers.Size());
  task.OwnerId = grp.GroupMembers.get(userIndex).UserOrGroupId;
}
IntrandomNumber = IntrandomNumber+1;

}

Wednesday, October 30, 2019

Custom Notifications in Lightning

Sometimes we come up with the scenario when we need to assign Tasks to multiple users or users from the Queue or Groups.
But this functionality is not available in Configuration, i.e. Point-and-Click, so achieve this we need to go for code (link).
Idea can be found at Link.

The Lightning experience has a solution : 
The Lightning experience comes up with a functionality called - Custom Notifications under Setup --> Home.



Let us say, we have a requirement in an organization that Sales team (the team members might be a part of a public group or a queue) needs to be notified (through task, not possible without code, or using Custom Notifications in Lightning) whenever the Stage is Prospecting.

This can be achieved using Process Builder :



Once "Send Custom Notification" is selected, give some value in the Action Name. The Notification Type populates the value of the Custom Notification created earlier on Setup -> Home page.


The Notification Type gives us the ability to assign the Custom Notification to a variety of User types, ranging from Owner, User to Group, Queue, Account Team, Opportunity Team.




Sunday, September 29, 2019

Preview Files/Attachments in Lightning Web Components (LWCs)

--------------------- TestClass.cls --------------------------

//to fetch all files in an org
@AuraEnabled(cacheable=true)
public static List<ContentDocumentLink> getFiles(){
    return [Select Id, ContentDocumentId From ContentDocumentLink];
}

//to fetch files related to a specific record
@AuraEnabled(cacheable=true)
public static List<ContentDocumentLink> getFilesFromSpecificRecord(sObject sObjId){
    return [Select Id, ContentDocumentId From ContentDocumentLink WHERE LinkedEntityId =:sObjId];
}

------------------- fetchFilesFromOrg.js -----------------
/* eslint-disable no-console */
/* eslint-disable no-unused-vars */

import { LightningElement, track , wire} from 'lwc';
import { NavigationMixin, CurrentPageReference } from 'lightning/navigation';
import getFiles from '@salesforce/apex/TestClass.getFiles';

export default class fetchFilesFromOrg extends NavigationMixin(LightningElement) {
@track data;
        @wire(getFiles,{})
        rec({error,data}){
         if(data){
            var result =[];
            for(var i=0; i<data.length; i++){
                result.push(data[i].ContentDocumentId);
            }
            this.data=result;
         }if(error){
             console.log("error while fetching files from org");
         }
        }

navigateToWebPage(event) {
var fileId = event.target.title;
this[NavigationMixin.Navigate]({
                type: 'standard__namedPage',
                attributes: {
                    pageName: 'filePreview'
                },
                state : {
                   selectedRecordId: fileId
                }
              })
}
}
}

------------------ fetchFilesFromOrg.html -----------------------

<template>
<lightning-card>

<template for:each={data} for:item='item'>
<tr key={item.Id}>
<td><a> <lightning-formatted-rich-text  title={item} value={item} onclick={navigateToWebPage}></lightning-formatted-rich-text> </a></td>
</tr>
    </template>

</lightning-card>
</template>

This shows up like this:

Wednesday, September 25, 2019

System.QueryException: Non-selective query against large object type (more than 200000 rows)

Always try to use WHERE clause to query results, this limits down the number of records getting fetched and thus avoid this error.

Best practice - use indexed fields in WHERE clause.

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

Wednesday, July 31, 2019

PubSub event in Lightning Web Component 


Description : Event is used when we have to send some data from one component/LWC to the other. 
When the relationship between two components is Parent-Child, we can send data directly using regular events, discussed in the post. But when we have the Sibling-relationships, i.e. the two components are not linked with each-other but one of them needs inputs from the other for some operations, we need the Pub-Sub (Publisher-Subscriber) event-model.

For pub-sub model to be executed, make sure both the components are on the same DOM.


--------------- pubSub.js (a stand-alone LWC) ---------------

/**
 * A basic pub-sub mechanism for sibling component communication
 *
 * TODO - adopt standard flexipage sibling communication mechanism 
        when it's available.
 *
 * Temporarily removing all the pageRef checking in pubsub - not 
    supported in communities
 * https://salesforce.stackexchange.com/questions/252021/
    lightning-web-component-use-publish-subscribe-event-in-community-cloud
 * https://gist.github.com/kmesic/262887799fb70be94707cb0b87936e7b
 */

const events = {};

/**
 * Registers a callback for an event
 * @param {string} eventName - Name of the event to listen for.
 * @param {function} callback - Function to invoke when said event is fired.
 * @param {object} thisArg - The value to be passed as the this parameter to the 
    callback function is bound.
 */
const registerListener = (eventNamecallbackthisArg=> {

    if (!events[eventName]) {
        events[eventName] = [];
    }

    const duplicate = events[eventName].find(listener => {
        return listener.callback === callback && 
                listener.thisArg === thisArg;
    });

    if (!duplicate) {
        events[eventName].push({ callbackthisArg });
    }
};

/**
 * Unregisters a callback for an event
 * @param {string} eventName - Name of the event to unregister from.
 * @param {function} callback - Function to unregister.
 * @param {object} thisArg - The value to be passed as the this parameter 
    to the callback function is bound.
 */
const unregisterListener = (eventNamecallbackthisArg=> {
    if (events[eventName]) {
        events[eventName] = events[eventName].filter(
            listener =>
            listener.callback !== callback || listener.thisArg !== thisArg
        );
    }
};

/**
 * Unregisters all event listeners bound to an object.
 * @param {object} thisArg - All the callbacks bound to this object will
     be removed.
 */
const unregisterAllListeners = thisArg => {
    Object.keys(events).forEach(eventName => {
        events[eventName] = events[eventName].filter(
            listener => listener.thisArg !== thisArg
        );
    });
};

/**
 * Fires an event to listeners.
 * @param {object} pageRef - Reference of the page that represents the
     event scope.
 * @param {string} eventName - Name of the event to fire.
 * @param {*} payload - Payload of the event to fire.
 */
const fireEvent = (eventNamepayload=> {
    if (events[eventName]) {
        const listeners = events[eventName];
        listeners.forEach(listener => {
            try {
                listener.callback.call(listener.thisArgpayload);
            } catch (error) {
                // fail silently
            }
        });
    }
};
const utility = {
    navigateToPage: (pageNameurlParams = ""=> {
        window.open(`/er/s/${pageName}?${urlParams}`'_self');
    }
};

var sharedDataForLeads = {};
export {
    registerListener,
    unregisterListener,
    unregisterAllListeners,
    fireEvent,
    utility,
    sharedDataForLeads
};

--------------- Sibling 1 (firing the Event) ---------------

.html -->>

<!--firing the event at some onclick/onchange event : -->
<template>
    <lightning-card>
        <lightning-input value={datVal} onchange={setInputVal} 
            label="The msg\">
        </lightning-input>
    </lightning-card>
</template>
.js -->>

import { LightningElement } from 'lwc';
import { fireEvent } from 'c/pubSub';

export default class PubsubFireCmp extends LightningElement {

    datVal = '';

    setInputVal(event){
        this.datVal = event.detail.value;

        fireEvent('msg'this.datVal);
        //msg -> an arbitary event name
        console.log(" ->> event fired ");
    }
}


--------------- Sibling 2 (subscribing the Event) ---------------

.html -->>
<template>
    <lightning-card>
        The message is : {myMsg}
    </lightning-card>
</template>
.js -->>

import { LightningElementwire } from 'lwc';
import { CurrentPageReferenceNavigationMixin } from 
        'lightning/navigation';
import {  registerListener } from 'c/pubSub';

export default class PubsubHandleCmp extends 
                NavigationMixin(LightningElement) {

    @wire(CurrentPageReferencepageRef;

    connectedCallback() //the subscriber method to be added 
                        inside connectedCallback method
    {
        registerListener('msg',this.getVal,this);
        //'msg' is the same event name being fired
        //getval is the method using the event data for business operations
    }

    myMsg = '';
    getVal(val    //val is the data sent during the event
                    component
    {
        this.myMsgval;
        console.log('message '+this.myMsg);
    }
}

Monday, July 29, 2019

Call Custom Labels in Apex:

String getLabel = Label.Label_API_Name;

Call Custom Labels in Lightning Component:

{!$Label.c.Label_API_Name}

Call Custom Labels in Lightning Javascript Controller:

var getLabel = $A.get(“{!$Label.c.Label_API_Name}”);

Tuesday, July 23, 2019

Parent-Child Communication in LWC


Sometimes we need data to be flown from Child-LWC to the parent (achieved through event), while sometimes we require data to be flown from parent to the child.


Here we deal with the flow from Parent (parentLWC) to Child (childLWC) :


***parentLWC***

html


<div title="Child LWC">

          <c-child-L-W-C clientid={records1}></c-vij-L-W-C>

</div>



***childLWC***

html


<template>

        <lightning-card title="Child Clientssss" icon-name="custom:custom14">

                <template if:true={bool}>

                <template for:each={newData} for:item="row" for:index="index" >

                       <------- show data ------->

                </template>

                </template>

         </lightning-card>

</template>


---
JS
---


import { LightningElement,wire, track, api } from 'lwc';


export default class childLWC extends LightningElement {

 @track newData=[];

 @track bool=false;

 @api

 get clientid() {

  // eslint-disable-next-line no-console

  return this._clientid;

 }


  set clientid(value) {

  if(value){

   this._clientid = value;

   for(var i=0; i<value.length; i++){

    this.bool=true;

    this.newData.push(value[i]);

   }

  }

  else{

   this.bool=false;

   this._clientid = undefined;

   this.newData = [];

  }

 }

}