Tutorials - Big bits of code to help you do more
Creating Previous and Next Buttons on a page
Tweet28 June 2009 | | | Supports v2.4, v2.3
When you have a number of pages which follow on from one another you may find that asking a user to return to an index or select the next item from a side menu each time they want to progress is cumbersome. In this situation having previous and next buttons at the bottom of a page becomes very useful. In this snippet we'll add these buttons and also a counter to show the current page we are on and the total number of pages.
First add this function to your Page_Controller class:
public function PrevNextPage($Mode = 'next') {
if($Mode == 'next'){
$Where = "ParentID = ($this->ParentID) AND Sort > ($this->Sort)";
$Sort = "Sort ASC";
}
elseif($Mode == 'prev'){
$Where = "ParentID = ($this->ParentID) AND Sort < ($this->Sort)";
$Sort = "Sort DESC";
}
else{
return false;
}
return DataObject::get("SiteTree", $Where, $Sort, null, 1);
}
Let's go through the function. First we pass in a string $Mode. This will be used to decide whether to return the previous or next page.
Then if we have passed in 'next' (the default) we setup the database criteria for that page, which is having the same parent ID and a sort value that is higher than the current page. We also set the database sort to arrange the pages by their Sort value in Ascending order. Otherwise if $Mode is 'prev' then we setup the criteria to fetch the previous page. If $Mode was not equal to either 'next' or 'prev' then we just return false.
Finally we do the database call and grab a single page using the criteria we set in the first part of the function and return the result.
Now we can use this function in our template like so:
<% control PrevNextPage(prev) %> <a href="$Link" title="Go to $Title">< previous page</a> <% end_control %> <% control PrevNextPage(next) %> <a href="$Link" title="Go to $Title">next page > </a> <% end_control %>
By wrapping the links in <% control %> blocks instead of using $Variables, we prevent the link from being drawn if there is no page to go to.
Finally we can also add these functions to our Page_Controller to enable us to print the current page's number and the total number of pages:
public function NumberOfSiblings(){
return DataObject::get("SiteTree","ParentID = ($this->ParentID)")->Count();
}
public function CurrentPageNumber(){
return (DataObject::get("SiteTree","ParentID = ($this->ParentID) AND Sort <= ($this->Sort)")->Count());
}
And then in our template:
<p>Page $CurrentPage of $NoOfSiblings</p>
Thanks to Rick for suggesting this snippet!
7 Comments
RSS feed for comments on this page RSS feed for all comments
bazilio
14/10/2010 12:40pm (3 years ago)
cant post any code to comment, if fails (% or $)
Aram Balakjian
14/10/2010 1:02pm (3 years ago)
Hi Bazilio, it seems to work ok for me?
function test(){
$CommentTest = $this->MyComment()->Test;
%f = % 5;
}
Prawnstar
20/05/2011 8:11pm (2 years ago)
Hi, Aram,
I followed your tutorial here and have noted that when PrevNextPage() returns false (i.e., no more previous or next records) the link is still printed in the template.ss because it lacks an 'if' statement. Even though the function is returning false, the link gets printed. For me the link takes me to the home page.
Something like this solved my issue (could use an else statement):
<% if Link %>
<a href="$Link" title="Go to $Title">previous page</a>
<% end_if %>
R Estar
01/01/2012 1:49pm (1 year ago)
Thanks, I was really hoping to find something like this! Only problem for me is that, in applying Prawnstar's suggestion and adding in an <% else %> tag, I CANNOT use $Parent.Link. I have tried putting plain text after then 'else' tag, and that works fine (which is what I have right now). I also tried creating a link using $Parent.Link in a different spot on the page (so, not inside this <% control ... %>) and that works fine. But no matter what I try, I cannot create a Parent link inside the control!!! Please help... I have searched for a solution and I cannot find one.
R Estar
01/01/2012 1:54pm (1 year ago)
Sorry, let me edit that... As soon as I hit 'Post' I realized that I had not tried using $Parent.Link inside the <% if .... %> but before the <% else %> tag. Sure enough, it works inside the control as long as it's not after the 'else' tag. Of course, that still doesn't help me because I am still unable to do what I need to... So confused!
benshu
14/06/2012 8:06am (11 months ago)
Great article, was very usefull.
Just for those copy pasting, the last snippet:
<p>Page $CurrentPage of $NoOfSiblings</p>
should be:
<p>Page $CurrentPageNumber of $NumberOfSiblings</p>
Matty Balaam
09/02/2013 12:29pm (3 months ago)
I updated this to work with the new DataList in Silverstripe 3. Any improvements welcome:
public function PrevNextPage($Mode = 'next') {
if($Mode == 'next'){
$Direction = "Sort:GreaterThan";
$Sort = "Sort ASC";
}
elseif($Mode == 'prev'){
$Direction = "Sort:LessThan";
$Sort = "Sort DESC";
}
else{
return false;
}
$PrevNext = SiteTree::get()
->filter(array(
'ParentID' => $this->ParentID,
$Direction => $this->Sort
))
->sort($Sort)
->First()
;
if ($PrevNext) return $PrevNext;
}
Post a comment ...
You cannot post comments until you have logged in. Login Here.