Wayfinder is a great snippet for building a dynamic navigation for your site, but sometimes all you need is just a quick and simple way to navigate between sibling pages with Previous and Next links. There are quite a few posts in the forums on this subject, but the solutions offered aren't usually that clear. So I'll propose a new approach using the famous
getResources.
Kudos
99% of the ideas discussed in this tutoral aren't mine. So kudos to Jason Coward for his enlightening take on using
getResources to Build Menus. Big props to YJ Tso for expanding on Jason's initial discussion in a very eloquent and newbie-friendly way. You can find his post here:
How-to: Use #MODX getResources for Dynamic Nested Menus
Our tutorial will be based on a sample website built for a children's book that has one container and 12 children resources beneath it.
Here's the site structure:
Home/ # Home page // Not really needed in our tutorial
|
|-- Book/ # Container - Book's summary page. ID: 927 (Yours could be different).
| |-- chapter-1.html # Pagetitle: My Awesome Book. Template: Book_chapters (44)
| |-- chapter-2.html # Pagetitle: My Awesome Book. Template: Book_chapters (44)
| |-- chapter-3.html # Idem
| |-- chapter-4.html # etc.
| |-- chapter-5.html
| ...
| |-- chapter-12.html
The idea is to be able to jump from one chapter page to another using the previous/next links (usually placed just after the content).
Sot let's get started!
THE SETUP
1) Create a new property set for our custom navigation links
Open getResources from the Elements tab
Under the properties tab, click on "Add Property Set"
In the window that pops up, check the "Create new property set" option.
Give your property set a name. I named mine "FooterNav". Click save.
This should load your newly created property set. You can now modify the values by right-clicking the property.
We'll later reference our property set name in our getResources call like this:
[[getResources@FooterNav? &property=`value`]]
.
Go ahead and add/modify the following values: For more details on why we're using these properties, please refer to YJ Tso's in depth coverage here:
How-to: Use #MODX getResources for Dynamic Nested Menus depth=`0`
level=`1`
maxLevel=`2`
sortby=`menuindex`
sortdir=`ASC`
tpl=`myRowTpl`// Used for the next link
tplFirst=`myFirstRowTpl` // Used for the previous link
tplWrapper=`myWrapperTpl`
showHidden=`Yes` // My resources are hidden from the tree. Yours may not be, so this is optional.
Don't forget to save your property set.
2) Create the chapter number TV
I've created a text TV that I've named "Chapter" to store chapter numbers and I've assigned it to my Book_chapters template. You'll see why in a moment.
3) Create your tpl chunks
myRowTpl => This chunk will be used as our next link template.
//Styled with Bootstrap V.3.1.1
<div class="btn-group pull-right">
<a href="[[~[[+id]]]]" class="btn btn-default" title="[[+pagetitle]] Chapter [[+tv.Chapter]]" rel="next">[[+pagetitle]] Chapter [[+tv.Chapter]] →</a>
[[[[+level:lt=`[[+maxLevel]]`:then=`getResources@FooterNav? &parents=`[[+id]]` &level=`[[+level:add]]``:else=`-`]]]]
</div>
myFirstRowTpl => This chunk will be used as our previous link template.
//Styled with Bootstrap V.3.1.1
<div class="btn-group pull-left">
<a href="[[~[[+id]]]]" class="btn btn-default bbl-toolbar-btn" title="[[+pagetitle]] Chapter [[+tv.Chapter]]" rel="prev">← [[+pagetitle]] Chapter [[+tv.Chapter]]</a>
[[[[+level:lt=`[[+maxLevel]]`:then=`getResources@FooterNav? &parents=`[[+id]]` &level=`[[+level:add]]``:else=`-`]]]]
</div>
myWrapperTpl => This chunk will be used to wrap our links. [[+output]] will be replaced with the processed content of our previous/next links chunks.
//You can add some HTML if you like.
[[+output]]
THE MAGIC PART
4) Create the (crappy and lazy) snippet that will help determine the previous link
I named mine getPreviousChap
/**
* getPreviousChap
*
* DESCRIPTION
*
* Helper Snippet that subtracts &y from the supplied number &x
*
* PROPERTIES:
*
* &x integer required. Default: 1
*
* USAGE:
*
* [[!getPreviousChap? &x=`10` &y=`1`]]
*
*/
$x = (int) $modx->getOption('x', $scriptProperties, 1);
$y = (int) $modx->getOption('y', $scriptProperties);
return $x - $y;
5) Finally, the getResources calls
<!-- Footer nav-->
//Styled with Bootstrap V.3.1.1
<div class="panel panel-default">
<div class="panel-body">
<!-- Previous link -->
[[*Chapter:gt=`1`:then=`[[getResources@FooterNav? &parents=`927` &limit=`1` &includeTVs=`1` &processTVs=`1` &offset=`[[getPreviousChap? &x=`[[*Chapter]]` &y=`2`]]` &where=`{"template:=":44, "pagetitle:=":"[[*pagetitle]]"}`]]`]]
<!--/. Previous link -->
<!-- Next link -->
[[getResources@FooterNav? &parents=`927` &limit=`1` &includeTVs=`1` &processTVs=`1` &offset=`[[*Chapter]]` &where=`{"template:=":44, "pagetitle:=":"[[*pagetitle]]"}`]]
<!--/. Next link -->
</div>
</div>
<!--/. Footer nav-->
And voilà!
LET'S EXPLAIN
Basically the links are generated by two getResources calls. The first one takes care of our previous navigation, while the second brings us forward. The trick is to use the &offset property to determine your previous and next links.
[[*Chapter:gt=`1`:then=`... => Do not display the previous link on Page one.
getResources@FooterNav => We're referecing the custom property set we created earlier.
&tpl, &tplFirst => The &tpl/&tplFirst properties arent' included in the call, because we've already defined them in our @FooterNav property set.
&limit=`1` => We're limiting our output to 1 to ensure that only one link is displayed
&where=`{"template:=":44, "pagetitle:=":"[[*pagetitle]]"}` => Only grab resources whose template ID is 44 and page title is equal to the current. Our sample book website happens to be be using the same pagetitle for all its chapter pages. Aliases and [[*Chapter]] are specific to the resources. You can use a TV instead of repeating page titles to identify the resources you want to browse. You would then use &tvFilters=%myTVName% in your call. This is not crucial though.
The magic trick
&offset=`[[getPreviousChap? &x=`[[*Chapter]]` &y=`2`]]` => We're subtracting 2 => (&y=`2`) from the active resource's Chapter TV value. This gives us the offset number we need to display the previous link's URL. For example: if the getResources call retrieves 12 results (although only 1 is visible per the &limit property) and the current resource's Chapter TV has a value of 11, by setting the offset property to 9 (as discussed above), we're basically telling getResources to display the 10th result by skipping the first 9 results. And this happens to be our "previous link", relative to the one being browsed.
I hope I haven't lost you yet.
&offset=`[[*Chapter]]` => Getting the next resource's URL is much easier - we simply use the active resource's Chapter TV. To use our previous example: if the current resource's Chapter TV has a value of 11 and we set the &offset property to 11, we're telling getResources to display the 12th result by skipping the first 11 results. And that's how we get our "next link", relative to the resource being browsed.
Conclusion
The example used in the tutorial was very specific to a project I'm working on, but hopefully you get point. The magic trick is the &offset property.
I'm definitely not an expert MODXer and I suspect, there's a much better approach. Please feel free to suggest better ways or correct this one wherever appropriate.
Cheers!
[ed. note: treigh last edited this post 12 years, 6 months ago.]