Salesforce Pagination Using OFFSET keyword in SOQL
As per salesforce Governor limitations we can't get more than 1000 records in visualforce page. To display large number of records we can use pagination using OFFSET keyword in controller. OFFSET is use full feature for pagination.
Apex Controller:
public class PaginationController{
// initial query string for contact
String queryString = 'Select Id,FirstName,LastName,Email,Account.Name from Contact';
Integer queryLimit;
Integer offset;
// for active and deactive page naviagator
public Boolean firstOff{set;get;} // previous part
public Boolean lastOff{set;get;} // next part
public String limits{set;get;}
public Integer pageNumber{set;get;}
Integer listSize; // for total contact size
// constructor
public PaginationController(){
firstOff = false;
queryLimit = 10;
offset = 0;
limits = '10';
pageNumber = 1;
aggregateResult res = [select COUNT(id) cnt from Contact ];
// fill size of all contact
listSize = Integer.valueOf(res.get('cnt'));
// initialy check page more then 1 or not
if(listSize > queryLimit) lastOff = true;
else lastOff = false;
}
// get record according to limit and offset
public List<Contact> getRecords(){
return (List<Contact>)database.query(queryString+' LIMIT '+queryLimit+' OFFSET '+offset);
}
// navigate on next page
public void next(){
offset += queryLimit;
if(offset+queryLimit >= listSize) lastOff = false;
firstOff = true;
pageNumber++;
}
// navigate on previous page
public void previous(){
if(offset-queryLimit <= 0){
offset = 0;
firstOff = false;
}
else offset -= queryLimit;
lastOff = true;
pageNumber--;
}
// switch on first page
public void first(){
offset = 0;
firstOff = false;
lastOff = true;
pageNumber = 1;
}
// switch on last page
public void last(){
// set page number of and offset
if(Math.Mod(listSize,queryLimit) == 0){
offset = listSize-queryLimit;
pageNumber = listSize/queryLimit;
}
else{
offset = (listSize/queryLimit)*queryLimit;
pageNumber = (listSize/queryLimit)+1;
}
lastOff = false;
firstOff = true;
}
// for record limits
public List<SelectOption> getItems(){
List<SelectOption> options = new List<SelectOption>();
options.add(new SelectOption('10','10'));
options.add(new SelectOption('20','20'));
options.add(new SelectOption('50','50'));
options.add(new SelectOption('100','100'));
return options;
}
// change query limit
public void changeLimit(){
// set query limit
queryLimit = Integer.valueOf(limits);
offset = 0;
firstOff = false;
// initialy check page more then 1 or not
if(listSize > queryLimit) lastOff = true;
else lastOff = false;
// set page number
pageNumber = 1;
}
// for show current record numbers
public String getRecordInfo(){
integer lastLimit;
if(offset+queryLimit > listSize) lastLimit = listSize;
else lastLimit = offset+queryLimit;
return (offset+1) + ' - ' + lastLimit + ' of '+listSize;
}
// return total page number
public Integer getTotalPage(){
if(Math.Mod(listSize,queryLimit) == 0) return listSize/queryLimit;
else return (listSize/queryLimit)+1;
}
// for direct page switching
public void pageNavigation(){
/* if user enter more then number ot total page number than
set the value last page number in PageNumber. */
if(Math.Mod(listSize,queryLimit) == 0 && pageNumber > listSize/queryLimit)
pageNumber = listSize/queryLimit;
else if(pageNumber > (listSize/queryLimit)+1)
pageNumber = (listSize/queryLimit)+1;
// set offset according to pageNumber
if((pageNumber-1)*queryLimit < 0) offset = 0;
else offset = (pageNumber-1)*queryLimit;
/* if pageNumber is 1 than deactive previous navigator
else if pageNumber is o tha set the value of pageNumber is 1
else if pageNumber is more than 1 active next navigator
*/
if(pageNumber == 1) firstOff = false;
else if(pageNumber == 0) pageNumber = 1;
else if(pageNumber > 1) firstOff = true;
// user enter last number of pagenumber than deactive next navigator
if(Math.Mod(listSize,queryLimit) == 0){
if(pageNumber == listSize/queryLimit) lastOff = false;
else lastOff = true;
}
else{
if(pageNumber == (listSize/queryLimit)+1) lastOff = false;
else lastOff = true;
}
}
}
Visualforce Page:
<apex:page controller="PaginationController">
<apex:form >
<apex:pageBlock id="pgb" title="Accounts Details">
<apex:actionStatus id="status">
<apex:facet name="start">
<div style="width: 1300px;">
<img src="/img/loading24.gif" style="vertical-align:middle;"/>
<span style="margin-left: 10px; font-size:12px; font-weight: bold; color:#000000;">Please wait...</span>
</div>
</apex:facet>
</apex:actionStatus>
<apex:actionFunction name="first" action="{!first}" status="status" reRender="pgb"/>
<apex:actionFunction name="last" action="{!last}" status="status" reRender="pgb"/>
<apex:actionFunction name="next" action="{!next}" status="status" reRender="pgb"/>
<apex:actionFunction name="previous" action="{!previous}" status="status" reRender="pgb"/>
<apex:actionFunction name="changeLimit" action=" {!changeLimit}" status="status" reRender="pgb"/>
<apex:actionFunction name="callAction" action="{!pageNavigation}" status="status" reRender="pgb"/>
<div id="scroll" style="height: 300px; width: 1300px;overflow:auto;">
<apex:pageBlockTable value="{!records}" var="con" id="pgbt">
<apex:column value="{!con.FirstName}"/>
<apex:column value="{!con.LastName}"/>
<apex:column value="{!con.Account.Name}"/>
<apex:column value="{!con.Email}"/>
</apex:pageBlockTable>
</div> <br></br><br></br>
<div style="width:750px;">
<span>
<apex:outputLabel value="{!recordInfo}"/>
<apex:selectList value="{!limits}" size="1" onchange="changeLimit();return false;">
<apex:selectOptions value="{!items}"/>
</apex:selectList>
</span>
<span style="margin: 0 200px;">
<span style="margin: 0 3px;">
<apex:outputPanel rendered="{!firstOff}">
<img src="/s.gif" onclick="first();return false;" style="cursor:pointer; cursor:hand; background- image:Url('/img/paginationArrows.gif');background-position: 0 1px;background-repeat: no-repeat;height:10px;width: 9px"/
</apex:outputPanel>
<apex:outputPanel rendered="{!(!firstOff)}">
<img src="/s.gif" style="cursor:text; background-image:url('/img/paginationArrows.gif');background-position: 0-10px;background-repeat: no-repeat;height: 10px;width: 9px;"/>
</apex:outputPanel>
</span>
<span style="margin: 0 3px;">
<apex:outputPanel rendered="{!firstOff}">
<img class="prev" src="/s.gif" onclick="previous();return false;" style="cursor:pointer; cursor:hand;background-image: url('/img/paginationArrows.gif'); background-position: -10px 1px;background-repeat: no-repeat;height: 10px;margin: 0; padding: 0;width: 9px;"/>
<apex:outputLabel value="Previous" style="cursor:pointer; cursor:hand;" onclick="previous();return false;"/>
</apex:outputPanel>
<apex:outputPanel rendered="{!(!firstOff)}">
<img src="/s.gif" style="cursor:text; background-image: url('/img/paginationArrows.gif');background-position: -10px -10px;background-repeat: no-repeat;height: 10px;margin: 0;padding: 0;width: 9px;"/>
<apex:outputLabel value="Previous" style="cursor:text; color: #A8A8A8"/> </apex:outputPanel> </span>
<span style="margin: 0 3px;">
<apex:outputPanel rendered="{!lastOff}">
<apex:outputLabel value="Next" style="cursor:pointer; cursor:hand;" onclick="next();return false;"/>
<img src="/s.gif" onclick="next();return false;" style="cursor:pointer; cursor:hand; background-image: url('/img/paginationArrows.gif');background-position: -17px 1px; background-repeat: no-repeat;height: 10px; width: 9px;"/>
</apex:outputPanel>
<apex:outputPanel rendered="{!(!lastOff)}">
<apex:outputLabel value="Next" style="cursor:text; color: #A8A8A8"/>
<img src="/s.gif" style="cursor:text; background-image: url('/img/paginationArrows.gif');background-position: -17px -10px;background-repeat: no-repeat;height: 10px;width: 9px;"/>
</apex:outputPanel>
</span>
<span style="margin: 0 3px;">
<apex:outputPanel rendered="{!lastOff}">
<img src="/s.gif" onclick="last();return false;" style="cursor:pointer; cursor:hand; background-image: url('/img/paginationArrows.gif'); background-position: -27px 1px;background-repeat: no-repeat;height: 10px;width: 9px;"/>
</apex:outputPanel>
<apex:outputPanel rendered="{!(!lastOff)}">
<img src="/s.gif" style="cursor:text; background-image: url('/img/paginationArrows.gif');background-position: -27px -10px;background-repeat: no-repeat;height: 10px;width: 9px; "/>
</apex:outputPanel>
</span>
</span>
<span style="margin: 0 -80px;">
<apex:outputLabel value="Page"/>
<apex:inputText id="pageNo" value="{!pageNumber}" style="width:20px; text-align:center" size="3" onkeydown="return runScript(event);"/>
<apex:outputLabel value="of {!totalPage}"/>
</span>
</div>
</apex:pageBlock>
<script>
function runScript(obj){
//alert(obj.keyCode);
if(obj.keyCode == 13){
callAction(); // call action function
return false;
}
else if((obj.keyCode > 34 && obj.keyCode < 40) || (obj.keyCode > 95 && obj.keyCode < 106) || (obj.keyCode > 47 && obj.keyCode < 58) || obj.keyCode == 8 || obj.keyCode == 46 ){
return true;
}else{
return false;
}
}
</script>
</apex:form>
</apex:page>
<apex:form >
<apex:pageBlock id="pgb" title="Accounts Details">
<apex:actionStatus id="status">
<apex:facet name="start">
<div style="width: 1300px;">
<img src="/img/loading24.gif" style="vertical-align:middle;"/>
<span style="margin-left: 10px; font-size:12px; font-weight: bold; color:#000000;">Please wait...</span>
</div>
</apex:facet>
</apex:actionStatus>
<apex:actionFunction name="first" action="{!first}" status="status" reRender="pgb"/>
<apex:actionFunction name="last" action="{!last}" status="status" reRender="pgb"/>
<apex:actionFunction name="next" action="{!next}" status="status" reRender="pgb"/>
<apex:actionFunction name="previous" action="{!previous}" status="status" reRender="pgb"/>
<apex:actionFunction name="changeLimit" action=" {!changeLimit}" status="status" reRender="pgb"/>
<apex:actionFunction name="callAction" action="{!pageNavigation}" status="status" reRender="pgb"/>
<div id="scroll" style="height: 300px; width: 1300px;overflow:auto;">
<apex:pageBlockTable value="{!records}" var="con" id="pgbt">
<apex:column value="{!con.FirstName}"/>
<apex:column value="{!con.LastName}"/>
<apex:column value="{!con.Account.Name}"/>
<apex:column value="{!con.Email}"/>
</apex:pageBlockTable>
</div> <br></br><br></br>
<div style="width:750px;">
<span>
<apex:outputLabel value="{!recordInfo}"/>
<apex:selectList value="{!limits}" size="1" onchange="changeLimit();return false;">
<apex:selectOptions value="{!items}"/>
</apex:selectList>
</span>
<span style="margin: 0 200px;">
<span style="margin: 0 3px;">
<apex:outputPanel rendered="{!firstOff}">
<img src="/s.gif" onclick="first();return false;" style="cursor:pointer; cursor:hand; background- image:Url('/img/paginationArrows.gif');background-position: 0 1px;background-repeat: no-repeat;height:10px;width: 9px"/
</apex:outputPanel>
<apex:outputPanel rendered="{!(!firstOff)}">
<img src="/s.gif" style="cursor:text; background-image:url('/img/paginationArrows.gif');background-position: 0-10px;background-repeat: no-repeat;height: 10px;width: 9px;"/>
</apex:outputPanel>
</span>
<span style="margin: 0 3px;">
<apex:outputPanel rendered="{!firstOff}">
<img class="prev" src="/s.gif" onclick="previous();return false;" style="cursor:pointer; cursor:hand;background-image: url('/img/paginationArrows.gif'); background-position: -10px 1px;background-repeat: no-repeat;height: 10px;margin: 0; padding: 0;width: 9px;"/>
<apex:outputLabel value="Previous" style="cursor:pointer; cursor:hand;" onclick="previous();return false;"/>
</apex:outputPanel>
<apex:outputPanel rendered="{!(!firstOff)}">
<img src="/s.gif" style="cursor:text; background-image: url('/img/paginationArrows.gif');background-position: -10px -10px;background-repeat: no-repeat;height: 10px;margin: 0;padding: 0;width: 9px;"/>
<apex:outputLabel value="Previous" style="cursor:text; color: #A8A8A8"/> </apex:outputPanel> </span>
<span style="margin: 0 3px;">
<apex:outputPanel rendered="{!lastOff}">
<apex:outputLabel value="Next" style="cursor:pointer; cursor:hand;" onclick="next();return false;"/>
<img src="/s.gif" onclick="next();return false;" style="cursor:pointer; cursor:hand; background-image: url('/img/paginationArrows.gif');background-position: -17px 1px; background-repeat: no-repeat;height: 10px; width: 9px;"/>
</apex:outputPanel>
<apex:outputPanel rendered="{!(!lastOff)}">
<apex:outputLabel value="Next" style="cursor:text; color: #A8A8A8"/>
<img src="/s.gif" style="cursor:text; background-image: url('/img/paginationArrows.gif');background-position: -17px -10px;background-repeat: no-repeat;height: 10px;width: 9px;"/>
</apex:outputPanel>
</span>
<span style="margin: 0 3px;">
<apex:outputPanel rendered="{!lastOff}">
<img src="/s.gif" onclick="last();return false;" style="cursor:pointer; cursor:hand; background-image: url('/img/paginationArrows.gif'); background-position: -27px 1px;background-repeat: no-repeat;height: 10px;width: 9px;"/>
</apex:outputPanel>
<apex:outputPanel rendered="{!(!lastOff)}">
<img src="/s.gif" style="cursor:text; background-image: url('/img/paginationArrows.gif');background-position: -27px -10px;background-repeat: no-repeat;height: 10px;width: 9px; "/>
</apex:outputPanel>
</span>
</span>
<span style="margin: 0 -80px;">
<apex:outputLabel value="Page"/>
<apex:inputText id="pageNo" value="{!pageNumber}" style="width:20px; text-align:center" size="3" onkeydown="return runScript(event);"/>
<apex:outputLabel value="of {!totalPage}"/>
</span>
</div>
</apex:pageBlock>
<script>
function runScript(obj){
//alert(obj.keyCode);
if(obj.keyCode == 13){
callAction(); // call action function
return false;
}
else if((obj.keyCode > 34 && obj.keyCode < 40) || (obj.keyCode > 95 && obj.keyCode < 106) || (obj.keyCode > 47 && obj.keyCode < 58) || obj.keyCode == 8 || obj.keyCode == 46 ){
return true;
}else{
return false;
}
}
</script>
</apex:form>
</apex:page>