Thursday, October 1, 2020

Dynamic table in LWC

Sometimes we come across scenarios when we need dynamic table where we have dynamic number of columns as well as rows.

One such was to display the Profiles with different users assigned to it in an org in Lightning Web Component (LWC).


pivotTable.html

<template>
    <div if:true={isLoading} class="cstm-spinner"> 
        <lightning-spinner alternative-text="Loading...">
        </lightning-spinner>
    </div>
    <div if:false={isLoading}>
        <table 
            class="slds-table slds-table_cell-buffer slds-table_bordered 
                    slds-max-medium-table_stacked-horizontal">
                   <thead>
                     <th class="" scope="col">
                       <div class="slds-truncate">
                        User
                        <lightning-icon if:false={val} 
                                icon-name="utility:down" 
                                size="x-small">
                        </lightning-icon>
                        /Profile
                        <lightning-icon if:false={val} 
                                icon-name="utility:right" 
                                size="x-small">
                        </lightning-icon></div>
                      </th>
                     <template for:each={profiles} for:item='prof' >
                       <th class="" scope="col" key={prof}>
                        <div class="slds-truncate" title={prof}>
                            {prof}
                        </div>
                        </th>
                      </template>
                      </thead>
                      <tbody>
                        <template for:each={users} for:item='user' >
                          <tr key={user.name}>
                            <td key={user.name} >
                                {user.name}
                            </td>
                            <template for:each={user.chex} for:item='val' >
                              <td class="" key={val} 
                                style="text-align: center;">
                                <lightning-icon if:true={val} 
                                    icon-name="utility:check" 
                                    variant="success" 
                                    size="small"></lightning-icon>
                                <lightning-icon if:false={val} 
                                    icon-name="utility:close" 
                                    variant="error" 
                                    size="xx-small"></lightning-icon>
                               </td>
                            </template>
                           </tr>
                          </template>
                       </tbody>
                     </table>
                    </div>
</template>

pivotTable.js

import { LightningElement } from 'lwc';
import getUserProfiles from '@salesforce/apex/pivotTableController.
                                getUserWithProfiles';

export default class PivotTable extends LightningElement {

    result = [];
    profiles = [];
    users = [];
    isLoading = true;

    connectedCallback(){
        getUserProfiles()
        .then(result =>{
            this.profiles = result[0].profiles;
            result.forEach(element => {
                this.users.push({
                    'chex' : element.isUserForProf,
                    'name' : element.userName
                });
            });
            this.isLoading = false;
        })
        .catch(error =>{
            console.log("error");
            this.isLoading = false;
        });
    }
}

pivotTableController.cls

public without sharing class pivotTableController {
    @AuraEnabled(cacheable=true)
    public static List<userProfWrappergetUserWithProfiles(){
        List<Userusers = [SELECT IdProfileIdProfile.Name
                            firstNamelastName, Name 
                            FROM User];
        List<Profileprofs = [SELECT IdName
                                      (SELECT Id,firstNamelastName 
                                       FROM Users
                               FROM Profile 
                               ORDER BY Name];
        List<userProfWrapperwrapperResult = new List<userProfWrapper>();
        List<Stringprofiles = new List<String>();
        for(User user : users){
            userProfWrapper wrapper = new userProfWrapper();
            List<Booleanbools = new List<Boolean>();
            String userName = '';
            for(Profile profile : profs){
                if(!profile.users.isEmpty()){
                    if(!profiles.contains(profile.Name))
                        profiles.add(profile.Name);
                    if(user.profileId == profile.Id)    
                        bools.add(true);
                    else    
                        bools.add(false);
                    userName = user.name;
                }
            }
            wrapper.isUserForProf = bools;
            wrapper.profiles = profiles;
            wrapper.userName = userName;
            wrapperResult.add(wrapper);
        }
        return wrapperResult;
    }

    public class userProfWrapper{
        @AuraEnabled
        public List<Stringprofiles;
        @AuraEnabled
        public List<BooleanisUserForProf;
        @AuraEnabled
        public String userName;
    }
}

Saturday, September 5, 2020

Lightning-Map demo in Lightning Web Component (LWC)




currentLocationLWC.html
<template>
    <lightning-card>
        <lightning-layout>
            <lightning-layout-item class="slds-p-left_small">
                <lightning-icon icon-name="action:map" 
                                size='small' 
                                variant='success' 
                ></lightning-icon>
            </lightning-layout-item>
            <lightning-layout-item>
                <p class="slds-p-horizontal_small slds-m-top_small" 
                   style="color: #87CEFA">
                    <b>
                        Mark your current location and destination on Map
                    </b>
                </p>
            </lightning-layout-item>
        </lightning-layout>
        <lightning-layout>
            <lightning-layout-item size="4" 
                                   padding="around-small" 
                                   large-device-size="4">
                <p style="font-size: 14px; color: #800000">
                    <b>Enter a destination</b>
                </p>
                <p>
                    <lightning-input value={street} 
                                     data-field="Street" 
                                     variant="label-hidden" 
                                     placeholder="Street/Locality" 
                    ></lightning-input>
                    <lightning-input value={city} 
                                     data-field="City" 
                                     variant="label-hidden" 
                                     placeholder="City" 
                    ></lightning-input>
                    <lightning-input value={pincode} 
                                     data-field="Pincode" 
                                     variant="label-hidden" 
                                     placeholder="Pincode" 
                    ></lightning-input>
                    <lightning-input value={state} 
                                     data-field="State" 
                                     variant="label-hidden" 
                                     placeholder="State" 
                    ></lightning-input>
                    <lightning-input value={country} 
                                     data-field="Country" 
                                     variant="label-hidden" 
                                     placeholder="Country" 
                    ></lightning-input>
                </p><br/>
                <lightning-button variant="brand" 
                                  onclick={markDestination} 
                                  label="Mark my Destination" 
                ></lightning-button>
            </lightning-layout-item>
            <lightning-layout-item size="8" 
                                   padding="around-small" 
                                   large-device-size="8">
                <lightning-map map-markers={lstMapMarkers} 
                               zoom-level={zoomLevel} 
                ></lightning-map>
            </lightning-layout-item>
        </lightning-layout>
    </lightning-card>
</template>

currentLocationLWC.js:
import { LightningElement } from 'lwc';

export default class CurrentLocationLWC extends LightningElement {
    lstMapMarkers = [];
    zoomLevel = 5;
    street = '';
    city = '';
    pincode = '';
    state = '';
    country = '';
    latitude = '';
    longitude = '';

    connectedCallback(){
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(position => {
                this.latitude = position.coords.latitude;
                this.longitude = position.coords.longitude;

                this.lstMapMarkers = [{
                    location : {
                        Latitude : this.latitude,
                        Longitude : this.longitude
                    },
                    title : 'This is your current location'
                }];
            });
        }
    }

    markDestination(){
        this.street = this.template.querySelector("[data-field='Street']")
                      .value;
        this.city =  this.template.querySelector("[data-field='City']")
                     .value;
        this.pincode = this.template.querySelector("[data-field='Pincode']")
                    .value;
        this.state = this.template.querySelector("[data-field='State']")
                     .value;
        this.country = this.template.querySelector("[data-field='Country']")
                       .value;

        let destinationVar = {
            Street: this.street,
            City: this.city,
            PostalCode: this.pincode,
            State: this.state,
            Country: this.country,
        }

        this.lstMapMarkers = [
            {
                location : {
                    Latitude : this.latitude,
                    Longitude : this.longitude
                },
                title : 'This is your current location'
            },
            {
                location : {
                    Street: this.street,
                    City: this.city,
                    PostalCode: this.pincode,
                    State: this.state,
                    Country: this.country
                },
                title : 'This is your destination'
            }];
    }
}

Saturday, April 18, 2020

Create and Use Map in a Lightning Component




Our Org has email addresses of Contacts Users in the format of FirstName.LastName@companyDomain.

We have a requirement to show the FirstName.LastName of the users on a lightning Component as a table.

Apex Class (testClass.apxc):

@AuraEnabled
    public static List<User> getUsers(){
        return [SELECT Id, Name, Email FROM User LIMIT 10];
    }

Lightning Component (testCMP):
.cmp

<aura:component controller="testClass" implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,force:lightningQuickAction" access="global" >

<aura:attribute name="myMap" type="Map"/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    <lightning:card>
<table class="slds-table slds-table_cell-buffer slds-table_bordered slds-max-medium-table_stacked-horizontal">
<thead>
<tr class="slds-line-height_reset">
<th class="" scope="col">
<div class="slds-truncate" title="ID">ID</div>
</th>
      <th class="" scope="col">
<div class="slds-truncate" title="Email">Email</div>
</th>
<th class="" scope="col">
<div class="slds-truncate" title="Username">FirstName.LastName</div>
</th>
</tr>
</thead>
<tbody>
<aura:iteration items="{!v.myMap}" var="mapvar" indexVar="key">
<tr data-target-id = 'eachRow' class="slds-hint-parent">
                            <td data-label="Id">
<div class="slds-truncate" title="Id">{!mapvar.key.Id}</div>
</td>
<td data-label="Email">
<div class="slds-truncate" title="Email">{!mapvar.key.Email}</div>
</td>
<td data-label="Username">
<div class="slds-truncate" title="FirstName.LastName">{!mapvar.value}</div>
</td>
</tr>
     </aura:iteration>
</tbody>
</table>
    </lightning:card>
</aura:component>

.controller.js

({
doInit : function(component, event, helper) {
var action = component.get("c.getUsers");
                action.setCallback(this, function(response){
                if(response.getState() == "SUCCESS"){
                    var result= response.getReturnValue();
                    var lst = [];
                    for(var i=0; i<result.length; i++){
                        let username = result[i].Email.split('@')[0];
                        lst.push({value:username, key:result[i]});
                    }
                   component.set("v.myMap", lst);
               }
           });
         $A.enqueueAction(action);
}
})


Monday, March 30, 2020

Component to fetch and display Country-wise COVID19 Data in Lightning Web Component


                 Note: The Data is being fetched from the public API (Click here for reference). 




Components:

Covid19Data - Apex class for making callouts.
covid19LWC - Lightning Web Component for displaying the data from the callout.
Endpoint_Covid19 - Remote Site Settings to enable our Salesforce org to make callouts to the desired endpoint.
COVID 19 Data - Lightning Tab to accommodate covid19LWC.


-------------------- Covid19Data.apxc -----------------------

public class Covid19Data {

    @AuraEnabled(cacheable=true)
    public static List<wrapperData> getCovid19SummaryData(){
        
        List<wrapperData> returnVal = new List<wrapperData>();
        
        http h = new http();
        httprequest req = new httprequest();
        req.setEndpoint('https://api.covid19api.com/summary');
        req.setHeader('Accept', 'application/json');
        req.setMethod('GET');
        req.setTimeout(12000);
        
        httpresponse res = h.send(req);
        
        if (res.getStatusCode() == 200) {
            Map<String, Object> responseResult = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
            List<Object> objects = (List<Object>) responseResult.get('Countries');
            for(Object obj : objects){
                wrapperData wrapperObj = new wrapperData();
                String strResult = JSON.serialize(obj);
                wrapperObj = (wrapperData) JSON.deserialize(strResult, wrapperData.class);
                if(String.isNotBlank(wrapperObj.Country)) returnVal.add(wrapperObj);
            }
        }
        return returnVal;
    }
    
    public class wrapperData{
        @AuraEnabled
        public string Country;
        @AuraEnabled
        public integer NewConfirmed;
        @AuraEnabled
        public integer TotalConfirmed;
        @AuraEnabled
        public integer NewDeaths;
        @AuraEnabled
        public integer TotalDeaths;
        @AuraEnabled
        public integer NewRecovered;
        @AuraEnabled
        public integer TotalRecovered;
    }
}


Tuesday, February 4, 2020

Guided Action in Salesforce

Guided Actions, in Lightning, help a user to get more insights while working on a complex business process and such that the data being captured is per the requirements and also, when more than one user/team (group/queue) are working on the same record one after the other.

Guided Actions are added under the component name - "Actions & Recommendations" in Lightning App Builder.
NOTE: This doesn't show up on Home Page



The Guided Action is invoked through Process Builder by creating a record of type RecordAction, the type can be a QuickAction or a Flow (we are dealing with Flow type here):
The various fields used are:
Action : Flow API Name
Action Type : Flow (Used) / QuickActions
Order : the order in which you want to show the Action type (when more than one Guided Action is to be shown)
Parent Record Id : The record on which the flow actions  would be saved on completion
Hide/Remove Action in UI : When False, user doesn't have the option to Hide the Action from Page
Pinned : To pin the action on UI
Is Mandatory : This comes up with an Asterisk mark before the Action, shown as Mandatory, when True.


When the condition is met, the Guided Action shows the Flow type on UI, as below:




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); 


    }