At that point I was like "gee if I could use Paging with the pageBlockTable tag" and then I decided to write it myself. So here is goes:
As we all know we should have two pieces of code, one for the Controller and the other is for the page tags.
The whole idea here is to create two lists on the controller object which one keeps the original records (all records) and the second one temporarily keeps only what should be shown to the user.
With defining a few parameters such as Total Pages, Current Page Number and Page size I managed to simulate paging successfully.
Here is what goes to the page:
<apex:page controller="MyPagingController" tabStyle="Account">
<apex:sectionHeader title="Accounts List with Paging"></apex:sectionHeader>
<apex:form >
<apex:pageBlock title="" id="pageBlock">
<apex:pageBlockButtons location="top">
<apex:commandButton value="View" action="{!ViewData}" id="theButton" rerender="pageBlock"></apex:commandButton>
</apex:pageBlockButtons>
<apex:pageMessages ></apex:pageMessages>
<div align="right" style="display:{!IF(NOT(ISNULL(accounts)),'block','none')}">
<font size="1pt">Page #: <apex:outputLabel value="{!PageNumber}"/> out of <apex:outputLabel value="{!totalPageNumber}"/> </font>
<apex:commandButton value="Previous" action="{!previousBtnClick}" disabled="{!previousButtonEnabled}" reRender="pageBlock"></apex:commandButton>
<apex:commandButton value="Next" action="{!nextBtnClick}" reRender="pageBlock" disabled="{!nextButtonDisabled}" ></apex:commandButton>
</div>
<br/><br/>
<apex:pageBlockTable value="{!accounts}" var="a" rendered="{!NOT(ISNULL(accounts))}" rows="{!PageSize}">
<apex:column >
<apex:facet name="header">Account Name</apex:facet>
<apex:outputLink value="/{!a.Id}" target="_blank">{!a.Name}</apex:outputLink>
</apex:column>
<apex:column value="{!a.Phone}"></apex:column>
<apex:column value="{!a.Fax}"></apex:column>
</apex:pageBlockTable>
<div align="right" style="display:{!IF(NOT(ISNULL(accounts)),'block','none')}">
<br/>
<font size="1pt">Page #: <apex:outputLabel value="{!PageNumber}"/> out of <apex:outputLabel value="{!totalPageNumber}"/> </font>
<apex:commandButton value="Previous" action="{!previousBtnClick}" disabled="{!previousButtonEnabled}" reRender="pageBlock"></apex:commandButton>
<apex:commandButton value="Next" action="{!nextBtnClick}" reRender="pageBlock" disabled="{!nextButtonDisabled}" ></apex:commandButton>
</div>
</apex:pageBlock>
</apex:form>
</apex:page>
Below is the code for Controller:
public class MyPagingController {
private List
private List
private Integer pageNumber;
private Integer pageSize;
private Integer totalPageNumber;
public Integer getPageNumber()
{
return pageNumber;
}
public List
{
return pageAccounts;
}
public Integer getPageSize()
{
return pageSize;
}
public Boolean getPreviousButtonEnabled()
{
return !(pageNumber > 1);
}
public Boolean getNextButtonDisabled()
{
if (accounts == null) return true;
else
return ((pageNumber * pageSize) >= accounts.size());
}
public Integer getTotalPageNumber()
{
if (totalPageNumber == 0 && accounts !=null)
{
totalPageNumber = accounts.size() / pageSize;
Integer mod = accounts.size() - (totalPageNumber * pageSize);
if (mod > 0)
totalPageNumber++;
}
return totalPageNumber;
}
public MyPagingController()
{
pageNumber = 0;
totalPageNumber = 0;
pageSize = 20;
ViewData();
}
public PageReference ViewData()
{
accounts = null;
totalPageNumber = 0;
BindData(1);
return null;
}
private void BindData(Integer newPageIndex)
{
try
{
if (accounts == null)
accounts = [Select id, Name, Phone, Fax from Account limit 1000];
pageAccounts = new List
Transient Integer counter = 0;
Transient Integer min = 0;
Transient Integer max = 0;
if (newPageIndex > pageNumber)
{
min = pageNumber * pageSize;
max = newPageIndex * pageSize;
}
else
{
max = newPageIndex * pageSize;
min = max - pageSize;
min = (min <>
}
for(Account a : accounts)
{
counter++;
if (counter > min && counter <= max)
pageAccounts.add(a);
}
pageNumber = newPageIndex;
if (pageAccounts == null || pageAccounts.size() <= 0)
ApexPages.addmessage(new ApexPages.message(ApexPages.severity.INFO,'Data not available for this view.'));
}
catch(Exception ex)
{
ApexPages.addmessage(new ApexPages.message(ApexPages.severity.FATAL,ex.getMessage()));
}
}
public PageReference nextBtnClick() {
BindData(pageNumber + 1);
return null;
}
public PageReference previousBtnClick() {
BindData(pageNumber - 1);
return null;
}
}
Nice code, Sam. Thank you!
ReplyDeleteI appreciate the work you've done!
BTW, is there a way to bind a custom non-SF table (say MyProduct) to the List<> collection?
Sure you can create an Apex class and keep them in a collection. Apex class are drived from sObject so you can bind them with pageBlockTable or other components.
ReplyDeleteHi again, Sam.
ReplyDeleteIt seems that I'm going in the wrong direction, and I can't figure out how to make the custom list work. Could you please have a look at my code?
Here's the Apex class that is supposed to represent the collection item:
public class MyProduct {
private String id;
private String name;
private String price;
public String getId() { return id; }
public String getName() { return name; }
public String getPrice() { return price; }
public MyProduct()
{
id = '0';
name = '';
price = '';
}
}
Here's the S-Control controller code:
public class ProductsController {
private List<MyProduct> products;
public List<MyProduct> getProducts() { return products; }
private void BindData()
{
String strQuery = 'SELECT Id, Name, Price FROM MyProduct';
products = database.query(strQuery); // error occurs here!
}
}
I get an error when I try to bind the DB query results to the products collection:
Error: Compile Error: Illegal assignment from LIST:SObject to LIST:MyProduct at line...
Can you tell what am I doing wrong?
Trying to run your code for paging of data. Receiving a compile error for the controller. "Compile Error: expecting a left angle bracket, found 'accounts' at line 2 column 14". Just starting with VF, I need this functionality but I am not yet skilled enough to see the trouble in the code.
ReplyDeleteNice post, appreciate the code samples to get ideas from.
ReplyDeleteBtw, I saw paging is supported natively from Winter'09. =)
Nice blog Sam.
ReplyDeletePaging is now native - check out my blog post on this - it simplifies your code quite a bit :-)
Regards,
Jon
This comment has been removed by the author.
ReplyDeleteHello Sam nice post!
ReplyDeleteWhat about the code if records are more than 1000?
thanks
Thats a good question.. what if the count of records is > 1000. How can we fetch 10,000 records from SOQL. Becoz the max limit is 10000
ReplyDeleteGreat job bro....I appreciate your effort
ReplyDeletecool man,i like your articles,great work
ReplyDeleteI have been visiting various blogs for my term papers writing research. I have found your blog to be quite useful. Keep updating your blog with valuable information... Regards
ReplyDeleteFantastic, cheers fella!
ReplyDeletecan u give me code to show records in multiple pages using next and previous buttons?
ReplyDeleteNice post....
ReplyDeleteSorry boss, Thank u boss... Great job.....
ReplyDeleteHi
ReplyDeleteI want to display a blank table with 10 rows and 3 columns ... Is there any wayto do this?
you can use readonly="true" in your page
ReplyDelete== It will increase your data from 1000 to 10000.
Hey great post. This is very useful indeed.
ReplyDeleteAlso do you know if this can be used with a Apex:dataTable instead or does Apex:datatable provide any out of the box means to provide a paging mechanism.
You Rock man!! Proud of you!
ReplyDeleteHey Really Good Post.
ReplyDeleteJust wanted to know.There is a missin code in controller class.
min = min<>....which is giving compliation error.Can u plz rectify it....Can i omit it.Would it effect functionality.
Hi All,
ReplyDeleteI am using jstree.js to display hierarachical data on treeview.
However because of the size of the data, tree takes ages to load on the
browser.
For that reason, I want to build custom paging solution similar to custom
paging in datagrid/gridview...
Any pointer/help for how to build custom paging for Tree?
Thanks,
Phuong vo
For some reason, Previous Page for me doesn't respond, but Next page does. I look at debug and it doesn't even show it as Invoking. But the action and other settings are precisely bound to the Controller. Any ideas?
ReplyDeleteBTW, here is the VF code used for Next/Previous page
ReplyDeletePrevious Page
Next Page
and the APEX code for them:
public void NextPage() {
GetSelected();
nPage += 1;
system.debug('nPage: ' + nPage);
} // END NextPage
public void PreviousPage() {
GetSelected();
nPage -= 1;
system.debug('nPage: ' + nPage);
} // END PreviousPage
nice help full code
ReplyDelete