Tidy Up Your AngularJS WordPress Theme With A Service

In the previous post, I spent some time to walk you through the basics about services in AngularJS, including what is a service, how to create a factory service, and what exactly can be improved with the new WPService created by us.

So basically it’s mainly about how to share data between controllers with a service (which looks so magical especially when we change the routes). If you’re convinced by the example I just demoed, I’m glad to show you another important usage about services, which we’ve mentioned that they are designed to organize and share code across the AngularJS app. That’s why I’m saying we can tidy up our AngularJS WordPress theme with a service.

Let’s start by taking a look at the controllers in scripts.js – the Main and Paged controller, to see if there’s anything can be rewritten to be reusable, and move the reusable code into our WPService service.

0. Getting Started

Everything you’ll need for this tutorial can be found at the GitHub repository, just download the theme and install it as a regular WordPress theme. It should work on any WordPress install with the WP REST API plugin activated. You can have a preview to see what we’ve accomplished so far at this page.

1. What do these two controllers share in common?

Here’s a code snippet that contains the Main and Paged controller:

Have a close look. Here are things they share in common:

  1. They get all categories from WP API which we’ve optimized in the previous tutorial.
  2. They get posts from WP API.
  3. They change the document title.
  4. They attached some new properties to the $scope based on the feedback from WP API. Those properties are: currentPage, totalPages, posts and pageTitle.

The anatomy helped us to figure out what can be rewritten as reusable code and should be moved to the WPService. Let’s keep going step by step.

2. Adding the shared properties to the WPService

It’s very clear that these four properties can be reusable: currentPage, totalPages, posts and pageTitle, we should add them to the WPService object in our WPService function. And it’s a good practice we give them default values (at line 5-8).

3. Creating a getPosts function in WPService

In the Main and Paged controller, we both query posts from WP API. So the getPosts function is a must-have property for our WPService service / object. Let’s create it by borrowing partial code from Main controller:

  1. From the gist above, please note at line 3 I add a parameter for this function: page, which will be used to pass the page route parameter later.
  2. At line 4 I add the page parameter to the posts endpoint.
  3. At line 9, we set the currentPage to page, though at homepage, it should always be 1.
  4. The other things to note is that I changed all $scope to WPService, so we could share these values between controllers.

4. Updating the Main controller

Now we should use WPService.getPosts to get posts in the Main controller:

  1. Line 4, we remove the $http service from the dependencies.
  2. At line 6, I used WPService.getPosts(1) to get all posts on the first page.

5. Updating the templates

Because we move several properties from $scope to WPService, we should update our templates to change how they access these properties.

In main.html, at line 3-5 I changed pageTitle to data.pageTitle, and posts to data.posts that we need to access properties in the WPService through data.

The other template file we need to update is posts-nav-link.html. At line 2-4, we changed currentPage to data.currentPage, and totalPages to data.totalPages.

Now the homepage should work as usual. Let’s see what we can do next.

6. Creating a private function in WPService to update titles

In this tutorial I want to show you how to tidy up our JavaScript with Angular services, in the mean time, we should also pay attention that not to mess up code in the WPService. It would be meaningless if we clean up one file but move everything messy to another. (You’re allowed to do so if you’re cleaning up your living room.)

So let’s keep digging what can be improved in the WPService.getPosts function. Yep, that’s it, these two lines looked specious to me:

WPService.pageTitle = 'Latest Posts:';
document.querySelector('title').innerHTML = 'Home | AngularJS Demo Theme';

The gist below is what I’ll do with them:

  1. Line 11-14: I create a function _updateTitle that takes two parameters: documentTitle and pageTitle, so I can change these two titles. Please note the naming convention that start a function name with an underscore (_), which is used to remind us such function is a private function that we can’t access it when we’re not in the WPService function. That said, we can’t use something like WPService._updateTitle in our controllers.
  2. Line 20: replace these two lines with the _updateTitle function.

7. Updating the WPService.getPosts to work with the Paged controller

The major difference between Main and Paged controller is that, we add an if/else statement for the page might not exist and we can’t get any post from WP API. Let’s update our getPosts function to include the if/else statement:

The upgraded getPosts function is much descriptive by itself. And we can happily change our Paged controller to:

8. Create a getSearchResults function in WPService for our searchForm directive

After seeing how powerful an AngularJS service can be, you must be wondering: can I use it for my custom directive? Of course you can! We can just create another function in WPService to get search results and use it in our searchForm directive (that we created a while back ago).

9. Creating a _setArchivePage function in WPService

Again, we want not only the scripts.js is tidy, but the WPService.js should be tidy too. I felt kind of nasty that every time we get posts from WP API, we need to write these three lines again:

WPService.posts = res;
WPService.currentPage = page;
WPService.totalPages = headers('X-WP-TotalPages');

My solution is kicking them into another private function – I’d like to call it _setArchivePage:

At line 5-9 our new _setArchivePage function lies there, at line 26 and 35, we change the way we update these three properties of WPService.

10. Fix the broken Category controller

After the steps above you found the Category controller is now broken. Stay calm, we’re going to fix it right away.

To be honest the Category controller itself is a pretty messy one. We need to fetch the category then fetch the posts in it, and we also have to take the page parameter for pagination.

I tried my best to keep it simple, so I created a getPostsInCategory function and it takes two parameter: category (the category object) and page (the page $routeParam).

The Category controller got updated as below. Try to click on the category links now, they should work again.


It’s still not perfect but now our code gets much more organized and sharable. You can download the finished code from the GitHub repository. Let me know your thoughts about this tutorial, I try to make it simple (and even stupid) but it’s not that easy (maybe I still mixed too much stuff together).

Anyway, I value your feedback very much and I’ll always get back to each comment, email and Twitter message as soon as I can. Just get in touch!

I’m a senior web developer helping clients build their websites to grow businesses. Currently I’m based in Taipei, Taiwan.

I write things about WordPress, AngularJS and life. Whenever you’d like to find someone to talk about these topics, just get in touch!

Submit a comment

Your email address will not be published. Required fields are marked *