Sunday, November 25, 2018

Custom Permissions

In Salesforce, many features require access checks that specify which users can access certain functions. Permission set and profiles settings include built-in access settings for many entities, like objects, fields, tabs, and Visualforce pages. However, permission sets and profiles don’t include access for some custom processes and apps.

Challenge 1 :
Suppose We have an object “Product Complaint” and it has filed like below,
1.      Status [Open/ Closed/ Other] è Pick list filed.
2.      Reason For Other è Text
Now create a validation rule so that if Status is selected as “Other” and if user was not entered any value for “Reason For Other” field, then an warning/error/validation message will be thrown as “Please enter reason to select other”.




Now our aim is that this validation rule will be fire for every users except the user belongs to System Admin profile. That mean user with system admin profile will able to save any PC record with status value as “Other” and no value in “Reason For Other” filed.


Solution:
1. Create a custom permission.
















2. Assign it to System Admin Profile.



3. Update the validation rule.



Now user with System Admin profile can create PC record with “Other” status – without entering “Reason For Other” value. But other profile user will get the validation message.

Challenge 2 :
Now if we want this validation in user level i.e. some System Admin user will face this validation rule and some not.

Solution:
1. Remove “Custom Permission” form System Admin Profile.
2. Create a permission set (Named it same as custom permission).



3. Click on “Manage Assignments” button to assign the user who can use this permission set.
4. Now click on the “Custom Permissions” link to assign custom permission to “Permission Set”.



5. Now try to test the validation rule for 2 System Admin Users, one who is assigned in Permission Set and one who is not assigned.

Note: We can also use custom permission in VISUALFORCE page. Like some render condition.
Syntax  is look like below,
(Not($Permission. Can_Set_PC_Status_to_Other))

Permission Sets Concept.

1. Why Permission Set is used in Salesforce?
 
     In Salesforce each user should has one and only one profile. But there could be multiple users for a single profile. Now taking the above consideration check the below scenario :

     Suppose we have a Profile named as "My Custom Profile" and suppose this profile has only read permission on Account Object. Now there are 3 users (U1, U2, U3) have assigned to this profile.
So, as per above scenario all 3 users (U1, U2, U3) should have only read permission as their assigned profile has read permission on Account object.

Now, suppose there is a requirement that U2 can also perform create and edit operation on Account irrespective of it's profile permission (i.e. only read permission). So this the place where we can use Permission Set.



2. How to create and configure Permission Set for the above scenario?


  • Search "permission sets" under "Quick Find" box and click on "Permission Sets" link and it will open "Permission Sets" detail page.Now click on "New" button to create a new permission set. For example our permission set name is "My Custom Permission" and the screen like below screen,




  • Now open newly created permission set named as "My Custom Permission Set" and then click on "Object Setting" link and it will open list of objects and then click on the object link for which you want to give the extra permission which not available in Profile. For the above example click on "Account" object.




  • Once we click on "Account" link it will open "my Custom Permission Set" for "Account" object and then click on "Edit" button and set the extra permission on Object and Field level and finally click on "Save" button.

  • Now its time to set the above create permission set to different user and for our case it is for user "U2". So, open user "U2" and then scroll down to " Permission Set Assignments" section and click on "Edit Assignments" button.

  • Once click it will shown you the available and enabled permission sets bucket and form available bucket we have to add "My Custom Permission Set" to enabled bucket and once done then click on "Save" button and its done. Now test the scenario.



Is it mandatory to select User License while creating permission sets? If not, what is the significance of selecting a User License?


It is not mandatory to select a User License while creating a permission sets.
If users with one type of license will use this permission set, then choose the same license that’s associate with them.
If you are planning to assign this permission set to multiple users with different licenses then, choose none.


Thursday, May 31, 2018

Lightning Datatable using Fieldset

1. Create a util class (FieldSetExample) which is responsible to return list of fields (label, api and       type) available under field set of an object passed as parameters by a method.

public class FieldSetExample {
    /**
     * This method is responsible to return list of fields (label, api and type) avaliable
     * under field set of an object passed as parameters.
     * */
    public static List<FieldSetProperties> getFieldFromFieldSet(String objApi, String fieldSetName){
        List<FieldSetProperties> lstOfWrapper = new List<FieldSetProperties>();
        
        Schema.SObjectType sObjType = Schema.getGlobalDescribe().get(objApi);
        Schema.DescribeSObjectResult desSObjRslt = sObjType.getDescribe();            
        Schema.FieldSet fieldSetIns = desSObjRslt.FieldSets.getMap().get(fieldSetName);
        
        for( Schema.FieldSetMember fieldSetMember : fieldSetIns.getFields() ){
            FieldSetProperties wrapperIns = new FieldSetProperties();
            
            wrapperIns.label = String.valueOf(fieldSetMember.getLabel()); 
            wrapperIns.fieldName = String.valueOf(fieldSetMember.getFieldPath()); 
            wrapperIns.type = String.valueOf(fieldSetMember.getType()).toLowerCase();
            
            lstOfWrapper.add(wrapperIns);
        }        
        
        return lstOfWrapper;
    }
    
    /**
     * Wrapper class to hold fieds properties like label, field api and field type.
     * */
    public class FieldSetProperties{
        @AuraEnabled
        public String label;
        @AuraEnabled
        public String fieldName;
        @AuraEnabled
        public String type;
    }
}

2. Create a server side controller class (DataTableExampleController) for the lightning component (dataTableExample) used to display records using data table.

public class DataTableExampleController {
    
    @AuraEnabled
    public static DataTableDetails getDataTableDetails(String objApi, String fieldSetName){
        DataTableDetails dataTableDtls = new DataTableDetails();
        List<FieldSetExample.FieldSetProperties> lstOfFieldSetProperties = FieldSetExample.getFieldFromFieldSet(objApi, fieldSetName);
        
        if(lstOfFieldSetProperties != null && lstOfFieldSetProperties.size() > 0){
            String strQuery = 'SELECT ';
            for(FieldSetExample.FieldSetProperties inst : lstOfFieldSetProperties){
                dataTableDtls.lstOfFieldLabels.add(inst);
                
                strQuery = strQuery + inst.fieldName + ',';
            }
            if(!strQuery.equalsIgnoreCase('SELECT '))
                strQuery = strQuery + 'Id FROM ' + objApi;
            
            dataTableDtls.lstOfSObjs = Database.query(strQuery);
        }
        
     return dataTableDtls;
    }
    
    
    public class DataTableDetails{
        @AuraEnabled
        public List<sObject> lstOfSObjs = new List<sObject>();
        @AuraEnabled
        public List<FieldSetExample.FieldSetProperties> lstOfFieldLabels = new List<FieldSetExample.FieldSetProperties>();
    }
}

3. Create the lightning component (dataTableExample.cmp).

<aura:component controller="DataTableExampleController">
    <aura:attribute name="lstOfRecords" type="Object"/>
    <aura:attribute name="columnsHeader" type="List"/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
        
    <lightning:datatable data="{!v.lstOfRecords}"
                         columns="{!v.columnsHeader}"
                         keyField="Id"
                         hideCheckboxColumn="true"/>
</aura:component>

4. dataTableExampleController.js

({
    doInit : function(component, event, helper) {
         helper.getDataTableRespone(component, event);
    }
})

5. dataTableExampleHelper.js

({
 getDataTableRespone : function(component, event) {
        var action = component.get("c.getDataTableDetails");
        action.setParams({
            objApi : 'YOUR OBJECT API',
            fieldSetName : 'YOUR FIELD SET NAME'
        });
        action.setCallback(this, function(response){
            var state = response.getState();
            if(state === 'SUCCESS'){
                //console.log('::::::::::::: SUCCESS :::::::::::::'+JSON.stringify(response.getReturnValue().lstOfFieldLabels));
                component.set("v.columnsHeader", response.getReturnValue().lstOfFieldLabels);
                
                component.set("v.lstOfRecords", response.getReturnValue().lstOfSObjs);    
            }else if (state === 'ERROR'){
                console.log('::::::::::::: ERROR :::::::::::::');
            }
        });
        $A.enqueueAction(action);
 }
})

6. Call the above component from an application (dataTableExampleApp.app)


<aura:application extends="force:slds">
 <c:dataTableExample />
</aura:application>

How to fetch Field(s) under Fieldset using Apex.



public class FieldSetExample {
    /**
     * This method is responsible to return list of fields (label, api and type) avaliable
     * under field set of an object passed as parameters.
     * */
    public static List<FieldSetProperties> getFieldFromFieldSet(String objApi, String fieldSetName){
        List<FieldSetProperties> lstOfWrapper = new List<FieldSetProperties>();
        
        Schema.SObjectType sObjType = Schema.getGlobalDescribe().get(objApi);
        Schema.DescribeSObjectResult desSObjRslt = sObjType.getDescribe();            
        Schema.FieldSet fieldSetIns = desSObjRslt.FieldSets.getMap().get(fieldSetName);
        
        for( Schema.FieldSetMember fieldSetMember : fieldSetIns.getFields() ){
            FieldSetProperties wrapperIns = new FieldSetProperties();
            
            wrapperIns.label = String.valueOf(fieldSetMember.getLabel()); 
            wrapperIns.fieldName = String.valueOf(fieldSetMember.getFieldPath()); 
            wrapperIns.fieldType = String.valueOf(fieldSetMember.getType()).toLowerCase();
            
            lstOfWrapper.add(wrapperIns);
        }        
        
        return lstOfWrapper;
    }
    
    /**
     * Wrapper class to hold fieds properties like label, field api and field type.
     * */
    public class FieldSetProperties{
        public String label;
        public String fieldName;
        public String fieldType;
    }
}

Wednesday, May 30, 2018

Open a Modal Window using overlayLibrary


1. Create a lightning component where your modal content will be displayed.

modalContent.cmp
<aura:component access="global">
    <!-- This is the reference of Modal window -->
    <lightning:overlayLibrary aura:id="overlayLibRefId"/>
    <div class="slds-grid slds-wrap">
        <div class="slds-size_8-of-12">
            <div class="slds-text-align_left">
                ::::: Modal window using overlayLibrary :::::
            </div>            
            <div class="slds-align_absolute-center">
                <lightning:button label="Close" 
                                  onclick="{!c.doCloseOperation}" 
                                  variant="brand" 
                                  class="slds-m-top--medium"/>
            </div>
        </div>
    </div>    
</aura:component>

modalContentController.js
({
 doCloseOperation : function(component, event, helper) {
        //Closing the Modal Window
        component.find("overlayLibRefId").notifyClose();
  
 },
})

2. Create second lightning component from where your actual component (as created above) will be called.

modalWindowOverlay.cmp
<aura:component implements="lightning:actionOverride" 
                access="global">
    <!-- overlayLibId is used to show modal window from controller -->
    <lightning:overlayLibrary aura:id="overlayLibId"/>
    <aura:handler name="init" action="{!c.doInit}" value="{!this}"/>
</aura:component>

modalWindowOverlayController.js
({
    doInit : function (component, event, helper) {
        var modalBody;
        $A.createComponent("c:modalContent", {},
                           function(content, status) {
                               if (status === "SUCCESS") {
                                   modalBody = content;
                                   component.find('overlayLibId').showCustomModal({
                                       header: "Modal Header",
                                       body: modalBody,
                                       showCloseButton: true,
                                       //cssClass: "mymodal CSS"
                                       closeCallback: function() {
                                           console.log('Close ......');
                                       }
                                   })
                               }
                           });
    }
})

3. Now, set the modalWindowOverlay.cmp  under any button and then click the button. It will open the modal window.

Thursday, May 24, 2018

How to call Lightning Component from Visualforce page.

Scenario: Suppose we have a lightning component named as "xyz.cmp" with some attributes. Now we want to call this component from a VF page (CallLightingCompFromVF).

Solution:

  • First we have to create a component (xyz.cmp) with attributes let say "var1" and "var2" and these attributes have default value as "Mr." , "Mark" respectively.
<aura:component >
 <aura:attribute name="var1" type="String" default="Mr."/>
    <aura:attribute name="var2" type="String" default="Mark"/>
    Helo! {!v.var1} {!v.var2}
</aura:component>

          Now if we preview this component then, it will display "Hello! Mr.Mark" as an output.

  • Now create a lightning app called as dependency app where component (which need to be called from VF for our case xyz.cmp) dependency will be defined.

<!-- Extending from ltng:outApp adds SLDS resources to the page to allow your 
Lightning components to be styled with the Salesforce Lightning Design System (SLDS). 
If you don’t want SLDS resources added to the page, extend from ltng:outAppUnstyled 
instead. -->
<aura:application access="GLOBAL" extends="ltng:outApp">
    <aura:dependency resource="c:xyz"/>
</aura:application>

  • Now our aim is to call the above component from a VF page and pass different attribute's value. Let say after preview the VF (which call the above component) display or output will be "Hello! Ms.Andi
<apex:page >
    <!-- The below tag help to add lighting component to Visualforce page -->
    <apex:includeLightning />
    
    <!-- Declear a div where your lightning component will be displayed -->
    <div id="lightningDivId" />
    
    <!-- Script logic to call Lightning component from VF using a dependiecy app. -->
    <script>
        $Lightning.use("c:LigDependencyAppForVF", function() {
             $Lightning.createComponent("c:xyz",
                                           {var1 : "Ms.",
                                            var2 : "Andi"},
                                           "lightningDivId"
                                       );
            }
        );
    </script>
</apex:page>


Wednesday, February 21, 2018

Load JS and CSS in Lightning Component from Static Resource

Suppose we have a ZIP file containing CSS and JS files, available under Static Resources (MIME Type : application/zip) and we want to load it in a lightning component, then check the code synapse needs to be update under .cmp file for solution ,

sample.zip - | sampleCss.css
                     | sampleJs.js


<aura:component>
 <ltng:require styles="{!$Resource.sample + '/sampleCss.css'}" 
                  scripts="{!$Resource.sample + '/sampleJs.js'}" 
                  afterScriptsLoaded="{!c.afterScriptsLoadedMethodInController}"/>
<aura:component>

Tuesday, February 20, 2018

Lightning UI Date Time Format


<lightning:formattedDateTime aura:id="thresholdRunOn"
                             value="your date time value"
                             month="short"
                             day="numeric"
                             year="numeric"
                             hour="2-digit"
                             minute="2-digit"
                             second="2-digit"
                             hour12="true"
                             timeZone="{!$Locale.timezone}"/>

Output:
The above example will return a value like this ==> Feb 20, 2018, 9:43:00 PM

Note: Properties value can be change based on your requirement.

Saturday, January 6, 2018

aura:method example in Lightning

Scenario: Scenario is same as posted in my previous post (Lightning Event Example) and the aim is also same and that is Pass value from child component to parent component.

Solution: 
To execute the above scenario, we can also use aura:method instead of aura:event.
For the same we will create a aura:method under child component and this method will return a string value and from parent component we will catch this value.

1. Create a Child component (childComponent.cmp). Under this child component declare a aura:method as shown in below example. aura:method has a name (this name will be used called from parent component), an action (for our example, this action method will return a string value) and set access as "PUBLIC".

childComponent.cmp
<!-- Child component with aura method -->
<aura:component >
    <aura:method name="messageFromChild" 
                 action="{!c.getMessageFromChild}" 
                 access="PUBLIC"/>
</aura:component>

childComponentController.js

//js controller for child component
({
 getMessageFromChild : function(component, event, helper) {
  return "##### I am under CHILD component. #####";
 }
})

2. Now create a parent component (parentComponent.cmp) and from parent component call the child component.
 Parent component have an local attribute (messageFromChild), with default value as "##### I am under PARENT component. #####" and a button (click on this button will call an action method, from where child method will be called and return value from child method will be set in local attribute.).
So, when this parent component will execute in UI, first it will show a button with an output text message as "##### I am under PARENT component. #####" and when the button will clicked then that output text message will display as "##### I am under CHILD component. #####".

parentComponent.cmp

<!-- Parent component to call child component to execute aura method -->
<aura:component implements="force:lightningQuickAction">
    <!-- Local attribute whith default value -->
    <aura:attribute name="messageFromChild" 
                    type="String" 
                    default="##### I am under PARENT component. #####"/>
    
    <!-- Child component calling. This should have aura:id -->
    <c:childComponent aura:id="childComp"/>
    
    <!-- On button click child aura:method will be called. -->
    <ui:button label="Call Child Method" press="{!c.callChildMethod}" />
    
    <!-- Initially display default message set in this parent componet.
   Once button click this attribute will be set by a string 
   value comming from child component. -->
    <p>{!v.messageFromChild}</p>
</aura:component>

parentComponentController.js

//js controller for parent component
({
 callChildMethod : function(component, event, helper) {
        //Child aura method calling logic.
        var childCmp = component.find("childComp");
        var rtnMsgFromChildMethod = childCmp.messageFromChild();
        
        //Set local attribute with string value, comming from child aura method.
        component.set("v.messageFromChild", rtnMsgFromChildMethod);
 }
})


Output on initial load (before click on button):


Output after button click:


LWC to LWC Communication using Lightning Messaging Service (Part - 2)

In my previous post ( previous post link ) we have learn how to create a Lightning Messaging Service with 6 steps and today we will use the ...