Sunday 2 December 2012

VLOOKUP Function in Salesforce


It returns a value by comparing the field on the related object. It can be easily understand by following example.

Syntax:
VLOOKUP(field_to_return_from_lookup_object, field_to_compare_on_lookup_object, value_to_compare)

Suppose there is a situation in which you have to configure a validation rule to compare/verify the field value against/with the value store on the related object, then this can be achieved by VLOOKUP easily.

For ex:

Country(1st object):

  • Fields:


    1. Name(Text)
    2. Capital(Text)
    3. Population(Numeric)


Customer(2nd object):

  • Fields:


    1. Name
    2. Country(Text)
    3. Capital(Text)
    4. Country(Lookup/related object)

Now you can set a validation rule for "Capital" in the Customer object like below:

VLOOKUP($ObjectType.Country__c.Fields.Capital__c,$ObjectType.Country__c.Fields.Name,Country__c) != Capital__c

Then display a message "Capital is not correct, please enter a valid one."

Now when you will save the 'Customer' record the validation rule would be fired. It will take the value from 'Country__c' and compare with the record in the 'Country' object until it gets one. Then it will return the related 'Capital__c' value to the function from Country object record. If the returned value is not equal to the value entered in the 'Capital__c' field in 'Customer' object record, then it will show the message and record will not be saved.

Saturday 1 December 2012

Dynamic Creation of VF components from Apex


We can create almost all VF components dynamically through controller.

Example:

// this is the controller which is used to develop the dynamic components.
// it's an example, in which several components are being created. you can try it one by one.

public class testController{
// this function asigns a panel bar to the outputPanel.
    public Component.Apex.OutputPanel getDynamicPanel() {
        // creates a outputPanel reference
        Component.Apex.OutputPanel dynOutputPanel = new Component.Apex.OutputPanel();
        Component.Apex.PanelBar dynPanelBar = getPanelBar();

        // adding a panel bar as a child component of outputPanel
        dynOutputPanel.childComponents.add(dynPanelBar);
        return dynOutputPanel;
    }

    private Component.Apex.PanelBar getPanelBar(){
        // creates a panelBar reference
        Component.Apex.PanelBar dynPanelBar = new Component.Apex.PanelBar();
        Component.Apex.PanelBarItem dynPanelBarItem = getPanelBarItem();

        // adding a panel bar Item as a child component of panelBar
        dynPanelBar.childComponents.add(dynPanelBarItem);
        return dynPanelBar;    
    }

    private Component.Apex.PanelBarItem getPanelBarItem(){
        // creates a panelBarItem reference
        Component.Apex.PanelBarItem dynPanelBarItem = new Component.Apex.PanelBarItem();
     
        // adding a pageBlock as a child component of panelBarItem
        dynPanelBarItem.childComponents.add(dynPageBlock);
        return dynPanelBarItem;      
    }
}

// This is the visual force page for the above controller

<apex:page>
<apex:form>
<apex:dynamicComponent componentValue="{!dynamicPanel}"/>
</apex:form>
</apex:page>

Notes:

1. We can add multiple dynamicComponent in a visualforce page.

2. Dynamic Component tag is the only place where we can add dynamically generated component.

3. Attributes can also be assigned to the components.

Creation of Dynamic HTML tags using DOM


We can generate almost all tags of HTML through Javascript dynamically.

Example:
This is the piece of code in which I am generating a table, in that table there would be rows and columns. In those columns, I will generate a text box in one column and write a label in another.

<apex:Page>
<script type="text/javascript">

// call this function from any action it will create a table with text box and its label.
Function createTags(){
var newTable = document.createElement('table'); // Instance of table tag is created
newTable.id ='newTable'; //sets id
newTable.width = '100%'; // sets width attribute

var tbdy =document.createElement('TBODY'); // create instance of Body of table.
                newTable.appendChild(tbdy); // adds child elements of table

var newTableRow = document.createElement('tr'); //row created              
                tbdy.appendChild(newTableRow); // added as child in tbody

var newTableColumnForTextBoxLabel = document.createElement('td'); // column created.
newTableColumnForTextBoxLabel.innerHTML = 'New TextBox: '; // this inner HTML will work as label.
newTableRow.appendChild(newTableColumnForTextBoxLabel); // added as child.

var newTableColumnForTextBox = document.createElement('td'); // column created.
newTableRow.appendChild(newTableColumnForTextBox);  // added as child.

var newTextBox =document.createElement('input'); // input tag created, default is of Type text.
newTableColumnForTextBox.appendChild(newTextBox); // added as child
}
</script>
</apex:Page>

Note:-

1. createElement()- to create the element.
appendChild()- to append any element as a child of any element.
removeChild()- to remove the child element of any element.

/*** element = document.getElementById("element-id");
element.parentNode.removeChild(element);  // in case if dont know the parent element
**/

2. addEventListener('event_Name',listener,state)- to add action on dynamically created elements, it doesnt work in IE.
attachEvent('event_Name',listener)- to add action on dynamically created elements, it works in IE.

listener- This must be an object implementing the EventListener interface, or simply a JavaScript function.
state- As to the true or false that is the last argument of addEventListener, it is meant to state whether the event handler should be executed in the capturing or in the bubbling phase. If you’re not certain whether you want capturing or bubbling, use false (bubbling).

3. innerHTMl(element)- it contains all of the element's descendants.

4. we can also set inline style attribute through this.
e.g: newTextBox.style.visibility ='hidden';

5. insertBefore()- it inserts the node exactly before the given node.

e.g: node.insertBefore(newnode, existingchild);
It inserts newnode as a child of node and exactly before the existingchild.

6. we can add multiple child in a elements, the order of display would be same as adding.


Add values of a object Picklist to selectOption variable


Suppose we need to add values of a picklist which is defined in the object, to a variable of
type selectoption in the controller. The code for that is below:

Steps:

  1. Initiate the selectOption list
  2. Get the schema of the object
  3. Describe the properties of the object
  4. Get the field map in a Map with API name of the field as key
  5. iterate over the map value for the picklist field 
  6. add values to the selectOption list.



Controller:

public List<selectOption> getPicklistValues(){  
                // define a selectoption variable
        List<selectOption> pickListValues= new List<selectOption>();
   
         //retrieves the schema of the object
        Schema.sObjectType sobject_type = test_Object__c.getSObjectType();

        Schema.DescribeSObjectResult sobject_describe = sobject_type.getDescribe();

        Map<String, Schema.SObjectField> field_map = sobject_describe.fields.getMap();
       
         // picklist_field__c is the API name of the picklist field defined in the object
         List<Schema.PicklistEntry> pick_list_values =                       field_map.get('picklist_field__c').getDescribe().getPickListValues();    
     
for (Schema.PicklistEntry a : pick_list_values){
pickListValues.add(new selectOption(a.getLabel(), a.getValue()));
}
         return pickListValues;
}

How to create a record of a particular record type in Controller and Test class


Here i am taking an example of Account(Object) and Person Account (Record Type).

Controller:

public class personAccountClass{
public void createPersonAccount(){
Account acc = new Account();
acc.lastName = 'test';
RecordType rt =Database.Query('Select id from RecordType where Name = \'Person Account\' and          
   sObjectType  =  \'Account\'and IsPersonType=True');
acc.RecordTypeid = rt.id;                
insert acc;
}
}

Test class:

@isTestprivate
class testClass{  
static testMethod void testGetAccountDetails(){      
RecordType rType = new RecordType(Name='Person Account',sObjectType='Account');
       List<RecordType> AccountRTypes = Database.Query('Select id, Name, sObjectType from      
 RecordType where Name = \'Person Account\' and sObjectType = \'Account\'and 
IsPersonType=True');

Map<String,String> AccountRecordTypes = new Map<String,String>{};      
for(RecordType rt: AccountRTypes){                      
AccountRecordTypes.put(rt.Name,rt.Id);
           }      

Account acc = new Account();      
acc.LastName = 'test';      
acc.RecordTypeid= AccountRecordTypes.get('Person Account');
insert(acc);
}
}


The record type id can also found by below syntax without using a SOQL:

Id recordTypeId = Schema.SObjectType.Account.getRecordTypeInfosByName().get('Person Account').getRecordTypeId();

How to call a method in controller from Javascript


We can call controller's function from javascript with the help of

  1. <apex:actionFunction>

      VF Page:

            <apex:page controller="testClass">

                <apex:form >

                     <apex:actionFunction name="controllerMethod" action="{!check}"/>

                </apex:form>

                 <script>
                      window.onload = function deleteRecord(){

                            controllerMethod(); // this calls the actionFunction defined in the VF page.
                      }

                 </script>

           </apex:page>

        Controller:

        public class testClass{

             public void check(){

                  String s= 'Function called';

                  apexPages.addMessages(s);

             }

        }

    2. JavaSript Remoting:

      VF Page:

            <apex:page controller="testClass">

                 <script>
                   window.onload = function deleteRecord(){
                      var stringName =  'test';
                                                         
                      Visualforce.remoting.Manager.invokeAction('{!$RemoteAction. testClass. check}',                
                       stringName, function(result, event){

                           if (event.status) {

                                if(result.length > 0){
                                     //logical operation
                                }
          
                           }
                        },
                        {escape: true}
                    }

                 </script>

           </apex:page>

        Controller:

       Global class testClass{

             @RemoteAction
             Global void check(String name){

                  String s= name;

                  apexPages.addMessages(s);

             }

        }

Call JS function and Controller function together from a VF component


Sometimes we need to check values, data entered by the user or simply we validate the input data for better data quality. And after validation we like to go ahead to the database using DML.

It is advisible to use Java script for client side and then use your controller / class for rest of the logics.

This example will show you, how we can achieve both validation and controller from a single command button:


Controller:

 public class testClass{
public boolean renderVar {get;set;}
public string textValue {get;set;}
public testClass(){
renderVar= false;
}
public void showPanel(){
renderVar=true;
}
}



VF Page:

<apex:page controller="testClass">

<script type="text/javascript">
function jsFunction(){
var returnVal = confirm("Do you want to go to controller?");
return returnVal;
}
</script>

<apex:form>
<apex:outputPanel id="panelId" rendered={!renderVar}>
<apex:inputText id="text" value={!textValue} />
</apex:outputPanel>
       
         <!-- Below command button first calls onClick method and if it returns true then goes ahead        
         with action  attribute -->

<apex:commandButton value="Click Me" action="{!showPanel}" onClick = " if(!jsFunction()    
         {return false;} )"  reRencder="panelId">

</apex:form>
</apex:page>


Please note: onComplete attribute of command button component can also be used to do operations post controller action call.

Java script validations - String, DOB, Email & Alphanumeric



  • Alphanumeric validation

     The code for the alpha Numeric validation in javascript is below:

     function alphanumericValidation(obj){
            var i = 0;
            var returnVal = true;
            if(obj != null){
                var val = new String(obj.value);
                for(i = 0; i<val.length; i++){
                    var ch = val.charAt(i);
                    if((ch<'a' || ch>'z') && (ch<'A' || ch>'Z') && (ch<'0' || ch>'9')){
                        alert('Only alphanumeric characters are allowed in this field.');
                        obj.focus();
                        obj.select();
                        returnVal = false;
                        break;                      
                    }
                }
                if(returnVal){
                    return true;
                }
                else{
                    return false;
                }
            }
        }


  • DOB validation:
     Code for DOB validation in JS in below:

      // the format for DOB is yyyy-mm-dd

      function dobValidation(dob){
            var yearfield=dob.value.split("-")[0];
            var monthfield=dob.value.split("-")[1];
            var dayfield=dob.value.split("-")[2];
            var mon = parseFloat(monthfield);
            
            var returnval=false;
            var date = dob.value;

            if(date.length == 10){           
                if(date[4] == '-' && date[7] == '-'){
                    var dateOfBirth = new Date(yearfield,monthfield,dayfield); 
                    var today = new Date();
                    
                    var oneDay=1000*60*60*24;
                    var diff = Math.ceil((today.getTime() - dateOfBirth.getTime()) / oneDay);
                    if(diff <= 0){
                        alert('Birth date cannot be today or in future. Please enter again.');
                        returnval=false;
                    }
                    else{
                        var yearInt = parseFloat(yearfield);
                        var currYearInt = today.getFullYear();
                        var monthInt = parseFloat(monthfield);
                        var dayInt = parseFloat(dayfield);                                              
                        if(monthInt >= 1 && monthInt <= 12){
                           if(dayInt>=1 && dayInt <= 31){
                               returnval=true;
                            }
                            else{
                               alert('Date cannot be greater than 31 or less than 1.');
                               returnval=false;
                            }                                
                         }
                         else{
                            alert('Month cannot be greater than 12 or less than 1.');
                            returnval=false;
                         }                            
                    }                
                }   
                else{
                    alert('Birth date format invalid. Please enter again in \'yyyy-mm-dd\' format. eg: \'1999-
                            01-01\'');
                    returnval=false;
                } 
            } 
            else{
                alert('Invalid birth date. Please enter again in \'yyyy-mm-dd\' format. eg: \'1999-01-01\'');
                returnval=false;
            } 
            if (returnval==false){ 
                dob.select();
            }
            return returnval;                       
        }  

  • Email validation:
        Code for email validation is below:

        function emailValidate(text){ // text is the object which contains email value.
            var str=text.value;
            var returnVal = true;
            if(str!=''){
                var filter=/^([A-Za-z0-9_\-\.])+@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,3})$/
                if (!filter.test(str)){                    
                    returnVal = false;
                }
            } 
            if(returnVal){
                return true;
            }
            else{
                text.focus();
                text.select();                
                alert("Invalid Email Address. Valid Example:abc1@abc.com");  
                return false;             
            }  
        }  

  • String validation:
        This is the code for String validation, only alphabets are allowed in the string.

        function stringValidation(name){ // name is the object of the component which contains string.
            var i = 0;
            var returnVal = true;
            if(name!=null){
                var val = new String(name.value);
                for(i = 0; i<val.length; i++){
                    var ch = val.charAt(i);
                    if((ch<'a' || ch>'z') && (ch<'A' || ch>'Z')){
                        alert('Only alphabets are allowed in this field.');
                        name.focus(); // this sets the focus to the field which contains the string.
                        name.select(); // this selects the string so that the user can change directly.
                        returnVal = false;
                        break;
                    }
                }
                if(returnVal){
                    return true;
                }
                else{
                    return false;
                }                
            }
        }

Disabled components in Visual Force(VF) page

Sometimes we disable the components in VF page to make it read only, it works fine in firefox and other browsers too. But when it comes to the IE, it doesnt work properly as per our requirements.

ex: <apex:inputText id="text" disabled="true">

Here is the reason why it doesnt work properly. IE believes that if a component is disabled that means
user is not going to perform any action on it, so that 'tag' does not work too. so always use "readonly"
attribute to make a component only readable.

ex: <apex:inputText id="text" readOnly="true">

Set any page as current page in a apex test class

This is a very common scenario where we need to set a page as current page in the test class, so that we can test related controller functionality. Below is the easiest example to understand the syntax:


Syntax for test class:

    @isTest
    private class testClass{
        public static testMethod void testFunction(){ 
            // test class logic    
            //Create Page Reference - 'test_Page' is the name of Page       
            PageReference pgRef = Page.test_Page;
            Test.setCurrentPage(pgRef); //Set the page for Test Method
        }
    }

Note:

1. Syntax for passing any value to the URL. Here lang is the variable which is passed to the URL and English is the value for that variable:
  
pgRef.getParameters().put('lang','English');

How to return or redirect a visual force(VF) page from JS & controller

In many instances we need to return a page on some action. There are various ways to return a page.

1. If you want to display your object home page from controller, i.e, page displays when u click on the object tab,

    // in this example when this function will be called, it will return the pageReference of object.
   
    public pageReference cancel(){

         // I have hardcoded the link of the object home page in this example.                   
         pageReference pr = new pageReference('/a0E/o');

         return pr;
    }

 2. If you want to display any VF page.

        public pageReference cancel(){

            return Page.test_page;   // here test_page is the name of VF page.  
      
        }
   
    or

        public pageReference cancel(){

            PageReference pr;

            pr = Page.test_page;// here test_page is the name of VF page.
       
            pr.setRedirect(true);

            return pr;             
         }
   


3. if you want to return edit or view page of a record. view() and edit() internally calls the page assigned in the object for view and edit. If no page is assigned
then it opens default page.

    // this function saves the record and display its details
    public pageReference save(){

        insert(obj); // obj is the reference of the Object which is currently in use.

        return (new ApexPages.StandardController(obj)).view();

    }

    // this function opens the record in editable form
    public pageReference edit(){

        // obj is the reference of the Object which is currently in use.

        return (new ApexPages.StandardController(obj)).edit();

    }

4. If you want to display your object home page from javascript

    window.onload=function redirect(){

        parent.frames.location.replace('/a0F/o');

        // I have hardcoded the link of the object home page in this example.

    }

5. if you want display detail page of a record from javascript

    function redirect(){

         // Obj_Test__c is API name of my object.     and Obj_Test__c should be mapped to the current  
         object id in the controller.

         parent.frames.location.replace('/{!Obj_Test__c.Id}');

    }   

6. If you want to return to the home page of a object, through javascript using global variable.
   
    window.onload = function redirect()
    {
         // this will return the home page of Obj_Test__c.          
         window.parent.location.href = "/{!$ObjectType.obj_Test__c}";
    }

7. if you want to close a window from javascript

    function closeWindow(){
            window.close(); // this will close the current window.
    }

Create a Task using Apex

Apex provides the facility to create a Task activity and assign it to the respective users. We can create task via controller for a user or group of users. But Salesforce Task can't be share among the users so each user will have their own copy of Task created.

Below is the syntax to create a task in Salesforce

Controller syntax:
    public class example{
        public void createTask(){
            Task taskCreation = new Task(); // object initialized
                taskCreation.Priority = 'Normal'; // setting the priority of the task
                taskCreation.Status = 'Not Started'; // current status of the task
                taskCreation.Subject = 'New task created'; // subject for the task
                taskCreation.ActivityDate = System.today().addDays(10); // setting the due date
                taskCreation.Description = 'This task is created for testing.';
                // e is the instance of any record.
                // ownerId should be the id of a user for which task needs to be created.
                taskCreation.OwnerId = e.CreatedById;
                taskCreation.WhatId = e.id; // this will set the id for which task is created.          
                insert taskCreation;
        }
    }

Note:
1. If you want to assign a contact to a task, then you can use WhoId field to set the values.