Wednesday, 9 December 2015

Tips to clear Salesforce Certified Platform Developer II Multiple Choice Exam

Many of you may aware of the new certifications from Salesforce after Summer’15. Please check this link for more information (here).

I want to share my experience in preparing for the Developer II exam. I recently cleared the exam on 5th of December 2015 (Developer II Transition Exam). You can get the study guide for the exam here, but I didn’t feel it is helpful for the preparation. Because, the questions are from everywhere, as you have covered most of it in Developer1 exam, you need to prepare more in depth for the Developer II.

The pass percentage is just 63%. Looks easy but the questions are very tricky. But, if you prepare well with the following topics then it will help you to clear at the first shot.

Here is what you have to prepare,

  1. Read about SOAP and REST implementation. Know about the limits. How to write the Test classes for SOAP and REST using the Mock classes.
  2. @InvocableMethod and @InvocableVariable
  3. Apex Governor Limits.
  4. Implement the Lightning Application in a new Dev Org. You can find Lightning pdf here. Understand the Lightning Component very well.
  5. Querying the PermissionSet.
  6. Apex Test class best practice.
  7. @testSetup considerations
  8. apex:chart
  9. Using Webservice keyword and considerations
  10. Querying based on the Currency field (Read here).
  11. Aggregate Queries
  12. Look into apex:actionSupport, apex:actionFunction, apex:actionPoller, apex:remoteObjects
  13. Automation Tools - Lighting ProcessBuilder, Flows, Workflow and Approval Process.
  14. Go through the Apex Language Reference PDF and VF PDF.

Also, there are many scenario based questions to test your knowledge to use the best practices.

Hope this helps to clear your Developer II exam. If you have any questions please comment below. I will get back to you.

All The Best!!




Tuesday, 17 March 2015

Editable Email Popup Window – Salesforce Service Console

Editable Email Popup Window – Salesforce Service Console

Popup window is a very popular way to edit or add comments or edit records in the current page. In the business world the necessity of a popup window has increased a lot over the years. My client was also interested in a popup window to edit the selected email template from the salesforce service console (AnswerCustomer).

Firstly I tried using the JQuery libraries for the same using Lightboxme, Colorbox, boxy and bpopup. I recommend you all to use these libraries if you just want a popup window to display a piece of information in a stylish way in your page.

As the requirement is an editable email template window, I placed a Preview link in the Service Console Page (AnswerCustomer page),



The code for the above page is very simple,

<apex:page standardController="Case" ><apex:includeScript value="{!URLFOR($Resource.JQuery, 'jquery-ui-1.11.2/external/jquery/jquery.js')}" />
<script type="text/javascript">
var $j = jQuery.noConflict();
$j(document).ready(function(){

var newWin=null;

$j('#previewlinkid').click(function(){

newWin=window.open('/apex/EmailTemplatePopup', 'preview', 'width=600,height=800,scrollbars=yes,resizable=yes,toolbar=no,status=no'); if(window.focus){
newWin.focus();
}
return false;
});

});
</script>

<apex:form id="theform">
<div align="right">
<font style="font-family:arial;font-size:10px"><a href="#" id="previewlinkid" title="Preview">Preview</a></font>
</div>
</apex:form>

<apex:emailPublisher entityId="{!case.id}" toAddresses="{!case.contact.email}" emailBodyFormat="textAndHTML" bccVisibility="editable" verticalResize="true" showTemplates="true" width="100%" />
</apex:page>

 

I have written a new Visualforce page (EmailTemplatePopup) for the Popup window. In the EmailTemplatePopup page, I am calling the parent window component to access the html content of it. When I select an Email Template and click on the Preview link as shown in the AnswerCustomer page, it opens the window as shown below,




The code for the EmailTemplatePopup is,

<apex:page sidebar="false" showHeader="false">         
<apex:includeScript value="{!URLFOR($Resource.JQuery, 'jquery-ui-1.11.2/external/jquery/jquery.js')}"  /> 
<script type="text/javascript">         
var $j = jQuery.noConflict();                  
$j(document).ready(function(){ 
   //OnLoad copy the content from parent window to child window (Popup)                       
   $j("[id*='emailtextval']").text(window.opener.$j('#cke_1_contents').find('iframe').contents().find('body').html());
   //Save and Close link action             
   $j('#copytoid').click(function(){ 
  //use console.log to display the content in the debug log                 
   console.log('^^^ : '+$j('#cke_1_contents').find('iframe').contents().find('body').html());
   //Copy the html content from Popup window and replace it in Parent window
   window.opener.$j('#cke_1_contents').find('iframe').contents().find('body').html( $j('#cke_1_contents').find('iframe').contents().find('body').html());                  
   window.close(); //Close the Window on Save and Close                 
   return false;              
 });
});          
</script>  
<apex:form id="emailform">         
<div align="right">             
<font style="font-family:arial;font-size:10px"><a href="#" id="copytoid" >Save and Close</a></font>         
</div>         
<apex:inputTextarea id="emailtextval" richText="true" cols="500" rows="100" title="Preview"/>     
</apex:form>      
</apex:page>
 
                  
Those who are very familiar in JQuery will easily understand the aforementioned code easily. I recommend others to read the basic JQuery before looking into the aforementioned code.

On page load, I used the following line to populate the email template html from parent window,

$j("[id*='emailtextval']").text(window.opener.$j('#cke_1_contents').find('iframe').contents().find('body').html());

I am finding the element by using $j("[id*='emailtextval']") and then using the JQuery TEXT() method (here) to replace the contents from the parent window component. In the service console Email page, Salesforce is using Rich Text Area to populate the HTML content inside. If you search all the Rich Text Area component Id in Salesforce, you will get cke_1_contents. So, in your page you don’t have to worry about finding the id.

In the popup window (child window), I used the Save and Close link to populate the content back to the original page. Here, I have applied a reverse logic and replaced the HTML content in the parent window component using JQuery HTML() method (here).

Please comment below for more queries.


Thanks.

Monday, 15 December 2014

Populating (Overriding) From Email Addresses with Display Name



Recently, I was working on a client requirement to populate the From Email Addresses in Service cloud console based on the Case Origin. The From Email Addresses should be fetched from Email2Case Addresses.

Hope you know that there is no way in salesforce to query the Email2Case addresses.


  1.  I created an email to case settings in Custom Settings (E2C_Settings__c) and stored the Display Name, Case Origin and Email Address in the separate fields.
  2.  Salesforce apex:emailPublisher (Read here) incorporates all the components of Email. This can be only used in Service Console. Since, I need to display the Email Addresses based on Case Origin, I used apex:emailPublisher.
  3.  After, all the implementation, I encountered the issue of the From Email Address. The From Email Addresses populated like the following,
“person1@mycompany.com”< person1@mycompany.com>

“person2@mycompany.com”< person2@mycompany.com>


Then, I started thinking about overriding the From Address (select Component) dynamically by using JQuery with the help of Apex Remoting.

I opened the Developer Tools to see the From Addresses (select component) Id. This is from_CASEID(15 digits). I passed the cased id to a hidden field and accessed it in the jQuery dynamically to append the From list. The following Controller and Visualforce page code explains the logic.

The Controller code :

global class AnswerCustomerController {
    
    private final Case caseRec;
    
    public String caseID { get;set; }
    
    public String fromAddresses { get;set; }
    
    global static list<wEmailWrapper> wEmailWrapperList { 
    
     get{
     if(wEmailWrapperList==null)
     wEmailWrapperList = new list<wEmailWrapper>();
     return wEmailWrapperList;
     }
     set
    }

    public AnswerCustomerController(ApexPages.StandardController stdController) {
        
        this.caseRec = (Case)stdController.getRecord();
        
    }//Constructor ends
    
    @remoteaction
    global static list<wEmailWrapper> getCaseOriginList(String cId) {
    
     list<Case> casList = [select id, Origin from Case where id =: cId];
     
     String caseOrigin = '';
        
         //Copy Case Origin if the caseList is not empty
         if(!casList.isEmpty()){
         //system.debug('*** : '+casList);
         caseOrigin = casList.get(0).Origin;
         }
        
         //Accessing all the Email2Case Settings
       map<String,E2C_Settings__c> E2CSettings = E2C_Settings__c.getAll();
      
       if(caseOrigin != ''){
       //Add the email addresses with the same Case Origin
       for(E2C_Settings__c e2c:E2CSettings.values()){
        
         if(e2c.Case_Origin__c.equals(caseOrigin)){
         system.debug('*** : '+e2c);
         wEmailWrapperList.add(new wEmailWrapper(e2c.Email__c,e2c.Display_Name__c,e2c.Case_Origin__c));//Adding to Wrapper List
         }
       }//for ends
       }
      
       
       //If Case Origin is not found
       if(wEmailWrapperList.size()==0){
       //Add all the email addresses
       for(E2C_Settings__c e2c:E2CSettings.values()){
         wEmailWrapperList.add(new wEmailWrapper(e2c.Email__c,e2c.Display_Name__c,e2c.Case_Origin__c));//Adding to Wrapper List
       }//for ends
       }
    
        return wEmailWrapperList;
    }
    
    /* Wrapper Class to hold the Email Address into a JSON String */
    global class wEmailWrapper{
     public String wEmail { get;set; }
     public String wDisplayName { get;set; }
     public String wOrigin { get;set; }
    
     public wEmailWrapper(String email,String displayName,String origin){
     this.wEmail = email;
     this.wDisplayName = displayName;
     this.wOrigin = origin;
     }
    }

}

VF Code :
<apex:page standardController="Case" extensions="AnswerCustomerController">

<apex:includeScript value="{!URLFOR($Resource.JQuery, 'jquery-ui-1.11.2/external/jquery/jquery.js')}"  /> 


<script type="text/javascript">
var $j = jQuery.noConflict();
$j(document).ready(function(){
var caseid = $j("[id*='tempcaseid']").val();
var selList = $j("#from_"+caseid.substring(0,15)).val();
 
  //Remove the list – Otherwise it populates all the addresses from Orgganization default
  $j("#from_"+caseid.substring(0,15)).empty();
 
  //Javascript Remoting to get the dynamic List
  Visualforce.remoting.Manager.invokeAction(
         '{!$RemoteAction.AnswerCustomerController.getCaseOriginList}',
         caseid,
         function(result, event){
         if (event.status) {
         for (var i=0; i<result.length; i++){
         var res = result[i];
         //$j("#from_"+caseid.substring(0,15)).append(new Option(res.wDisplayName+"<"+res.wEmail+">",res.wEmail+":"+res.wEmail));
         $j("#from_"+caseid.substring(0,15)).append(new Option("\""+res.wDisplayName+"\""+"<"+res.wEmail+">",res.wEmail+":"+res.wEmail));
         }
         }
         },
         {escape: true}
         );
 
});
 
</script>

<apex:form id="theform">
<apex:inputHidden value="{!case.id}" id="tempcaseid"/>
</apex:form>
 <apex:emailPublisher entityId="{!case.id}"
  toAddresses="{!case.contact.email}"
  emailBodyFormat="textAndHTML"
  bccVisibility="editable"/>
</apex:page>

Now, the console page (populated From Addresses) look like below,


Hope this solves the problem for some of them to populate the Display Name with Email Address.