Saturday, September 28, 2019

File Preview in Lightning Web Component(lwc)

To open one or more file records in Lightning Experience and the Salesforce app, use the navigation service, lightning/navigation.
The navigation service opens the preview of one or more files in a modal dialog in Lightning Experience or triggers a file download in the Salesforce app on mobile devices.

The navigation service uses a PageReference, which describes a page, or in this case, a file.

Use a page reference with 
type: 'standard__namedPage
pageName: 'filePreview'

Page Reference sample
this[NavigationMixin.Navigate]({
        type: 'standard__namedPage',
        attributes: {
            pageName: 'filePreview'
        },
        state : {
            recordIds: '069xx0000000001AAA,069xx000000000BAAQ',
            selectedRecordId:'069xx0000000001AAA'
        }
      })

 recordIds: the property is a comma-separated list of all record IDs(ContentDocumentId) available for download.
 selectedRecordId: the selectedRecordId specifies the record to downloads first.


Example

FilePreviewInLWC.html
<template>
    <lightning-card title="File Preview In Lightning Web Component">
        <template if:true={files}>
            <table class="slds-table slds-table_bordered slds-table_cell-buffer">
                <thead>
                    <tr class="slds-text-title_caps">
                        <th scope="col">
                            <div title="Key">File Name</div>
                        </th>
                        <th scope="col">
                            <div title="Value">File Extension</div>
                        </th>
                    </tr>
                </thead>
                <tbody>
                    <template for:each={files} for:item="keyValue">
                        <tr key={keyValue.Id}>
                            <th scope="col">
                                <div>{keyValue.Title}</div>
                            </th>
                            <th scope="col">
                                <div>{keyValue.FileExtension}</div>
                            </th>
                            <th scope="col">    
                                <!-- Using Dataset Property to get ContentDocumentId -->
                                <lightning-button data-id={keyValue.ContentDocumentId} 
                                                  label="Preview" 
                                                  variant="brand" 
                                                  value="file preview" 
                                                  onclick={filePreview}></lightning-button>
                            </th>
                        </tr>
                    </template>
                </tbody>
            </table>
        </template>
    </lightning-card>
</template>

FilePreviewInLWC.js

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

// importing Apex class method
import retriveFiles from '@salesforce/apex/LWCExampleController.retriveFiles';

// importing navigation service
import { NavigationMixin } from 'lightning/navigation';

// extends the class to 'NavigationMixin'
export default class FilePrivewInLWC extends NavigationMixin(LightningElement) {
    // reactive variables
    @track files;

    // Reteriving the files to preview
    @wire(retriveFiles)
    filesData({data, error}) {
        if(data) {
            window.console.log('data ===> '+data);
            this.files = data;
        }
        else if(error) {
            window.console.log('error ===> '+JSON.stringify(error));
        }
    }

    // when you click the preview button this method will call and
    // it will show the preview of the file based on ContentDocumentId
    filePreview(event) {
        // Naviagation Service to the show preview
        this[NavigationMixin.Navigate]({
            type: 'standard__namedPage',
            attributes: {
                pageName: 'filePreview'
            },
            state : {
                // assigning ContentDocumentId to show the preview of file
                selectedRecordId:event.currentTarget.dataset.id
            }
          })
    }
}

Apex Class
public inherited sharing class LWCExampleController {
    @AuraEnabled(cacheable=true)
    public static list<ContentVersion> retriveFiles(){
        return [SELECT Id, Title, FileExtension, ContentDocumentId From ContentVersion];
    }
}

Note
  • The filePreview named page value supports the ContentDocument and ContentHubItem (external files) objects.
  • The filePreview named page value is supported in Lightning Experience and all versions of the mobile app. 
  • It isn’t supported in other containers, such as Lightning Components for Visualforce, Lightning Out, or Communities. 
  • The page value isn’t supported even if you access these containers inside Lightning Experience or the Salesforce mobile app.


Result

Monday, September 23, 2019

How to check overall code coverage Percentage in Salesforce using SOQL

Note: Use Tooling API to Query.

SOQL Query
SELECT PercentCovered FROM ApexOrgWideCoverage

Result

Sunday, September 22, 2019

Display Radio Buttons Group In Horizontal View in Lightning Component(AURA)

This post explains how to implement a radio group in the horizontal view in lightning components.


Component

<aura:component controller="LWCExampleController" implements="flexipage:availableForAllPageTypes">
    <!--Declaring variables-->
    <aura:attribute name="picklistValues" type="String[]"/>
    <aura:attribute name="selectedValue" type="String"/>
    <aura:attribute name="mapPicklistValues" type="Map" />

    <aura:handler action="{!c.fetchPicklistValues}" name="init" value="{!this}"/>

    <div class="slds-box slds-theme_default">
        <h2>
            <p>Radio Buttons in Horizontal View in Lightning Component</p>
        </h2><br/>
        <aura:iteration items="{!v.picklistValues}" var="item">
            <fieldset style="display: block; float: left;">
                <div class="slds-form-element__control">
                    <span class="slds-radio">
                        <input id="{!item}" name="radiogroup" onchange="{!c.handleSelected}" type="radio" value="{!item}"/>
                        <label class="slds-radio__label" for="{!item}">
                            <span class="slds-radio_faux"></span>
                            <span class="slds-form-element__label">{!item}</span>
                        </label>
                    </span>
                </div>
            </fieldset>
        </aura:iteration><br/><br/>
        <aura:if isTrue="{!not(empty(v.selectedValue))}">
            <div>
                Selected Vlaue:
                <b>{!v.selectedValue}</b>
            </div>
        </aura:if>
    </div>
</aura:component>

Component Controller:
({
    fetchPicklistValues : function(component, event, helper) {
       
        var action = component.get("c.getAccRatings");
        var options=[];
        action.setCallback(this, function(response) {
            let state = response.getState();
            if(state === 'SUCCESS') {
                var mapValues = response.getReturnValue();
                component.set('v.mapPicklistValues', mapValues);
                let picklistValuesList = [];

                for(let key in mapValues) { 
                    picklistValuesList.push(mapValues[key]);
                }
            
                component.set("v.picklistValues", picklistValuesList);
            }
             
        });
        $A.enqueueAction(action); 
    },

    handleSelected : function(component, event, helper) {
        let currentValue = event.target.value;
        
        let mapValues = component.get('v.mapPicklistValues');
        let selectedValue;
        for(let key in mapValues) {
            if(currentValue == mapValues[key]) {
                selectedValue = key;
                break;
            }
        }
        component.set('v.selectedValue', selectedValue);

    }
})

Apex Class

public inherited sharing class LWCExampleController {
    @AuraEnabled
    public static map<String, String> getAccRatings(){
        map<String, String> options = new map<String, String>();
        Schema.DescribeFieldResult fieldResult = Account.Rating.getDescribe();
        List<Schema.PicklistEntry> lstPicklistValues = fieldResult.getPicklistValues();
        for (Schema.PicklistEntry iterator: lstPicklistValues) {
            options.put(iterator.getValue(), iterator.getLabel());
        }
        return options;
    }
}

Output


Content Security Policy(CSP) in Salesforce

Content Security Policy(CSP)
  • The Lightning Component framework uses the Content Security Policy (CSP) to impose restrictions on content. 
  • The main objective is to help prevent cross-site scripting (XSS) and other code injection attacks. 
  • To use third-party APIs that make requests to an external (non-Salesforce) server or to use a WebSocket connection, add a CSP Trusted Site.

CSP is a W3C standard that defines rules to control the source of content that can be loaded on a page. All CSP rules work at the page level and apply to all components and libraries.

When you define a CSP Trusted Site, the site’s URL is added to the list of allowed sites for the following directives in the CSP header.
connect-src
frame-src
img-src
style-src
font-src
media-src

This change to the CSP header directives allows Lightning components to load resources, such as images, styles, and fonts, from the site. It also allows client-side code to make requests to the site.

Path
From Setup, enter CSP Trusted Sites in the Quick Find box, and then select CSP Trusted Sites



1. Enter the site URL
2. Select the Context for this trusted site to control the scope of the approval.
All  -  (Default)CSP header is approved for both your organization’s Lightning Experience and Lightning Communities.
LEX CSP header is approved only for your organization’s Lightning Experience.
Communities CSP header is approved only for your organization’s Lightning Communities.


Reference
Content Security Policy

Saturday, September 21, 2019

Record Type Selector in Lightning Web Component(lwc)

This post explains how to implement record type selector in lightning web components(lwc)

To get the record type info in lightning web components we have to use the wire adapter getObjectInfo this wire adapter gets metadata about a specific object. The response includes metadata describing fields, child relationships, record type, and theme.

In this example, I am using the Account Object. getObjectInfo wire adapter returns the account object info.



RecordTypesInLWC.html

<template>
    <lightning-card title="Record Type Selector in Lightning Web Component">
            <lightning-layout multiple-rows="true" vertical-align="end">
                <lightning-layout-item size="6" small-device-size="2" medium-device-size="4" large-device-size="4" padding="around-small">
                        <div class="slds-form-element">
                            <div class="slds-form-element__control">
                                <lightning-combobox name="recordTypes"
                                                    label="Account Record Types"
                                                    value={selectedValue}
                                                    placeholder="-Select-"
                                                    options={options}
                                                    onchange={handleChange} ></lightning-combobox>
                            </div>
                        </div>
                </lightning-layout-item>
            </lightning-layout><br/>
        <div style="margin-left:3%;">
            <div if:true={selectedValue}>
                Selected Record Type Id: <b>{selectedValue}</b>
            </div>
        </div>
    </lightning-card>
</template>

recordTypesInLWC.js
import { LightningElement, wire, track } from 'lwc';

// importing to get the object info 
import { getObjectInfo } from 'lightning/uiObjectInfoApi';
// importing Account shcema
import ACCOUNT_OBJECT from '@salesforce/schema/Account';

export default class RecordTypesInLWC extends LightningElement {
    @track selectedValue;
    @track options = [];

    // object info using wire service
    @wire(getObjectInfo, { objectApiName: ACCOUNT_OBJECT })
    accObjectInfo({data, error}) {
        if(data) {
            let optionsValues = [];
            // map of record type Info
            const rtInfos = data.recordTypeInfos;

            // getting map values
            let rtValues = Object.values(rtInfos);

            for(let i = 0; i < rtValues.length; i++) {
                if(rtValues[i].name !== 'Master') {
                    optionsValues.push({
                        label: rtValues[i].name,
                        value: rtValues[i].recordTypeId
                    })
                }
            }

            this.options = optionsValues;
        }
        else if(error) {
            window.console.log('Error ===> '+JSON.stringify(error));
        }
    }
     
    // Handling on change value
    handleChange(event) {
        this.selectedValue = event.detail.value;
    }

}

recordTypesInLWC.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="RecordTypesInLWC">
    <apiVersion>45.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>

Output


Monday, September 16, 2019

Progress Bar in Lightning Web Component(lwc)

This post explains how to use progress bar in Lightning Web Components(lwc)



progressBarDemoInLWC.html
<template>
    <lightning-card title="Progress Bar in Lightning Web Component"><br/>
        <div style="margin-left: 2%;">
            <lightning-progress-bar size="medium" value={progress} variant="circular"></lightning-progress-bar>
        </div>
        <div class="slds-text-align--center slds-text-title" style="color:forestgreen;">
            {processStatus}
        </div>
    </lightning-card>
</template>

ProgressBarDemoInLWC.js
import { LightningElement, track } from 'lwc';

export default class ProgressBarDemoInLWC extends LightningElement {
    @track progress = 0;
    @track processStatus = 'In Progress';

    connectedCallback() {
        
        // eslint-disable-next-line @lwc/lwc/no-async-operation
        this._interval = setInterval(() => {
            this.progress = this.progress + 5;
            this.processStatus = 'Processing => ' + this.progress +'/100';
            if(this.progress === 100) {
                clearInterval(this._interval);
                this.processStatus = 'Completed';
            }
        }, 300);

    }
}

ProgressBarDemoInLWC.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="ProgressBarDemoInLWC">
    <apiVersion>46.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>

Output

Disable Browser Cache During Lightning Componet(AURA), Lightning Web Component Development(lwc)

Path:
From Setup, enter Session Settings in the Quick Find box, and then select Session Settings.
Deselect the checkbox for “Enable secure and persistent browser caching to improve performance”.
then click save.


Note:
Disabling secure and persistent browser caching has a significant negative performance impact on Lightning Experience. Always enable the setting in production orgs.

Display Radio Buttons Group in Horizontal view in Lightning Web Component(lwc)

This post explains how to display radio buttons group in Horizontal view in Lightning Web Components(lwc)


radioGroupInHorizontal.html
<template>
    <lightning-card title="Radio Buttons Group Horizontal View in Lightning Web Component"><br/>
        <div style="margin-left:3%;">
            <template for:each={options} for:item="item">
                <fieldset key={item.value} style="display: block; float: left;">
                    <div class="slds-form-element__control">
                        <span class="slds-radio">
                            <input name="radiogroup" id={item.value} type="radio" value={item.value} onchange={handleSelected}/>
                            <label class="slds-radio__label" for={item.value}>
                                <span class="slds-radio_faux"></span>
                                <span class="slds-form-element__label">{item.label}</span>
                            </label>
                        </span>
                    </div>
                </fieldset>
            </template><br/><br/>

            <div if:true={selectedValue}>
                Selected Vlaue: <b>{selectedValue}</b>
            </div>
        </div>

    </lightning-card>
</template>

radioGroupInHorizontal.js
import { LightningElement, wire, track} from 'lwc';
import { getPicklistValues } from 'lightning/uiObjectInfoApi';
import { getObjectInfo } from 'lightning/uiObjectInfoApi';
import ACCOUNT_OBJECT from '@salesforce/schema/Account';
import Rating_FIELD from '@salesforce/schema/Account.Rating';

export default class RadioGroupInHorizontal extends LightningElement {
    @track selectedValue;
    @track options = [];

    // object info using wire service
    @wire(getObjectInfo, { objectApiName: ACCOUNT_OBJECT })
    objectInfo;

    // Getting Account Rating Picklist values using wire service
    @wire(getPicklistValues, { recordTypeId: '$objectInfo.data.defaultRecordTypeId', fieldApiName: Rating_FIELD})
    ratingPicklistValues({error, data}) {
        if(data) {
            window.console.log('result ===> '+JSON.stringify(data.values));
            this.options = data.values;
        }
        else if(error) {
            window.console.log('error ===> '+JSON.stringify(error));
        }
    }

    // handle the selected value
    handleSelected(event) {
       window.console.log('selected value ===> '+event.target.value);
       this.selectedValue = event.target.value;
    }

}

RadioGroupInHorizontal.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="RadioGroupInHorizontal">
    <apiVersion>46.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>

Output


Sunday, September 15, 2019

Radio Group buttons in Lightning Web Component(lwc)

This post explains how to implement radio buttons in the lightning web components(lwc)



RadioButtonsInLWC.html
<template>
    <lightning-card title="Radio Group in LWC">
        <div style="margin-left:3%;">
            <lightning-radio-group label="Account Type" 
                                    name="radioButtonGroup" 
                                    onchange={handleChange} 
                                    options={options}
                                    value={selectedValue}
                                    type="radio"></lightning-radio-group>
        
            <br/>
            <div if:true={selectedValue}>
                Selected Vlaue: <b>{selectedValue}</b>
            </div>
        </div>

    </lightning-card>
</template>

RadioButtonsInLWC.js
import { LightningElement, wire, track} from 'lwc';
import { getPicklistValues } from 'lightning/uiObjectInfoApi';
import { getObjectInfo } from 'lightning/uiObjectInfoApi';
import ACCOUNT_OBJECT from '@salesforce/schema/Account';
import Type_FIELD from '@salesforce/schema/Account.Type';

export default class RadioButtonsInLWC extends LightningElement {
    @track selectedValue;
    @track options = [];

    // object info using wire service
    @wire(getObjectInfo, { objectApiName: ACCOUNT_OBJECT })
    objectInfo;

    // Getting Account Type Picklist values using wire service
    @wire(getPicklistValues, { recordTypeId: '$objectInfo.data.defaultRecordTypeId', fieldApiName: Type_FIELD})
    typePicklistValues({error, data}) {
        if(data) {
            let optionsValues = [];
            for(let i = 0; i < data.values.length; i++) {
                optionsValues.push({
                    label: data.values[i].label,
                    value: data.values[i].value
                })
            }
            this.options = optionsValues;
            window.console.log('optionsValues ===> '+JSON.stringify(optionsValues));
        }
        else if(error) {
            window.console.log('error ===> '+JSON.stringify(error));
        }
    }

    // handle the selected value
    handleChange(event) {
        this.selectedValue = event.detail.value;
    }

}

RadioButtonsInLWC.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="RadioButtonsInLWC">
    <apiVersion>46.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>

Output

Friday, September 13, 2019

How to implement Progress Bar in Visualforce Page

This post explains how to implement Progress bar on the Visualforce page using SLDS class.

This is Demo only you can extend this functionality based on your requirement.

Demo

Visualforce page
<apex:page controller="ProgressBarController" >
    <apex:slds />
    <apex:form id="frm">
        <apex:actionPoller action="{!checkStatus}" enabled="{!bProcess}" interval="5" reRender="frm" />
        
        <div class="slds-grid slds-gutters" style="margin-left:1%;">
            <div class="slds-col slds-size_1-of-3">
                <h1 style=" font-weight: bold;">
                    Progress Bar Demo in Visualforce Page
                </h1>
                <div style="display: block; margin-top:5%;" class="slds-progress-bar slds-progress-bar_circular" aria-valuemin="0" aria-valuemax="100"
                     aria-valuenow="{!deProgressBarWidth}" role="progressbar">
                    <span class="slds-progress-bar__value slds-progress-bar__value_success" style="width: {!deProgressBarWidth}%;">
                        <span class="slds-assistive-text">Progress: {!deProgressBarWidth}%</span>
                    </span>
                    <div class="slds-text-align--center slds-text-title" style="color:forestgreen;">
                        {!strStatus}
                    </div>
                </div>
            </div>
        </div>
    </apex:form>
</apex:page>


Apex Class
public class ProgressBarController {
    
    public Decimal deProgressBarWidth {get;set;}
    public Integer iCount {get;set;}
    public String strStatus {get;set;}
    public Boolean bProcess {get;set;}
    
    public ProgressBarController() {
        deProgressBarWidth = 0;
        strStatus = 'In Progress...';
        bProcess = true;
        iCount = 0;
    }
    
    public PageReference checkStatus() 
        // Caluclating Percentage value
        deProgressBarWidth = (iCount != 0 ? (Decimal.valueOf(iCount) > 100 ? 100 : Decimal.valueOf(iCount))/100 * 100 : 0);
        if(iCount >= 100) {
            strStatus = 'Completed';
            bProcess = false;
        }
        else {
            strStatus = 'Processing => ' + iCount + '/100';
        }  
        
        iCount += 45;
        return null;
    }
}

Output