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:
- They get all categories from WP API which we’ve optimized in the previous tutorial.
- They get posts from WP API.
- They change the document title.
- They attached some new properties to the
$scope
based on the feedback from WP API. Those properties are:currentPage
,totalPages
,posts
andpageTitle.
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:
- From the gist above, please note at line 3 I add a parameter for this function:
page
, which will be used to pass thepage
route parameter later. - At line 4 I add the
page
parameter to the posts endpoint. - At line 9, we set the
currentPage
topage
, though at homepage, it should always be 1. - The other things to note is that I changed all
$scope
toWPService
, 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:
- Line 4, we remove the
$http
service from the dependencies. - 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:
- Line 11-14: I create a function
_updateTitle
that takes two parameters:documentTitle
andpageTitle
, 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 theWPService
function. That said, we can’t use something likeWPService._updateTitle
in our controllers. - 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!
Leave a Reply