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 :
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; }
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:
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.
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:
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.
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(){
//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(); }
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:
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
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:
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.
Thnaks a lot. Worked like a charm.
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 ***/
}