In this tutorial, I’ll be showing you how to add a simple pagination to your AngularJS WordPress theme. We’ll create a custom directive with AngularJS which works like the WordPress built-in function posts_nav_link()
, that will display previous and next posts links in your index and category pages.
Before we get started, let’s take a look at the posts_nav_link()
function first. By its description from the WordPress Codex, posts_nav_link()
‘displays links for next and previous pages. Useful for providing “paged” navigation of index, category and archive pages.’ So after we add our custom directive “postsNavLink
” to our AngularJS app, we expect to see a paged navigation in our index and category pages:
You might notice that posts_nav_link()
takes three parameters:
$sep
: Text displayed between the links.$prelabel
: Link text for the previous page.$nxtlabel
: Link text for the next page.
Since we’re inspired by posts_nav_link()
to build postsNavLink
directive, we’d like to take the same parameters as attributes. We can use our custom directive as simple as:
<posts-nav-link></posts-nav-link>
Or we can pass values into the attributes to make some changes:
<posts-nav-link sep="//" prev-label="« Previous Page" next-label="Next Page »"></posts-nav-link>
Looks cool, right? If you’re ready, let’s dive into the code!
O. Getting Started
Please get the theme files from the GitHub repo. It would be easier to follow the steps in this tutorial with this ready made theme. After downloading the theme, you must change the “base href
” at line 4 in index.php.
For example, if you host your site at the root of the domain, you’ll need to change it to “/”; if you host your site in the “jsonapi” directory of the domain, which your website URL will be like “http://localhost/jsonapi”, you’ll need to set the base href
to “/jsonapi/”.
And don’t forget to install and activate the WP REST API plugin.
To make the demonstration simple, I’ll set the blog to show only one post per page at the WordPress Administration “Reading Settings” Screen.
1. Setting up the routes
First step we’ll do is to set up the routes to our “paged” pages. At line 20 – 27, we add two new routes for the paged category and index page. As you can see, we set the route paths consist with the default WordPress URL structure. For example, the URL of page 2 for index page would be [site-url]/page/2/
, and the URL of page 3 for uncategorized posts would be [site-url]/category/uncategorized/page/3/
.
If you haven’t do so (I’ve mentioned the permalink settings in my previous tutorial), you need to set the permalink structure in WordPress as the following screenshot to get the best SEO performance. That when search engines crawl your website, they won’t run into a bunch of 404 pages or pages without correct content.
2. Updating the Main controller
When we’re trying to add paged navigation to our AngularJS app, the most importance thing is to know what are the values of “current page” and “total pages“. Luckily WP REST API has passed them to us in headers.
We’ll need to add the headers
parameter to our function (at line 9) to access it. At line 14 and 15, we also add two new properties: currentPage
and totalPages
to the $scope
object. We set currentPage
to 1
because we’re at homepage, and we get totalPages
from headers
which is a function passed by WP REST API, so we get the value with syntax like headers("X-WP-TotalPages")
.
We’ll use the values from these two properties to help our postsNavLink
directive to show or hide the pagination links.
3. Creating the postsNavLink
directive to display the previous / next posts links
If you’re not so familiar with custom directives in AngularJS, I’ve written a tutorial for you: Using AngularJS Custom Directive In A WordPress Theme. I’d like to analogize the custom directives in AngularJS to the template tags in WordPress, that we wrap some reusable code snippets into a function, and call it from our theme when we need it.
In this case, we need a function to display the previous / next posts links in our AngularJS app. Basically it would be exactly like an AngularJS version of posts_nav_link()
. Let’s see how to create the postsNavLink
directive:
- Line 7: we’ll create a new template file for this custom directive. I named it
posts-nav-link.html
but you can choose any file name you like. - Line 9: we’ll get the current page number from the route parameter “
page
“. - Line 10: the linkPrefix can help us to set the different route paths for index and category page.
- Line 12-18: we create a new property for
$scope
object calledpostsNavLink
, which is an object to contain all information our custom directive will use.
Let’s take a look at the controller in our postsNavLink
directive, we just pass a new parameter $element
into it. The $element
object represents the directive itself, and it’s a jqLite element. Since jqLite is a lite version of jQuery, we can manipulate it with some of the jQuery methods.
For example, we use $element.attr('sep')
to get the value of the sep
attribute in the postsNavLink
directive.
4. Creating the pagination template posts-nav-link.html
Let’s create a new file posts-nav-link.html
in the partials
directory. In the template file we add all required HTML there with some AngularJS attributes and markups:
- Line 2: We get the
preLink
andprevLabel
frompostsNavLink
object. And we useng-if
with the condition that only show the previous link whencurrentPage>1
. - Line 3: The
sep
text between two links should be displayed whencurrentPage>1 && currentPage<totalPages
. - Line 4: We get the
nextLink
andnextLabel
frompostsNavLink
object. And we useng-if
with the condition that only show the next link whencurrentPage<totalPages
.
5. Creating the Paged controller
When we set the new route for paged index page, we added a new “Paged
” controller. Now let’s create it.
Basically the Paged
controller is pretty much like the Main
controller, we just make some modification:
- Line 4: We add
$routeParams
to the controller function, that for us to get thepage
parameter from the route. - Line 9: We query paged posts with endpoint like
[site-url]/wp-json/posts?page=3
. - Line 10-12: Set
currentPage
andtotalPages
properties. Please note we useparseInt
to convert$routeParam.page
to be an integer, or it would be a string and can’t be used to compare with integers. - Line 15-16: Update the page and document title.
6. Updating the Category controller
Let’s take a look at the Category
controller. The Category controller looks a bit messy at this time, and so do other controllers. I’ll write another tutorials about how to use AngularJS service
to tidy up our code later.
For now let’s just focus on line 15 – 24, where we add pagination to category pages by changing the endpoint to query posts with category_name
and page
. And we also add currentPage
and totalPages
to $scope
object. These are important properties we’ll use in our directive, so we must make sure they’ve been attached to the $scope
.
7. Updating the searchForm directive
After the steps above, we’ve almost got everything done. But there might be a feature we have broken – the search function.
Because we add pagination to the index and category pages, the search results will be paginated either. For technically the search results page is also one of the archive pages in WordPress. But when I built the searchForm
directive in previous tutorial, I made it very simple to only demonstrate the search function, and I didn’t make it a standalone page so it didn’t get its own route.
Here I still want to keep it simple so the quick and dirty method is to add “posts_per_page
” to filter and set it to “-1
“. I also set the currentPage
and totalPages
to “1
” because I don’t want to paginate the search results. (at line 13 – 18)
8. Add the postsNavLink
directive to main.html
Now it’s the final step! Just add the postsNavLink
directive to the bottom of the main.html
. Remember you can set three attributes value: sep
, prev-label
and next-label
. (I set prev-label
and next-label
in the following example.)
After these steps we finally add pagination links to index and category pages in our AngularJS WordPress theme. Here’s the screencast to show how it works in category pages:
You can get the final theme files from the project repo on GitHub. I hope you enjoy this tutorial as much as I do. If you have any problem when following the instructions, just send me an email. I’d love to get back to you as soon as I can. Talk to you soon!
Leave a Reply