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