Previous and Next Links in content
How do I create links to previous and next items?
When using a multiple item region, particularly with a list/detail display, it is sometimes useful to be able to link to the next or previous item in that region. This can be done with some simple filtering and ordering using
Here’s the scenario; we have a multiple item region set up using the list and detail approach. On the detail page, it would be great to be able to show links to the previous and next items in the list, with the user needing to navigate back to the list to find them.
To do this we need three
- The original call that finds the main item we’re looking at
- A call to find the previous item
- A call to find the next item
Modifying the main call
Taking the example from the list and detail solution, our
perch_content_custom() call used to show the detail view looks like this:
perch_content_custom('Products', array( 'template' => 'product_detail.html', 'filter' => 'slug', 'match' => 'eq', 'value' => perch_get('s'), 'count' => 1, ));
We need to make an important change to this in order to have the information we need to find the next and previous items. We need to use the
skip-template option to return the raw content, and then use the
return-html option to make sure we get the HTML back too.
The result looks like this:
$result = perch_content_custom('Products', array( 'template' => 'product_detail.html', 'filter' => 'slug', 'match' => 'eq', 'value' => perch_get('s'), 'count' => 1, 'skip-template' => true, 'return-html' => true, ));
Because of the
skip-template, this call won’t output anything to the page. We need to do that with a simple
This leaves us with the main detail item being output to the page just as before, but now we have the raw content fields also available to us in the variable
Creating the template
To show the previous and next items, we need a template. This can be anything from a simple link, to a mini preview of the content item. You have the full range of content available, including images and so on.
Save this as
product_prevnext.html in your templates folder.
<a href="?s=<perch:content id="slug" type="slug">"> <perch:if exists="is_prev">Previous<perch:else>Next</perch:if>: <perch:content id="image" type="image" width="100" height="100" crop output="tag"> <perch:content id="title" type="text"> </a>
Finding the Next item
To find the next item, the logic is simple:
- Sort the region
- Filter for just the items that come after our main item in the list
- Take the first one of those left
Remember we have our main item stored in the variable
$result, so we can make use of that here.
perch_content_custom('Products', array( 'template' => 'product_prevnext.html', 'filter' => '_order', 'match' => 'gt', 'value' => $result['_sortvalue'], 'sort' => '_order', 'sort-order' => 'ASC', 'count' => 1, ));
There’s a neat trick at play here. We’re filtering on a special value of
_order. This is the ‘natural’ order of the items within the region. According to this filter, the
_order needs to be greater than (
_sortvalue of the main item.
_sortvalue is the other part of the trick. This is the value that was used for sorting when the main item was found. So if it was found using the natural order (no sort value) then it would be its
_order. If you sorted by another field, say price, then
_sortvalue would be the price. This enables you to figure out a relational order between items no matter how they’re sorted.
We’re sorting by the regions natural order, and filtering where the position in that order is greater than the main item’s position. And then just taking the first result.
Finding the Previous item
The process for the previous item is just the same, but we reverse the filtering and ordering. We need to find the items whose order puts them before our main item in the list, and then just pick off the last one. We don’t have the tools to pick off the last one, so we reverse the order (
'sort-order'=>'DESC') and pick off the first.
We also need to set that
is_prev value that our template is using to display the correct labels.
PerchSystem::set_var('is_prev', true); perch_content_custom('Products', array( 'template' => 'product_prevnext.html', 'filter' => '_order', 'match' => 'lt', 'value' => $result['_sortvalue'], 'sort' => '_order', 'sort-order' => 'DESC', 'count' => 1, ));
That gives us our previous item.
Sorting by a particular field
If you want to sort the region by something other than its natural order, you just need to set the same
sort option on all three
perch_content_custom() calls, and update the
filter on the previous and next items to use that field too.