Tuesday, August 25, 2015

PASSING PARAMETERS from one vf to another vf



Many a times you would want to pass parameters to a visualforce page..
There are a number of Situations in which you would want this. This article covers a few of them.
Scenario 1 - From a Custom Button. 
When you create a custom button on "Account",  you will only have the option of selecting Visualforce pages that have the "standardcontroller="Account"" attribute.

To overcome this restriction, select the content source as URL and not visualforce... Then you could type the URL as \apex\yourpage.. And what more you can now pass parameters as you need using merge fields... This method has got one more advantage.. You are not forced to use a standard controller with an extension just for your page to appear in the list when you actually do not need a standard controller.. 



Situation 2 - From a Link.
When you want to pass parameters between visualforce pages use the <apex:param> tag....

Here is a small sample program

Step 1: Create a Visualforce page called SamplePage1....

<apex:page >
<apex:outputlink value="/apex/SamplePage2"> Click Here <apex:param name="msg" value="success"/> </apex:outputlink>
</apex:page>

Step2:  Create a Visualforce page called SamplePage2

<apex:page controller="Sampleclass"> </apex:page>

Step 3:  On SamplePage1 Click on the " Click Here" link. You will see that when you click on the link you will navigate to the SamplePage2. Check the URL now..

https://na5.salesforce.com/apex/SamplePage2?msg=success

You can see that the parameter " msg" with value "success" has been passed to the new page.

Pagereference().getParameters().put()

PageReference is a type in Apex. Read the documentation here. 

When you click a command button or a command link in a visualforce page, you call a method. The return type 
of this method would be a PageReference meaning that, after clicking the button the user will be redirected to a 
new Page. Below is a sample code, which shows how to pass parameters from a PageReference

public Pagereference gotonewpage()
{     
     PageReference pageRef = Page.existingPageName;
     pageRef.getParameters().put('msg','success');
     return PageRef
}

existingPageName - actual name of a visualforce page

Retrieve Parameter Values in Apex Class:

The Apex Class code would be 

public class Sampleclass
{
Public String message = System.currentPagereference().getParameters().get('msg');
}

So now, the variable "message" would store the value of your parameter "msg"....

How to Cover this code in TEST Method?????


public class Sampleclass{Public String message = System.currentPagereference().getParameters().get('msg');public static testmethod void SampleclassTest(){System.currentPagereference().getParameters().put('msg','success');}}


Using Param

how can we pass the id of the contact to the controller? The answer is straightforward, but requires a slight mindshift. 

The <apex:param> standard component allows parameters to be defined for a parent component, which can be assigned to a controller property. I can therefore change my markup to the following to specify the parameter:
?



<apex:commandButton value="Del" action="{!delCont}" rerender="all">  <apex:param name="contIdParam" value="{!cont.id}" assignTo="{!contIdChosen}"/>
</apex:commandButton>


Note the rerender attribute of the commandbutton - if this attribute is not present, the parameter does not get sent back to the controller. I simply have an outputpanel around the entire page contents.


I then add the following property to my controller:

1
public String contIdChosen {get; set;}


The key to this is the behaviour when the button is clicked - the id of the contact instance is assigned to my controller property before the action method is invoked. Thus the method that is actually carrying out the delete can simply access the contIdChosen property secure in the knowledge that it will contain the id of the contact associated with the button:

public PageReference delCont()
{
 Contact toDel=new Contact(id=contIdChosen);

 delete todel;

 setupContacts();

 return null;
}

  


The fact that I have to rerender in order to get the parameter passing to work is the reason why I maintain the list of Contacts independent of the Account record from the standard controller - I can't make the browser refresh the page and thus rebuild the related contacts from scratch, so I have to rebuild the list server side.


Through URL


You can simply pass the parameters through the URL.
say you are redirecting from one VF page to another
string value = 'your param value';
string url;
url = '/apex/VF_Page_Name?param1=' + value; 

PageReference pageRef = new PageReference(url);
pageRef.setRedirect(true);
return pageRef;
Then in the controller of the VF page, you just can get the param like this

String param_value = system.CurrentPageReference.GetParameters().get('param1');

Monday, August 24, 2015

Preventing duplicates by checking two fields

---------------------------------------------------------------------------------------------------------------------

Scenario: Single Contact should not add same Date more than Once.
              This scenario is based on Timesheet filling... system   should not allow user to add                     same date again and again

___________________________________________________________________________________



trigger DuplicateCheckTrigger on Timesheet__c (before insert) {
       Set<string> nameSet = new Set<string>();
     
       Map<id,Date> dtr=new  Map<id,Date>();
       map<Id,List<Timesheet__c>> avoiddups=new map<Id,List<Timesheet__c>>();

        for(Timesheet__c times : trigger.new){
  if(!dtr.containskey(times.ContactId__c)){

  dtr.put(times.ContactId__c,times.StartDate__c);
  }
 
            nameSet.add(times.ContactId__c );      
         
        }

   

      system.debug('%%%%%%%%%%%%%nameSet%%%%%%%%%%%%%%'+nameSet);
        List<Timesheet__c> timList = new List<Timesheet__c>(
            [select id,ContactId__c , StartDate__c,ContactId__r.name from Timesheet__c where ContactId__c in:nameSet]);

            system.debug('%%%%%%%%%%%%%timList%%%%%%%%%%%%%%'+timList);
         
        for(Timesheet__c timess : timList){

     
        if(avoiddups.containskey(timess.ContactId__c)){
   avoiddups.get(timess.ContactId__c).add(timess);
   }
   else{
   avoiddups.put(timess.ContactId__c,new List<Timesheet__c>{timess});
 
   }
}
system.debug('%%%%%%%%%%%%%%%%%%%%%%%%%%%'+avoiddups.values());
system.debug('%%%%%%%%%%%%%%%%%%%%%%%%%%%'+dtr.values());
  For(Timesheet__c str:trigger.new)
  {
    For(Timesheet__c dt:avoiddups.get(str))
    {
 
     if(dt.StartDate__c==dtr.get(str.ContactId__c))
     {
   
     system.debug('%%%%%%%%%%%%%%%%%%%%%%%%%%%'+dt.StartDate__c+'^^^^^^^^^^^^^^^^^^^^^^^^'+dtr.get(str.ContactId__c));
   
     str.StartDate__c.adderror('This date is already specified to this contact: '+dt.ContactId__r.Name);
     }
 
 
    }


  }


}

Recursive triggers handling salesforce



Helper class

----------------------------------------------------------------------------------------------------------------


public class recursioncontrol
{

public static boolean flag=True;

}


-----------------------------------------------------------------------------------------------------------------


Trigger

-----------------------------------------------------------------------------------------------------------------


trigger firsttrigggercontact on Contact (before insert, before update,before delete,after insert,after update,after delete) {



List<Contact> c1=trigger.new;

List<Contact> c2=trigger.old;

if(trigger.isbefore)
{
if(trigger.isinsert)
{
system.debug('%%%%%%%%%%%%am from  before insert%%%%%%%%%%%%%'+c1);
}


if(trigger.isUpdate)
{

system.debug('%%%%%%%%%%%%am from  before update%%%%%%%%%%%%%'+c1);
system.debug('%%%%%%%%%%%%am from  before update%%%%%%Old Values%%%%%%%'+c2);
}


if(trigger.isDelete)
{
system.debug('%%%%%%%%%%%%am from before delete%%%%%%%%%%%%%'+c1);

system.debug('%%%%%%%%%%%%am from  before update%%%%%%%%%%%%%'+c1);
system.debug('%%%%%%%%%%%%am from  before update%%%%%%Old Values%%%%%%%'+c2);
}

}





if(trigger.isafter)
{
if(trigger.isinsert)
{

List<contact> c4=new List<contact>();
contact c5=new contact();
for(contact c3:trigger.new)
{
if(recursioncontrol.flag){
c5.LastName=c3.LastName;
c4.add(c5);
}
recursioncontrol.flag=false;
}
insert c4;

system.debug('%%%%%%%%%%%%am from  after insert%%%%%%%%%%%%%');
}


if(trigger.isUpdate)
{
system.debug('%%%%%%%%%%%%am from  after insert%%%%%%%%%%%%%');

}


if(trigger.isDelete)
{
system.debug('%%%%%%%%%%%%am from  after insert%%%%%%%%%%%%%');

}

}


}

Explaining Trigger events

trigger updatefields on Account (before insert,before update,before delete,after insert,after update,after delete) {



List<account> ac=trigger.new;


List<account> ac1=trigger.old;
if(trigger.isbefore)
{
if(trigger.isinsert )
{


system.debug('333$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$am from insert###################new Data'+ac);

//system.debug('333$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$am from insert###################old Data'+ac1);
For(Account ac3:ac)
{
ac3.Name='Mr.' +ac3.Name;


}



}

if(trigger.isupdate)

{

system.debug('333$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$am from update###################new Data'+ac);
system.debug('333$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$am from update###################old Data'+ac1);


For(Account ac3:ac)
{
if(!ac3.Name.contains('Mr'))
{
ac3.Name='Mr.' +ac3.Name;
}

}


}

if(trigger.isdelete)
{
system.debug('333$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$am from delete');


}
}

if(trigger.isafter)
{
List<contact> con1=new List<contact>();
if(trigger.isinsert)
{
for(account ac6:trigger.new)
{

contact c1=new contact();


c1.lastname=ac6.Name;

con1.add(c1);



}
insert con1;
}
}










}

salesforce trigger error message

Salesforce provides validation rules in configuration for standard as well as custom objects. Validation rule for standard object can be written by navigating to following:
set up --> customise --> standard object name --> validation rule

similarly for custom object you can write validation rule by navigating to following:
set up --> create --> objects --> click on the custom object --> scroll down and click on new(next to validation Rules)

Although, you can write validation using simple configuration, sometimes your requirements may not be fullfilled using validation rule especially when your validation criteria is bit complex or need querying in database to check previously created data. In such a case you can write your logic in trigger.

Lets write down a very basic trigger that will throw a validation errror message.

Scenario : Show error message on account if annual revenue is less than 2000.

The error message can be shown using adderror method as shown in the example below:

trigger validation_using_Trigger on Account (before insert, before update) {
 for(Account acc:trigger.new){
    if(acc.AnnualRevenue < 2000){
       acc.adderror('Annual revenue cannot be less than 2000');
    }
 }
}












message at the top of the page. You can also display your message at a particular field, you only have to mention the field name in the adderror method as in the below example:

trigger validation_using_Trigger on Account (before insert, before update) {
 for(Account acc:trigger.new){
    if(acc.AnnualRevenue < 2000){
       acc.AnnualRevenue.adderror('Annual revenue cannot be less than 2000');
    }
 }
}





Above triggers will also throw validation errors while inserting/updating records using data loader. 

While writing validation you have to make sure that your trigger is bulkified; that is you are properly iterating over for loop(trigger.new)

Also your trigger should run over before insert and before update contexts as you want the message be displayed before the record is created or updated. 

Also the adderror method should always be written in the trigger new context. Trigger will not show error message if you are iterating over some other collection which is not trigger.new 


Thursday, August 13, 2015

Salesforce Triggers

Trigger is piece of code that is executes before and after a record is Inserted/Updated/Deleted from the force.com database.
Syntax:
Trigger <trigger name> on <Object name> (trigger Events) {
// Implement the Logic here
}
Types of Triggers:
– Before Triggers
– After Triggers

Before Trigger: Before triggers are used to perform the logic on the same object and specifically we cannot use the DML operation (Insert, update, delete) on these triggers.
These triggers are fired before the data is saved into the database.
After Trigger: After triggers are used to perform the logic on the related objects and these triggers are used access the fields values that are created by system (Ex: CreatedBy, LasteModifiedBy , Record Id etc..).
Bulk Triggers:
By default every trigger is a bulk trigger which is used to process the multiple records at a time as a batch. For each batch of 200 records.
Trigger Context Variables:
All the trigger context variables are prefixed with “Trigger.” (Ex: Trigger.isInsert, etc..)
isInsert: Returns true if the trigger was fired due to insert operation.
isUpdate: Returns true if the trigger was fired due to update operation.
isDelete: Returns true if the trigger was fired due to delete operation.
isBefore: Returns true if the trigger was fired before record is saved.
isAfter: Returns true if the trigger was fired after record is saved.
New: Returns a list of new version of sObject records.
Old: Returns a list of old version of sObject records.
NewMap: Returns a map of new version of sObject records. (map is stored in the form of map<id,newRecords>)
OldMap: Returns a map of old version of sObject records. (map is stored in the form of map<id,oldRecords>)
Size: Returns a integer (total number of records invoked due to trigger invocation for the both old and new)
isExecuting: Returns true if the current apex code is a trigger.
The below table is tells what are the events we can use in the new trigger and old trigger
Trigger EventTrigger.NewTrigger.Old
Before InsertYesNo
Before UpdateYesYes
Before DeleteNoYes
Before UnDeleteNoYes
After InsertYesNo
After UpdateYesYes
After DeleteNoYes
Trigger Context Variable considerations:
– Trigger.Old is always readOnly
– We cannot delete trigger.new
– In before triggers, trigger.new can be used to update the fields on the same object.
– In After trigger, we get run time exception is thrown when user try to modify the fields in the same object.

Error codes for http requests

HTTP response codeDescription
200“OK” success code, for GET or HEAD request.
201“Created” success code, for POST request.
204“No Content” success code, for DELETE request.
300The value returned when an external ID exists in more than one record. The response body contains the list of matching records.
304The request content has not changed since a specified date and time. The date and time is provided in a If-Modified-Since header. See Get Object Metadata Changes for an example.
400The request couldn’t be understood, usually because the JSON or XML body contains an error.
401The session ID or OAuth token used has expired or is invalid. The response body contains the message anderrorCode.
403The request has been refused. Verify that the logged-in user has appropriate permissions.
404The requested resource couldn’t be found. Check the URI for errors, and verify that there are no sharing issues.
405The method specified in the Request-Line isn’t allowed for the resource specified in the URI.
415The entity in the request is in a format that’s not supported by the specified method.
500An error has occurred within Force.com, so the request couldn’t be completed. Contact Salesforce Customer Support.