Sunday, July 2, 2017

Wrapper class usage in apex and visualforce pages.

A common use case for Visualforce is to present a list of sObjects, allowing a user to select a number of these, and then choose an action to apply to the selected entries. Marking an sObject entry as selected presents a challenge, as it is associating transient information, the selected status, with a record persisted in the Salesforce database.

The solution is to use a wrapper class to encapsulate or wrap an sObject instance and some additional information associated with the sObject instance.

In the below example i developed a visualforce page with delete functionality based on the selected account records. when ever user select's particular account records to delete then wrapper object holds the selected account with check box value as true, then based on the check box value we can able to delete the particular selected account records.

Controller Class: 
Here i am using custom controller to develop the wrapper functionality, HereAccountRecordCls  is wrapper class to have multiple things like  holding the selected account record with check-box value and individual account record.

---------------------------------
Example:
<apex:page controller="Checkbox_Class" Tabstyle="Account">
    <apex:form >
     <apex:pageBlock Title="List of Accounts" >
     <apex:pageBlockButtons >
     <apex:commandButton value="Display the selected Records" action="{!GetSelected}" rerender="Selected_PBS"/>
     </apex:pageBlockButtons>
        <apex:pageblockSection >
            <apex:pageBlockSection Title="List of Available Accounts" columns="1" >
                <apex:pageblockTable value="{!accounts}" var="a1" >
                    <apex:column >
                        <apex:facet name="header">
                            <apex:inputCheckbox onclick="selectAllCheckboxes(this,'inputId')"/>
                        </apex:facet>
                        <apex:inputCheckbox value="{!a1.selected}" id="inputId"/>
                    </apex:column>
                    <apex:column headervalue="Account Name" value="{!a1.acc.Name}" width="200"/>
                    <apex:column headervalue="Phone" value="{!a1.acc.Phone}" width="300"/>
                </apex:pageblocktable>
            </apex:pageBlockSection>

            <apex:pageBlockSection Title="Selected Accounts" id="Selected_PBS" columns="1">
                <apex:pageblockTable value="{!SelectedAccounts}" var="s"  >
                    <apex:column headervalue="Account Name" value="{!s.Name}" width="30"/>
                  <apex:column headervalue="Phone" value="{!s.Phone}" width="30"/>
                </apex:pageblockTable>
            </apex:pageBlockSection>
</apex:pageblockSection>
        </apex:pageBlock>
    </apex:form>
    <script type="text/javascript">
        function selectAllCheckboxes(obj,receivedInputID){
            var inputCheckBox = document.getElementsByTagName("input");
            for(var i=0; i<inputCheckBox.length; i++){
                if(inputCheckBox[i].id.indexOf(receivedInputID)!=-1){
                    inputCheckBox[i].checked = obj.checked;
                }
            }
        }
    </script>

</apex:page>

Controller:

public class Checkbox_Class

{
     List<accountwrapper> accountList = new List<accountwrapper>();
     List<Account> selectedAccounts = new List<Account>();

  /* public Pagereference displaytheselectedaccounts()
   {
   return null;
   }  */

public List<accountwrapper> getAccounts()
   {
    for(Account a1 : [select Id, Name, AccountNumber, Phone from Account limit 10]){
    
    system.debug('for loop begin..'+a1 );
    accountList.add(new accountwrapper(a1));
    system.debug('for loop ending..'+accountList );
    }
    return accountList;
    }

public PageReference getSelected()
    {
    selectedAccounts.clear();
    for(accountwrapper accwrapper : accountList)
    if(accwrapper.selected == true)
    selectedAccounts.add(accwrapper.acc);
    system.debug('for loop select..'+selectedAccounts);
    return null;
    }

public List<Account> GetSelectedAccounts()
    {
    if(selectedAccounts.size()>0)
    return selectedAccounts;
   else
   return null;
    }

public class accountwrapper
   {
   public Account acc{get; set;}
   public Boolean selected {get; set;}
  public accountwrapper(Account a1)
   {
   acc = a1;
   selected = false;
}
}

}
--------------------------------public class AccountDeleteWrapperCLs{
public List<AccountRecordCls> accWrapperRecordList {get;set;}


 public AccountDeleteWrapperCLs(){
 List<Account> accList= new List<Account>();
 accWrapperRecordList = new List<AccountRecordCls>();
 accList = [select id,Name,Phone,AccountNumber from Account];
  if(!accList.isEmpty()) {
    for(Account acc: accList){
     AccountRecordCls arcls = new AccountRecordCls();
     arcls.isSelected =  false;
     arcls.accObj = acc;
     accWrapperRecordList.add(arcls);
    
    } //end of for loop.
  
  } //end of if condition.
 }
  
  /*
   Delete Account functionality based on the selected records.
  */
  public PageReference DeleteAccount(){
   List<Account> accToDelete = new List<Account>();
   //To hold the unselected account records.
   List<AccountRecordCls> listUnSelectedRecords  = new List<AccountRecordCls>();  
    if(accWrapperRecordList !=null && accWrapperRecordList.size()>0) {
      for(AccountRecordCls wrapObj :  accWrapperRecordList){
        if(wrapObj.isSelected == true){
          accToDelete.add(wrapObj.accObj);
        }else{
          listUnSelectedRecords.add(wrapObj);
        }
      
      
      }//end of for.
      /*
       checking the delete list size and assign the unselected values to 
       original wrapper list.
      */
      if(accToDelete !=null && accToDelete.size()>0){
       delete accToDelete;
       accWrapperRecordList.clear();
       accWrapperRecordList.addAll(listUnSelectedRecords);
      }
    
    }else{
     ApexPages.Message  myMsg = new ApexPages.Message(ApexPages.Severity.info, 'Records were not there to delete.');
     ApexPages.addMessage(myMsg);
    }
    
    return null;
  }

  

 /* Wrapper class with checkbox and account object. 
  this is also  called as inner class 
  */

 public class AccountRecordCls{
  public boolean isSelected {get;set;}
  public Account accObj {get;set;}

 }

}

Visualforce Page: 


<apex:page controller="AccountDeleteWrapperCLs">

 <!-- This i am using for action status message display with processing records information -->

 <style>
    /* This is for the full screen DIV */
    .popupBackground {
        /* Background color */
        background-color:black;
        opacity: 0.20;
        filter: alpha(opacity = 20);
    
        /* Dimensions */
        width: 100%;
        height: 100%;
        top: 0;
        left: 0;
        z-index: 998;
        position: absolute;
        
        /* Mouse */
        cursor:wait;
    }

    /* This is for the message DIV */
    .PopupPanel {
        /* Background color */
        border: solid 2px blue;
        background-color: white;

        /* Dimensions */
        left: 50%;
        width: 300px;
        margin-left: -100px;
        top: 50%;
        height: 50px;
        margin-top: -25px;
        z-index: 999;
        position: fixed;
        
        /* Mouse */
        cursor:pointer;
    }
</style>
<apex:actionStatus id="deleteStatus" stopText="">
    <apex:facet name="start">
        <div>
            <div class="popupBackground" />
            <div class="PopupPanel">
                <table border="0" width="100%" height="100%">
                    <tr>
                        <td align="center"><b>Please Wait</b></td>
                    </tr>
                    <tr>
                        <td align="center"><img src="{!$Resource.AJAXProgressBar}"/></td>
                    </tr>
                </table>
            </div>
        </div>
    </apex:facet>
</apex:actionStatus>

 <!-- end of Action Status --> 
<apex:pagemessages id="Msg"> </apex:pagemessages>
<apex:pagemessage summary="Your are doing Mass Delete On Account Object" Severity="Info" Strength="2"></apex:pagemessage>


 <apex:form id="theForm">
  <apex:commandButton value="Delete Account" action="{!DeleteAccount}" reRender="thePb,Msg" status="deleteStatus"/>
  <apex:pageblock id="thePb">
   <apex:pageblockTable value="{!accWrapperRecordList}" var="record">
   <apex:column headerValue="Select">
     <apex:inputCheckbox value="{!record.isSelected}"/>
    </apex:column> 
    <apex:column value="{!record.accObj.Name}"/>
     <apex:column value="{!record.accObj.Phone}"/>
      <apex:column value="{!record.accObj.AccountNumber}"/>
   </apex:pageblockTable>  
  </apex:pageblock> 
 </apex:form>

</apex:page>



Example of using Wrapper class:

1). http://sfdcsrini.blogspot.com/2014/12/adding-and-deleting-rows-dynamically-in.html

2). http://sfdcsrini.blogspot.com/2014/08/displaying-records-in-visualforce-page.html

Visualforce PDF Rendering Considerations and Limitations
                       OR
RenderasPDF considerations in visualforce

Limitations of the Visualforce PDF rendering service include:


  • PDF is the only supported rendering service.
  • Rendering a Visualforce page as a PDF is intended for pages designed and optimized for print.
  • Standard components that aren’t easily formatted for print, or form elements like inputs, buttons, or any component that requires JavaScript to be formatted, shouldn’t be used. This includes, but isn’t limited to, any component that requires a form element.
  • PDF rendering doesn’t support JavaScript-rendered content.
  • Font used on the page must be available on the Visualforce PDF rendering service. Web fonts aren’t supported.
  • If the PDF fails to display all of the page’s text, particularly multi-byte characters such as Japanese or accented international characters, adjust the fonts in your CSS to use a font that supports them. For example:
  • Arial Unicode MS” is currently the only font supported for extended character sets that include multi-byte characters.
  • If you use inline CSS styles, you must set the API version to 28.0 or greater, set <apex:page applyBodyTag="false">, and add static, valid<head> and <body> tags to your page, as in the example above.
  • The maximum response size when creating a PDF must be below 15 MB before being rendered as a PDF. This is the standard limit for all Visualforcerequests.
  • The maximum file size for a generated PDF is 60 MB.
  • The maximum total size of all images included in a generated PDF is 30 MB.
  • PDF rendering doesn’t support images encoded in the data: URI scheme format.
  • Note that the following components do not support double-byte fonts when rendered as a PDF:
    • <apex:pageBlock>
    • <apex:sectionHeader

                These components aren’t recommended for use in pages rendered as a PDF.



How to Use Apex:enhancedList tag in Visualforce Page?

How to Use Apex:enhancedList tag in Visualforce Page?

Enhanced list views on a Visualforce page

Enhanced lists are used when you want to display a specific list view for a standard or custom object, rather than having all list views available for the user to select.
This tag supports following attributes.

Attribute Name
Description
customizable
A Boolean value that specifies whether the list can be customized by the current user. If not specified, the default value is true. If this attribute is set to false, the current user will not be able to edit the list definition or change the list name, filter criteria, columns displayed, column order, or visibility. However, the current user's personal preferences can still be set, such as column width or sort order.
height
An integer value that specifies the height of the list in pixels. This value is required.

id
The database ID of the desired list view. When editing a list view definition, this ID is the 15-character string after 'fcf=' in the browser's address bar. This value is required if type is not specified.
listId
The Salesforce object for which views are displayed. This value is required if type is not specified.
oncomplete
The JavaScript that runs after the page is refreshed in the browser. Note that refreshing the page automatically calls this JavaScript, while an inline edit and subsequent save does not.
rendered
A Boolean value that specifies whether the component is rendered on the page. If not specified, this value defaults to true.
reRender
The ID of one or more components that are redrawn when the result of an AJAX update request returns to the client. This value can be a single ID, a comma-separated list of IDs, or a merge field expression for a list or collection of IDs. Note: When an enhancedList is rerendered through another component's rerender attribute, the enhanceList must be inside of an apex:outputPanel component that has layout attribute set to "block".
rowsPerPage
An integer value that specifies the number of rows per page. The default value is the preference of the current user. Possible values are 10, 25, 50, 100, 200. Note: If you set the value for greater than 100, a message is automatically displayed to the user, warning of the potential for performance degradation.
type
The Salesforce object for which views are displayed, for example, type="Account" or type="My_Custom_Object__c".
width
An integer value that specifies the width of the list in pixels. The default value is the available page width, or the width of the browser if the list is not displayed in the initially viewable area of the viewport.



Step 1 – Create the list view

Go to the standard or custom object and click on the Create New View next to the Go button. Create the view and click on Save. When the page has reloaded, you will notice in the url a 15 digit id has been created for your view. Copy or make a note of the id.






Step 2 – Add code to your visualforce page

Add the following bit of code to your visualforce page, replacing the listid with your id:


<apex:enhancedlist type=”Lead” height=”730″ customizable=”false” rowsPerPage=”25″ Listid=”00B30000007wesH” />

Change customizable to equal true if you want your users to be able to edit the filters on the view. Once saved, you should find your visualforce page displays an enhanced list similar in appearance to the image below.





More about Visualforce page Tags:
http://sfdcsrini.blogspot.com/2014/06/visualforce-form-tags-with-examples.html

Trigger Scenario: 
I have requirement fire the trigger when data is uploading through data loader. It should not execute when record saved from User interface? How to achieve that?



You could add a custom checkbox field which is hidden from the pagelayout.
· This field could be mapped to always insert as "true" with dataloader.
· Make your after insert trigger only execute conditionally on this field to be true.

· Optionally have your trigger set the field to false, or you could keep it as true to see that these records were imported through data loader.

How to Use Apex:relatedList tag in Visualforce Page?

How to Use Apex:relatedList tag in Visualforce Page?


It is going to display a list of Salesforce records that are related to a parent record with a lookup or master-detail relationship.

This tag supports following attributes.

Attribute Name
Description
id
An identifier that allows the relatedList component to be referenced by other components in the page.
list
The related list to display. This does not need to be on an object's page layout. To specify this value, use the name of the child relationship to the related object. For example, to display the Contacts related list that would normally display on an account detail page, use list="Contacts".

pageSize
The number of records to display by default in the related list. If not specified, this value defaults to 5.
rendered
A Boolean value that specifies whether the component is rendered on the page. If not specified, this value defaults to true.
subject
The parent record from which the data and related list definition are derived. If not specified, and if using a standard controller, this value is automatically set to the value of the ID query string parameter in the page URL.
title
The text displayed as the title of the related list. If not specified, this value defaults to the title specified in the application.


Facet Name
Description
body
The components that appear in the body of the related list. Note that the order in which a body facet appears in a relatedList component does not matter, because any facet with name="body" will control the appearance of the related list body. If specified, this facet overrides any other content in the related list tag.
footer
The components that appear in the footer area of the related list. Note that the order in which a footer facet appears in the body of a relatedList component does not matter, because any facet with name="footer" will control the appearance of the bottom of the related list.
header
The components that appear in the header area of the related list. Note that the order in which a header facet appears in the body of a relatedList component does not matter, because any facet with name="header" will control the appearance of the top of the related list.


Example :

<apex:page standardController="Account">
    <apex:pageBlock >
    You're looking at some related lists for {!account.name}:
    </apex:pageBlock>

    <apex:relatedList list="Opportunities" />

    <apex:relatedList list="Contacts">
        <apex:facet name="header">Titles can be overriden with facets</apex:facet>
    </apex:relatedList>

    <apex:relatedList list="Cases" title="Or you can keep the image, but change the text" />
</apex:page>


Pass the account id as url parameter to display the related list.
For example, if 001D000000IRt53 is the account ID, the resulting URL should be:
https://Salesforce_instance/apex/myPage?id=001D000000IRt53






More about Visualforce Tags Examples:

What is Apex Sharing? How to share a records via apex?


Sharing rules, let us make automatic exceptions to organization-wide defaults for particular groups of users.Sharing rules can never be stricter than our org-wide default settings.We can extend the organization wide default setting with sharing rules.

Example – If any object is private with org-wide default  then we can extend the access to public read only or public read write with sharing rule.

Salesforce provide a way by which we can create sharing rule by only point and click  from the salesforce standard. You can set any criteria and give access to the object’s record . Example – Suppose u need to create a sharing rule for lead object when the lead field “Is_public” become true then you can easily add this criteria and give public access to the particular User or group etc.

But some cases are there where we can’t use the standard sharing rule functionality that’s why we need to create sharing rules with apex.

Let’s take a case example  –  I have a field “Reports to” in case object and this field is lookup to User object and we need to give public access to that user for their particular record. Suppose when a case is created and we select some user in the “Reports to” field then we want to give public access to this selected user for that record.So it is not possible with standard sharing rules. We need to create sharing rule for case object via apex.


Here I am sharing the code for how to create sharing rule for any object via Apex,each object has their own sharing object for case it is “CaseShare ” .We need to write down a trigger on case :
 Example:
trigger ShareWithReportingMng on Case (after insert) {
    List<CaseShare> csShareList = new List<CaseShare>();
    for( Case cs : trigger.new ) {
        if( cs.Reports_to__c != NULL ) {
            // Create a new caseShare object for each case where reports_to__c field is not NULL.
            CaseShare csShare = new CaseShare();
            // Give Read write access to that user for this particular case record.
            csShare.CaseAccessLevel = 'edit';
            // Assign case Id of case record.
            csShare.CaseId = cs.id;
            // Assign user id to grant read write access to this particular case record.
            csShare.UserOrGroupId = cs.Reports_to__c;
            csShareList.add( csShare );
        }
    }
    if( csShareList != null && csShareList.size() != 0 ) {
        try {
            insert csShareList;
        }catch( Exception e ) {
            trigger.new[0].Reports_to__c.addError('Error::::::'+e.getMessage());
        }
    }
}

So now you can create sharing rules from apex as above and delete that sharing when needed with apex(delete event).
Considerations and Limits of Sharing Rules

  • Sharing Rules cannot be stricter than Organization Wide Defaults. If access needs to be restricted, another type of security should be used.  Sharing rules are typically used to extend access to records.
  • Manual Sharing is only available on individual records, it is not available for all records of a certain object.
  • Sharing Rules are only applicable on records that have Private or Public Read Only access.
  • With Sharing Rules you have the option to give read only or read/write access to records.  We recommend being very conscious of what level of security users really need (i.e. is the access for informational purposes only or full collaboration).
  • When setting Automatic and Manual Sharing users and admins have the ability to define if the security should be extended to related records.  Make sure that extending the security makes sense before making the final decision to give this access.