+ Start a Discussion
sravusravu 

Urgent Help Needed!!!!!!! StandardSetController pagination not working properly

Hi,

 

I am trying to display the cases based on option selected by the user. I have two options open incidents and closed incidents. By default it will display open incidents. when user selects closed incidents it should display all the closed incidents. I somehow managed to build this. But the pagination is not working properly. For the datatable to refresh I have seen in other posts, that we should not use if(con==null) --  this will not refresh the table. I have commented that part. The moment I have commented that line in my controller, pagination is not working. Could anyhelp me with this issue. Below is my visaluforce page and the controller :

 

 

<apex:page sidebar="false" controller="MyIncidentsPageController">

<script>
var val;
function changeCaseType(changedvalue){
val = changedvalue.value;
setCaseStatusMethod(val);
}
</script>
<apex:form >
<apex:outputPanel >
<apex:selectRadio value="{!caseType}" onchange="changeCaseType(this)">
<apex:selectOptions value="{!items}">
</apex:selectOptions>
</apex:selectRadio>
</apex:outputPanel>
<apex:actionFunction action="{!setCaseStatusMethod}" name="setCaseStatusMethod">
</apex:actionFunction>
<apex:outputPanel style="padding:10px;display:block;" id="caseList">
<apex:dataTable value="{!Cases}" var="OI" headerClass="header" style="border-style:solid;border-width:2px;border-color:#c8c8c8;" rowClasses="odd,even" width="100%">
<apex:column headerValue="Incident" style="padding:10px;">
<apex:outputText >{!OI.CaseNumber}</apex:outputText>
</apex:column>
<apex:column value="{!OI.Created__c}" headerValue="Created" style="padding:10px;color:#2f627f;"/>
<apex:column value="{!OI.Modified__c}" headerValue="Modified" style="padding:10px;color:#2f627f;"/>
<apex:column value="{!OI.Priority}" headerValue="Priority" style="padding:10px;color:#2f627f;"/>
<apex:column value="{!OI.Productweb__c}" headerValue="Product" style="padding:10px;color:#2f627f;"/>
<apex:column value="{!OI.Submitted_By__c}" headerValue="Submitted By" style="padding:10px;color:#2f627f;"/>
<apex:column value="{!OI.Subject}" headerValue="Subject" style="padding:10px;color:#2f627f;"/>
<apex:column value="{!OI.Status}" headerValue="Status" style="padding:10px;color:#2f627f;"/>
</apex:dataTable>
<apex:panelGrid columns="3" style="float:right;" id="links">
<apex:commandLink action="{!previous}" rendered="{!hasPrevious}" style="padding:12px;">Previous</apex:commandlink>
<apex:outputLabel rendered="{!(hasPrevious && hasNext)}" >|</apex:outputLabel>
<apex:commandLink action="{!next}" rendered="{!hasNext}" style="padding:12px;">Next</apex:commandlink>
</apex:panelGrid><br/>
</apex:outputPanel>
<apex:outputpanel style="float:right;display:block;margin-right:7px;padding-top:2px;">

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

 

 

Here is my controller

 

 

public with sharing class MyIncidentsPageController {

public List<Case> caseList {get;set;}
String caseType;
public String caseStatus {get;set;}

public String getcaseType(){
return caseType;
}

public void setcaseType(String caseType){
this.caseType = caseType;
}

public PageReference setCaseStatusMethod(){
caseStatus = caseType;
return null;
}

public MyIncidentsPageController(){
caseType='Open';
caseStatus='Open';
}

public List<SelectOption> getItems(){
List<SelectOption> options = new List<SelectOption>();
options.add(new SelectOption('Open','Open Incidents'));
options.add(new SelectOption('Closed','Closed Incidents'));
return options;
}

public ApexPages.StandardSetController con{
get{
// if(con==null){
con = new ApexPages.StandardSetController(Database.getQueryLocator([select Id,Subject,CaseNumber, Resolution__c,AccountId, Status, Priority,Productweb__c, Created__c,Modified__c,Submitted_By__c,CreatedDate from Case where status=:caseStatus order by CreatedDate desc]));
con.setPageSize(10);
// }
return con;
}
set;
}

public Boolean hasNext{
get{
return con.getHasNext();
}
set;
}

public Boolean hasPrevious {
get{
return con.getHasPrevious();
}
set;
}

public void next(){
con.next();
}

public void previous(){
con.previous();
}

public List<Case> getCases(){
caseList = con.getRecords();
return caseList;
}

}

 

 

 

Thanks in advance.

Best Answer chosen by Admin (Salesforce Developers) 
sfdcfoxsfdcfox

You really shouldn't be initializing your StandardSetController in the getter method; this effectively causes it to re-initialize itself each time the page performs any action at all. Instead, move the assignment of the new StandardSetController to the setCaseStatusMethod, and call this function during your constructor to initialize the default listing. You can actually refactor this a bit better by changing your page as well. Here's my suggestion:

 

 

<apex:page sidebar="false" controller="MyIncidentsPageController">
<!-- removed script -->

<apex:form >
    <apex:outputPanel >
       <apex:selectRadio value="{!caseType}">
           <apex:selectOptions value="{!items}"/>
           <!-- moved onchange event to actionSupport -->
           <!-- added new function to refresh database -->
           <apex:actionSupport event="onchange" action="{!refreshCaseList}" />
       </apex:selectRadio> 
    </apex:outputPanel>
    <apex:outputPanel style="padding:10px;display:block;" id="caseList">
    <apex:dataTable value="{!Cases}" var="OI"  headerClass="header" style="border-style:solid;border-width:2px;border-color:#c8c8c8;" rowClasses="odd,even" width="100%">
        <apex:column headerValue="Incident" style="padding:10px;">  
                <apex:outputText >{!OI.CaseNumber}</apex:outputText>
        </apex:column>
        <apex:column value="{!OI.Created__c}" headerValue="Created" style="padding:10px;color:#2f627f;"/>
        <apex:column value="{!OI.Modified__c}" headerValue="Modified" style="padding:10px;color:#2f627f;"/>
        <apex:column value="{!OI.Priority}" headerValue="Priority" style="padding:10px;color:#2f627f;"/>
        <apex:column value="{!OI.Productweb__c}" headerValue="Product" style="padding:10px;color:#2f627f;"/>
        <apex:column value="{!OI.Submitted_By__c}" headerValue="Submitted By" style="padding:10px;color:#2f627f;"/>
        <apex:column value="{!OI.Subject}" headerValue="Subject" style="padding:10px;color:#2f627f;"/>
        <apex:column value="{!OI.Status}" headerValue="Status" style="padding:10px;color:#2f627f;"/>
    </apex:dataTable>
     <apex:panelGrid columns="3" style="float:right;" id="links">
    <apex:commandLink action="{!previous}" rendered="{!hasPrevious}" style="padding:12px;">Previous</apex:commandlink>
    <apex:outputLabel rendered="{!(hasPrevious && hasNext)}" >|</apex:outputLabel>
    <apex:commandLink action="{!next}" rendered="{!hasNext}" style="padding:12px;">Next</apex:commandlink>
    </apex:panelGrid><br/>
    </apex:outputPanel>
    <apex:outputpanel style="float:right;display:block;margin-right:7px;padding-top:2px;">

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

 

 

public with sharing class MyIncidentsPageController {

    // Removed List<Case> caseList. It's redundant, and we don't need it.
    // Removed String caseStatus, and associated functions. We don't need it. 
    // Removed function setCaseStatusMethod. We don't need it.

    // We now use the default getters and setters instead of getcaseType and setcaseType.
    public String caseType { get; set; }

    // Use default getters and setters instead of initializing controller here.
    public ApexPages.StandardSetController con { get; set; }

    // Single function that initializes the case list.
    public void refreshCaseList() {
        con = new ApexPages.StandardSetController(Database.getQueryLocator([select Id,Subject,CaseNumber, Resolution__c,AccountId, Status, Priority,Productweb__c, Created__c,Modified__c,Submitted_By__c,CreatedDate from Case where status=:caseType order by CreatedDate desc]));
        con.setPageSize(10);
    }

    public MyIncidentsPageController(){
        caseType='Open';
        // We initialize the StandardSetController here
        refreshCaseList();
    }
    
    public List<SelectOption> getItems(){
        List<SelectOption> options = new List<SelectOption>();
        options.add(new SelectOption('Open','Open Incidents'));
        options.add(new SelectOption('Closed','Closed Incidents'));
        return options;
    }

    // Changed this function to a getter only (it should be a read-only property).
    public Boolean getHasNext() {
        return con.getHasNext();
    }
    
    // Changed this function to a getter only (it should be a read-only property).
    public Boolean getHasPrevious() {
        return con.getHasPrevious();
    }
    
    public void next(){
        con.next();
    }

    public void previous(){
        con.previous();
    }
    
    public List<Case> getCases(){
        // Just return the list from the StandardSetController.
        return con.getRecords();
    }

}

This clears up some extra variables (which will reduce view state size, which will reduce page load times), and causes the StandardSetController to only be initialized as necessary. This code is still overly complex, because the StandardSetController's methods can be called directly from Visualforce, so the getters, setters, and functions here are redundant.

 

 

When a page is loaded the first time, the Constructor is called, then any getter methods are called. So, by initializing the StandardSetController in the constructor, we will ensure that con is not null before it is accessed the first time. We changed your onchange javascript attribute to an equivelant actionSupport Visualforce tag, which is Visualforce's way of automatically generating whatever JavaScript needs to be created for an element's events on the fly. This way, we eliminate the need for an actionFunction and the extra functions and variables that you had to support this framework.

 

All Answers

sfdcfoxsfdcfox

You really shouldn't be initializing your StandardSetController in the getter method; this effectively causes it to re-initialize itself each time the page performs any action at all. Instead, move the assignment of the new StandardSetController to the setCaseStatusMethod, and call this function during your constructor to initialize the default listing. You can actually refactor this a bit better by changing your page as well. Here's my suggestion:

 

 

<apex:page sidebar="false" controller="MyIncidentsPageController">
<!-- removed script -->

<apex:form >
    <apex:outputPanel >
       <apex:selectRadio value="{!caseType}">
           <apex:selectOptions value="{!items}"/>
           <!-- moved onchange event to actionSupport -->
           <!-- added new function to refresh database -->
           <apex:actionSupport event="onchange" action="{!refreshCaseList}" />
       </apex:selectRadio> 
    </apex:outputPanel>
    <apex:outputPanel style="padding:10px;display:block;" id="caseList">
    <apex:dataTable value="{!Cases}" var="OI"  headerClass="header" style="border-style:solid;border-width:2px;border-color:#c8c8c8;" rowClasses="odd,even" width="100%">
        <apex:column headerValue="Incident" style="padding:10px;">  
                <apex:outputText >{!OI.CaseNumber}</apex:outputText>
        </apex:column>
        <apex:column value="{!OI.Created__c}" headerValue="Created" style="padding:10px;color:#2f627f;"/>
        <apex:column value="{!OI.Modified__c}" headerValue="Modified" style="padding:10px;color:#2f627f;"/>
        <apex:column value="{!OI.Priority}" headerValue="Priority" style="padding:10px;color:#2f627f;"/>
        <apex:column value="{!OI.Productweb__c}" headerValue="Product" style="padding:10px;color:#2f627f;"/>
        <apex:column value="{!OI.Submitted_By__c}" headerValue="Submitted By" style="padding:10px;color:#2f627f;"/>
        <apex:column value="{!OI.Subject}" headerValue="Subject" style="padding:10px;color:#2f627f;"/>
        <apex:column value="{!OI.Status}" headerValue="Status" style="padding:10px;color:#2f627f;"/>
    </apex:dataTable>
     <apex:panelGrid columns="3" style="float:right;" id="links">
    <apex:commandLink action="{!previous}" rendered="{!hasPrevious}" style="padding:12px;">Previous</apex:commandlink>
    <apex:outputLabel rendered="{!(hasPrevious && hasNext)}" >|</apex:outputLabel>
    <apex:commandLink action="{!next}" rendered="{!hasNext}" style="padding:12px;">Next</apex:commandlink>
    </apex:panelGrid><br/>
    </apex:outputPanel>
    <apex:outputpanel style="float:right;display:block;margin-right:7px;padding-top:2px;">

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

 

 

public with sharing class MyIncidentsPageController {

    // Removed List<Case> caseList. It's redundant, and we don't need it.
    // Removed String caseStatus, and associated functions. We don't need it. 
    // Removed function setCaseStatusMethod. We don't need it.

    // We now use the default getters and setters instead of getcaseType and setcaseType.
    public String caseType { get; set; }

    // Use default getters and setters instead of initializing controller here.
    public ApexPages.StandardSetController con { get; set; }

    // Single function that initializes the case list.
    public void refreshCaseList() {
        con = new ApexPages.StandardSetController(Database.getQueryLocator([select Id,Subject,CaseNumber, Resolution__c,AccountId, Status, Priority,Productweb__c, Created__c,Modified__c,Submitted_By__c,CreatedDate from Case where status=:caseType order by CreatedDate desc]));
        con.setPageSize(10);
    }

    public MyIncidentsPageController(){
        caseType='Open';
        // We initialize the StandardSetController here
        refreshCaseList();
    }
    
    public List<SelectOption> getItems(){
        List<SelectOption> options = new List<SelectOption>();
        options.add(new SelectOption('Open','Open Incidents'));
        options.add(new SelectOption('Closed','Closed Incidents'));
        return options;
    }

    // Changed this function to a getter only (it should be a read-only property).
    public Boolean getHasNext() {
        return con.getHasNext();
    }
    
    // Changed this function to a getter only (it should be a read-only property).
    public Boolean getHasPrevious() {
        return con.getHasPrevious();
    }
    
    public void next(){
        con.next();
    }

    public void previous(){
        con.previous();
    }
    
    public List<Case> getCases(){
        // Just return the list from the StandardSetController.
        return con.getRecords();
    }

}

This clears up some extra variables (which will reduce view state size, which will reduce page load times), and causes the StandardSetController to only be initialized as necessary. This code is still overly complex, because the StandardSetController's methods can be called directly from Visualforce, so the getters, setters, and functions here are redundant.

 

 

When a page is loaded the first time, the Constructor is called, then any getter methods are called. So, by initializing the StandardSetController in the constructor, we will ensure that con is not null before it is accessed the first time. We changed your onchange javascript attribute to an equivelant actionSupport Visualforce tag, which is Visualforce's way of automatically generating whatever JavaScript needs to be created for an element's events on the fly. This way, we eliminate the need for an actionFunction and the extra functions and variables that you had to support this framework.

 

This was selected as the best answer
sravusravu

Thnaks a lot. Worked like a charm.

Pooja Chawla 3Pooja Chawla 3
I have a similar Pagination requirement and have done the same thing mentioned above but pagination is not working . Pls help

public with sharing class SMI_AdjustInvestmentController{

    private ApexPages.StandardController stdController  {get; set;}
    public Map<string,Investment__c> investmentMap = new Map<string,Investment__c>();
    public List<Investment__c> investmentList = new List<Investment__c>();
    public List<Investment__c> tempinvestmentList; 
    public string selectedValue {get;set;}
   // private Id smartAccountId = ApexPages.currentPage().getParameters().get('id');
    //public Smart_Account__c smartAccount = [Select Id,Name from Smart_Account__c where id = :smartAccountId];
   private Id smartAccountId = 'a012C000000FL1T';
   public ApexPages.StandardSetController investmentRecords { get; set; }

  
    
    public SMI_AdjustInvestmentController(ApexPages.StandardSetController controller){
        refreshInvestmentList();
    }
    
        
    public void refreshInvestmentList(){
        investmentRecords = new ApexPages.StandardSetController(
                    Database.getQueryLocator([Select id,Name,Active__c,Auto_Invest_Percent__c,Symbol__c,
                  Shares__c,Price__c,Value__c,smart_category__c,Smart_Fund__c from Investment__c where Smart_Account__c = :SmartAccountId
                  Order By Auto_Invest_Percent__c desc,Symbol__c asc]));
               // investmentRecords.setPageSize(2);          

    }   

   //tempinvestmentList is used for additional additional funds in Investments for a smart account
    public List<Investment__c> getInvestmentRecordsList(){                 
        
        if(investmentList.isEmpty()){             
           investmentList =(List<Investment__c>) investmentRecords.getRecords();
            return investmentList;
        }             
        else if(tempinvestmentList != null){                                                    
           refreshInvestmentList();
           investmentList =(List<Investment__c>)investmentRecords.getRecords();
            return investmentList;        
        }
        else
        return investmentList;        
    }
    
   //Populate Smart Category picklist 
    public List<SelectOption> smartCategory
    {
        get
        {
            List<SelectOption> options = new List<SelectOption>();
            Schema.DescribeFieldResult fieldResult = Smart_Fund__c.Smart_Category__c.getDescribe();
            List<Schema.PicklistEntry> ple = fieldResult.getPicklistValues();
            options.add(new SelectOption('None', '--None--'));
            for( Schema.PicklistEntry f : ple)
                options.add(new SelectOption(f.getLabel(), f.getValue()));
            return options;
        }
    }
   
  // other functionality code


    
    /*** Pagination code ***/
   
    // indicates whether there are more records before the current page set.
    public Boolean hasNext {
        get { return investmentRecords.getHasNext(); }
        set;
    }
    public Boolean hasPrevious {
        get { return investmentRecords.getHasPrevious(); }
        set;
    }
    public void previous() { 
        this.investmentRecords.previous();
    }
    public void next() {
        this.investmentRecords.next();
    }
    
    /*** end Pagination code ***/
}