Friday 18 September 2015

Pagination using Field Sets (i.e. with customizable columns) - Part # 4

Refer to my previous post on Using Field Sets in Visual force pages


This post explains the pagination in salesforce using field sets which allows easy customization of column display including 
a) what to display
b) what order/sequence

Below markup illustrates this:

Visualforce Page

<apex:page standardController="Product2"  recordsetvar="products" extensions="PaginationTutorial_4">
<apex:pageMessages id="pgm"/>
<apex:form >                     
<apex:pageBlock >
    <apex:outputPanel layout="block" styleClass="pSearchShowMore" id="otpNav2">
        Total Records Found: <apex:outputText rendered="{!IF(Con.resultSize==10000,true,false)}">10000 +</apex:outputText><apex:outputText rendered="{!IF(Con.resultSize < 10000,true,false)}">{!Con.resultSize}</apex:outputText>
        <apex:image url="/img/search_prevarrow_disabled.gif" styleClass="prevArrow" rendered="{!NOT(Con.HasPrevious)}"/>
        <apex:image url="/img/search_prevarrow.gif" title="Previous Page" styleClass="prevArrow" rendered="{!Con.HasPrevious}"/>
        <apex:commandLink action="{!Previous}" title="Previous Page" value="Previous Page" rendered="{!Con.HasPrevious}"/>
        <apex:outputPanel styleClass="pShowLess noLink" style="color:grey" rendered="{!NOT(Con.HasPrevious)}">Previous Page</apex:outputPanel>         
        &nbsp;({!IF(Con.PageNumber == 1,1,((Con.PageNumber -1) * Con.PageSize)+1)}-{!IF(Con.resultSize < Con.PageSize,Con.resultSize,Con.PageNumber * Con.pageSize)})&nbsp;
        <apex:outputPanel styleClass="pShowLess noLink" style="color:grey" rendered="{!NOT(Con.HasNext)}">Next Page</apex:outputPanel>         
        <apex:commandLink title="Next Page" value="Next Page" rendered="{!Con.HasNext}" action="{!Next}"/>&nbsp;
        <apex:image url="/img/search_nextarrow.gif" title="Next Page" styleClass="nextArrow" rendered="{!Con.HasNext}"/>
        <apex:image url="/img/search_nextarrow_disabled.gif" rendered="{!NOT(Con.HasNext)}"/>
    </apex:outputPanel>
    <apex:pageBlockTable value="{!products}" var="v">
        <apex:repeat value="{!$ObjectType.Product2.FieldSets.fieldSetForPagination}" var="f">
              <apex:column value="{!v[f.FieldPath]}"/>
        </apex:repeat>      
    </apex:pageBlockTable>
    <apex:outputPanel layout="block" styleClass="pSearchShowMore" id="otpNav">
        Total Records Found: <apex:outputText rendered="{!IF(Con.resultSize==10000,true,false)}">10000 +</apex:outputText><apex:outputText rendered="{!IF(Con.resultSize < 10000,true,false)}">{!Con.resultSize}</apex:outputText>
        <apex:image url="/img/search_prevarrow_disabled.gif" styleClass="prevArrow" rendered="{!NOT(Con.HasPrevious)}"/>
        <apex:image url="/img/search_prevarrow.gif" title="Previous Page" styleClass="prevArrow" rendered="{!Con.HasPrevious}"/>
        <apex:commandLink action="{!Previous}" title="Previous Page" value="Previous Page" rendered="{!Con.HasPrevious}"/>
        <apex:outputPanel styleClass="pShowLess noLink" style="color:grey" rendered="{!NOT(Con.HasPrevious)}">Previous Page</apex:outputPanel>         
        &nbsp;({!IF(Con.PageNumber == 1,1,((Con.PageNumber -1) * Con.PageSize)+1)}-{!IF(Con.resultSize < Con.PageSize,Con.resultSize,Con.PageNumber * Con.pageSize)})&nbsp;
        <apex:outputPanel styleClass="pShowLess noLink" style="color:grey" rendered="{!NOT(Con.HasNext)}">Next Page</apex:outputPanel>         
            <apex:commandLink title="Next Page" value="Next Page" rendered="{!Con.HasNext}" action="{!Next}"/>&nbsp;
            <apex:image url="/img/search_nextarrow.gif" title="Next Page" styleClass="nextArrow" rendered="{!Con.HasNext}"/>
            <apex:image url="/img/search_nextarrow_disabled.gif" rendered="{!NOT(Con.HasNext)}"/>          
    </apex:outputPanel>
</apex:pageBlock>
</apex:form>
</apex:page>

Apex Class


public class PaginationTutorial_4
{    
    public ApexPages.StandardSetController con{get; set;}
    public PaginationTutorial_4(ApexPages.StandardSetController controller) 
    {
        con = controller;
        con.setPageSize(10);
    }
      
    //Boolean to check if there are more records after the present displaying records
    public Boolean hasNext
    {
        get
        {
            return con.getHasNext();
        }
        set;
    } 
    //Boolean to check if there are more records before the present displaying records
    public Boolean hasPrevious
    {
        get
        {
            return con.getHasPrevious();
        }
        set;
    } 
    //Page number of the current displaying records
    public Integer pageNumber
    {
        get
        {
            return con.getPageNumber();
        }
        set;
    }
    //Returns the previous page of records
    public void previous()
    {
        con.previous();
    } 
    //Returns the next page of records
    public void next()
    {
        con.next();
    }
}


Field Set


Preview



Advantages

  • Table columns can be customized anytime by adjusting the field set and ends as just a configuration level change
  • We can make any display level changes by directly editing visual force page
  • Both columns and its sequence of display can be controlled
  • Use the dbrequired flag on field set if the pagination is for inline editing

Disadvantages

  • Pagination is limited only to the direct object fields. That is, relationship fields cannot be included. For example, we cannot display Last Modified By user email in this table. We can include this field in the pagination, but this visual force page will fail with exception: System.SObjectException: SObject row was retrieved via SOQL without querying the requested field: LastModifiedBy.Email.
          Hence this pagination is limited only to direct fields for the object in context.
          Further blog posts will cover this exception. Stay tuned.


Tuesday 15 September 2015

Pagination using Extension controller in addition to the Standard Controller - Part # 3

In this post we are handling the pagination functions via extension controller in addition to the standard controller.

What is Extension Controller?

controller extension is any Apex class containing a constructor that takes a single argument of type ApexPages.StandardController or CustomControllerName , where CustomControllerName is the name of a custom controller you want to extend.

Defining Extension Controller in Visualforce page:
public ApexPages.StandardSetController con{get; set;}
public PaginationTutorial_3(ApexPages.StandardSetController controller) 
{
        this.con = controller;

}


Using Extension Controller in Visualforce page:
<apex:page standardController="Product2"  recordsetvar="products" extensions="PaginationTutorial_3">
.
.
.
.
.
.
</apex:page>


The extension is associated with the page using the extensions attribute of the <apex:page> component.


Defining more than one Extension Controller:

Multiple controller extensions can be defined for a single page through a comma-separated list. This allows for overrides of methods with the same name. For example, if the following page exists:

<apex:page standardController="Account" 
    extensions="ExtOne,ExtTwo" showHeader="false">
    <apex:outputText value="{!foo}" />
</apex:page>
public class ExtOne {
    public ExtOne(ApexPages.StandardController con) { }

    public String getFoo() {
        return 'foo-One';
    }
}

public class ExtTwo {
    public ExtTwo(ApexPages.StandardController con) { }

    public String getFoo() {
        return 'foo-Two';
    }
}

The value of the <apex:outputText> component renders as foo-One. Overrides are defined by whichever methods are defined in the “leftmost” extension, or, the extension that is first in the comma-separated list. Thus, the getFoo method of ExtOne is overriding the method of ExtTwo.

Refer below markup for more details.

Visualforce Page:


<!--
Code Name   : PaginationTutorial_3
Code Type   : Visualforce
Dependency  : PaginationTutorial_3 (Apex Class)
Description : Pagination using Extension controller in addition to the Standard Controller
Author      : Bharathimohan Ramamurthy
-->
<apex:page standardController="Product2"  recordsetvar="products" extensions="PaginationTutorial_3">
<apex:pageMessages id="pgm"/>
<apex:form >                     
<apex:pageBlock >
    <apex:outputPanel layout="block" styleClass="pSearchShowMore" id="otpNav2">
        Total Records Found: <apex:outputText rendered="{!IF(Con.resultSize==10000,true,false)}">10000 +</apex:outputText><apex:outputText rendered="{!IF(Con.resultSize < 10000,true,false)}">{!Con.resultSize}</apex:outputText>
        <apex:image url="/img/search_prevarrow_disabled.gif" styleClass="prevArrow" rendered="{!NOT(Con.HasPrevious)}"/>
        <apex:image url="/img/search_prevarrow.gif" title="Previous Page" styleClass="prevArrow" rendered="{!Con.HasPrevious}"/>
        <apex:commandLink action="{!Previous}" title="Previous Page" value="Previous Page" rendered="{!Con.HasPrevious}"/>
        <apex:outputPanel styleClass="pShowLess noLink" style="color:grey" rendered="{!NOT(Con.HasPrevious)}">Previous Page</apex:outputPanel>         
        &nbsp;({!IF(Con.PageNumber == 1,1,((Con.PageNumber -1) * Con.PageSize)+1)}-{!IF(Con.resultSize < Con.PageSize,Con.resultSize,Con.PageNumber * Con.pageSize)})&nbsp;
        <apex:outputPanel styleClass="pShowLess noLink" style="color:grey" rendered="{!NOT(Con.HasNext)}">Next Page</apex:outputPanel>         
        <apex:commandLink title="Next Page" value="Next Page" rendered="{!Con.HasNext}" action="{!Next}"/>&nbsp;
        <apex:image url="/img/search_nextarrow.gif" title="Next Page" styleClass="nextArrow" rendered="{!Con.HasNext}"/>
        <apex:image url="/img/search_nextarrow_disabled.gif" rendered="{!NOT(Con.HasNext)}"/>          
    </apex:outputPanel>            
    <apex:pageBlockTable value="{!products}" var="v">
      <apex:column value="{!v.name}"/>
      <apex:column value="{!v.IsActive}"/>
      <apex:column value="{!v.ProductCode}"/>
      <apex:column value="{!v.RecordTypeId}"/>
      <apex:column value="{!v.CreatedbyId}"/>
      <apex:column value="{!v.CreatedBy.ProfileId}"/>      
      <apex:column value="{!v.CreatedDate}"/>
    </apex:pageBlockTable>
    <apex:outputPanel layout="block" styleClass="pSearchShowMore" id="otpNav">
        Total Records Found: <apex:outputText rendered="{!IF(Con.resultSize==10000,true,false)}">10000 +</apex:outputText><apex:outputText rendered="{!IF(Con.resultSize < 10000,true,false)}">{!Con.resultSize}</apex:outputText>
        <apex:image url="/img/search_prevarrow_disabled.gif" styleClass="prevArrow" rendered="{!NOT(Con.HasPrevious)}"/>
        <apex:image url="/img/search_prevarrow.gif" title="Previous Page" styleClass="prevArrow" rendered="{!Con.HasPrevious}"/>
        <apex:commandLink action="{!Previous}" title="Previous Page" value="Previous Page" rendered="{!Con.HasPrevious}"/>
        <apex:outputPanel styleClass="pShowLess noLink" style="color:grey" rendered="{!NOT(Con.HasPrevious)}">Previous Page</apex:outputPanel>         
        &nbsp;({!IF(Con.PageNumber == 1,1,((Con.PageNumber -1) * Con.PageSize)+1)}-{!IF(Con.resultSize < Con.PageSize,Con.resultSize,Con.PageNumber * Con.pageSize)})&nbsp;
        <apex:outputPanel styleClass="pShowLess noLink" style="color:grey" rendered="{!NOT(Con.HasNext)}">Next Page</apex:outputPanel>         
            <apex:commandLink title="Next Page" value="Next Page" rendered="{!Con.HasNext}" action="{!Next}"/>&nbsp;
            <apex:image url="/img/search_nextarrow.gif" title="Next Page" styleClass="nextArrow" rendered="{!Con.HasNext}"/>
            <apex:image url="/img/search_nextarrow_disabled.gif" rendered="{!NOT(Con.HasNext)}"/>          
    </apex:outputPanel>
</apex:pageBlock>
</apex:form>
</apex:page>

Extension Controller:


public class PaginationTutorial_3
{    
    public ApexPages.StandardSetController con{get; set;}
    public PaginationTutorial_3(ApexPages.StandardSetController controller) 
    {
        this.con = controller;
        this.con.setPageSize(10);
    }
      
    //Boolean to check if there are more records after the present displaying records
    public Boolean hasNext
    {
        get
        {
            return con.getHasNext();
        }
        set;
    } 
    //Boolean to check if there are more records before the present displaying records
    public Boolean hasPrevious
    {
        get
        {
            return con.getHasPrevious();
        }
        set;
    } 
    //Page number of the current displaying records
    public Integer pageNumber
    {
        get
        {
            return con.getPageNumber();
        }
        set;
    }
    //Returns the previous page of records
    public void previous()
    {
        con.previous();
    } 
    //Returns the next page of records
    public void next()
    {
        con.next();
    }
    
    /*
        
    public List productList
    {
        get
        {
            if(con != null)
                return (List)con.getRecords();
            else
                return null ;
        }
        set;
    } 
    
    */
}


Preview:




Pros:

  • Flexibility in handling pagination via extension controller
  • Compatible design to use Field Sets, especially for Field Sets that include relationship fields (Account.Name on opportunity etc.,). We are discussing this later in another post
  • Ideal design to retrieve and display specific set of records when using SOQL explicitly

Points to Note:

  • Like other Apex classes, controller extensions run in system mode. Consequently, the current user's credentials are not used to execute controller logic, and the user's permissions and field-level security do not apply. However, if a controller extension extends a standard controller, the logic from the standard controller does not execute in system mode. Instead, it executes in user mode, in which the permissions, field-level security, and sharing rules of the current user apply
  • You can choose whether a controller extension respects a user's organization-wide defaults, role hierarchy, and sharing rules by using the with sharing keywords in the class definition