Update 29/4: Thank you Bert Oost of OostDesign for the tip on supporting different getPage configurations!
If you've ever created custom components, chances are that you have had to create accompanying snippets to actually show the data on the front-end. That can be a lot of work, and once data starts piling up you may want to add some pagination to it. This brief article will explain the requirements that getPage puts on your coding to properly paginate custom objects.
Getting the number of Results
First of all, we will need to tell getPage what the total number of results matching any filters set in place by our snippet is. In our snippet, we can easily set up the xPDOQuery object the way we normally would and take that object to get the total amount of results. No - we don't use getCollection and count() the array - that would be an insane waste of processing time. Instead we use the little jewel called modX::getCount, which is actually extended from xPDO::getCount. This will, without retrieving all the data from the database, get the total number of results for your query. Let's show an example of how we could use this - in this example we look up the amount of resources that have a class of modWeblink or modSymLink and are published:
So that will give us a number in the $total var - but that doesn't tell getPage anything - yet! Having looked at the getPage documentation trying to figure out this part, I've overlooked the answer many times and it is surprisingly simple. The documentation tells us there's a totalVar property:
And that's our answer. We need to set a placeholder, of which the key matches the value of the totalVar property: by default that's "total", though users have the ability to change this in their getPage call, so we'll need to get the totalVar property and set a placeholder with that name. Let's update our example accordingly to set the placeholder and that's all there is to it.
Starting at the right offset
Secondly we will need to make sure our snippet understand which results to display - and that it passes this on to our xPDOQuery object. In this case all we need to do is lookout for two properties: limit and offset. Limit will be set by getPage to the &limit property, which indicates how many items to show at once. The offset will be calculated based on the "page" request and the limit per page.
If we would update our example, we could end up having this - which works perfect with getPage for pagination.
You may notice a few important things:
- We get the total amount of results, and set the total placeholder *before* we limit the query. While the docs say it may ignore the limit property, I like to be sure.
- We use modX::getOption() (extended from xPDO::getOption) to get the "limit" and "offset" properties from our scriptProperties array available in snippets. If it does not exist we assign default values of 10 and 0 respectively.
- We use xPDOQuery::limit() to set the limit and offset to the query. We then pass that on to our getCollection call and be on our way to process it further and give the site visitor what they want.
Hopefully this brief article will help more developers making their snippets getPage-proof, which will make it easier for front-end developers to use one tool (getPage) for all their pagination needs. Please feel free to share your thoughts and suggestions below!
