Building a WordPress-Powered Front End: Posts, Categories, and Users Controllers

In the previous part of the series, we built a custom directive for listing posts on the front end. This directive takes arguments directly in the HTML attribute as well as in the URL to fetch posts from the server. Building the directive has allowed us to show the post listing feature anywhere in our application by reusing the business logic and the rendering logic provided by the directive.

In this concluding part of the series, we will work on the remaining portion of our application and build controllers for post listing, single post, author, and the category page. We will also work on the templates of these controllers and display on them the data provided by the controllers.

To be specific, in the current part of the series, we will:

  • introduce ourselves to AngularJS controllers
  • build controllers for posts, categories, and users
  • link templates to the data provided by the controller

So let’s start by introducing ourselves to AngularJS controllers.

Introducing AngularJS Controllers

Controllers in AngularJS are one of the main building blocks of the application. They contain business logic that decides what data to display to the user. They drive much of the UI-related functionality of the application and also provide support for user interaction.

Controllers are tightly linked to DOM and they glue the model of the application—where the data resides—to the application view.

In our case, in which we are building the application powered by the WP REST API, the controllers are where we show the data retrieved through the API and different services to the end user.

Building a Controller for the Post Listing View

Controllers in AngularJS are defined in the module, and we will use the same notation of the safe style of dependency injection as we did for declaring the custom directive. Consider the following code, in which we are declaring a controller for the post listing page:

Controllers are defined in a module using the .controller() method that’s available in the module. The name of the controller we defined above is PostListing.

Any data that we need to expose to the outside world should be set on the this keyword inside the controller constructor function. Hence we cache the this keyword by creating a self variable.

The controller for post listing is the simplest of all the controllers that we will make, in the sense that it doesn’t need to have any data. It just needs to have a template linked, and we will place the <post-listing></post-listing> directive in that template to begin listing posts. The directive will fetch posts on its own using the Posts service and list them using its own rendering logic.

So as the first step, we will link the views/listing.html template to the PostListing controller, and we do so in the .config() section of our application. The .config() section is where we configured the routes for the application, and we need to modify the /wp/v2/posts route to the following:

In the above code, we placed two additional properties in the route definition, and these properties are:

  1. controller: The name of the controller we need to link to this route and its template.
  2. controllerAs: The keyword by which we refer to the controller in our template.

Hence we passed PostListing as the controller name, and we will be referring to it in the template using the postListing keyword.

Having linked the controller with the route and the template, we now need to modify the template to properly list posts. So open the views/listing.html template file and replace its contents with the following code:

Below is a screenshot of the completed template:

Post listing view

And that’s it! The above line of code exhibits the power of AngularJS directives. With just one line of code, we have been able to mimic the functionality for post listing that includes business logic as well as rendering logic. And we will further see how flexible this AngularJS directive can be when building controllers for the category and user listing views in the following sections.

Building a Controller for the Category View

Having familiarized ourselves with controller declaration syntax and having built a very simple controller for post listing, we are ready to begin working on a more advanced controller for the categories view.

The categories view controller we are building will use the $routeParam service to access the category ID in the URL, and using that ID, the controller will use the Categories service to fetch category information and a list of its associated posts. However, the controller will not directly fetch the posts using the Posts service, but rather it will use the postListing directive and pass it the category ID to retrieve a list of posts associated with that category.

Below is the code for the CategoryListing controller:

The CategoryListing controller above has two dependencies for the $routeParams service and the Categories custom service. Using the $routeParams service, it retrieves the ID of the category from the URL, and then it queries using that ID for the category information through the Categories service.

The controller has a variable defined on the $scope object named categoryInfo. This variable holds the category object returned by the server, and its value is set after the query has been successful.

The next thing we need to do is to link a template to this controller that will display the data to the user. And we do this in the .config section of the application, just as we did for the PostListing controller in the previous section.

So modify the /categories/:id route to contain the following code:

In the above code, we link the route to the CategoryListing controller and also define the categoryListing keyword through which we refer to it in the template.

It’s now time to modify the views/category.html template so that it displays data dynamically instead of showing static HTML code.

In the code above, we replaced the hard-coded category name with {{categoryListing.categoryInfo.name}}, where categoryListing is an instance of the CategoryListing controller. The categoryInfo variable holds the category object returned by the server, and this object contains the name property for the name of the category.

For the post listing feature, we use the postListing directive and pass it the category ID through the post-args attribute. For this purpose, we use the filter[] syntax supported by the /wp/v2/posts route of the WP REST API. We are already familiar with the filter[] syntax from the fourth part of the introductory series about the WP REST API.

Below is a screenshot of the completed category view:

Category view

Let’s now work out the controller for users, which is very similar to the categories controller.

Building a Controller for the User View

The controller for the user view is very similar to that of categories. We will begin by modifying the routing configuration to link the controller with the template:

Here we link the UserListing controller with the route and its template. The keyword by which we refer to the controller instance is userListing.

Following is the code for the UserListing controller:

The UserListing controller takes $routeParams and Users services as dependencies. Using the $routeParams service, it accesses the user ID in the URL. The Users service is then used to fetch the user object using the user ID. The userInfo variable holds the user object returned by the server.

Let’s now modify the views/author.html template to render this data to the user. Replace all of the contents of the author.html file with the following:

In the above code, we access the userInfo variable defined on the controller’s scope that contains the user information object. Using various properties of this user object, we replace the hard-coded username, user gravatar, and user description.

For listing the posts authored by the user, we use the postListing directive and pass it the user ID as the value of the author parameter. The directive then fetches posts using the Posts service.

Here is what the completed view should look like:

User view

The fourth and final controller that needs to be worked on now is for the single post listing view, and we do that in the following section.

Building a Controller for the Single Post View

The view for the single post is slightly different than the others as it won’t use the postListing directive because the directive uses a template that’s more suitable for the post listing page. Additionally, we will be adding support to show comments for a single post in the future, so we need to have a separate template for a single post instead of using the same template as for post listing.

Due to the above reasons, we will use the Posts service manually in the controller for a single post to retrieve the post based on its slug.

Let’s first do a quick modification in the single post route to link the controller and the template:

So the name of the controller for a single post will be SinglePost. We will use the singlePost keyword to refer to it in its template.

Below is the code for the controller declaration:

In the above code, we first retrieve the post slug using the $routeParams service and save it in the self.postSlug property on the controller’s scope. Then we query the database using the Posts service by providing the post slug as a query argument. The data returned is an array containing a single object, and we set the self.post property on the scope using this returned data. Simple!

Now for the template, below are the contents of the views/single.html file:

The above code is pretty simple as we bind various properties of the post object to different elements, just as we have been doing in the last few sections.

Below is a screenshot of the completed single post view:

Single post view

The application is now complete (not quite yet!) and provides views for the post listing, single post, user, and category pages.

Conclusion

Here we conclude our four-part series, in which we built a front-end powered by the WP REST API and AngularJS. We started out by analyzing the requirements and reviewing wireframes. Then we built a companion plugin that provides some additional fields in standard responses that will be needed in our front-end. 

In the following parts, we bootstrapped our AngularJS application, dissected templates for different views, and configured application routing. We also built a custom AngularJS directive for the post listing feature that abstracts away the functionality for listing posts and provides a flexible way for us to retrieve a set of posts for different requirements.

In the final part of the series, we built controllers for post listing, single post, category, and user views and linked them with their respective templates through the .config() section of our application.

The application is not complete and can be improved in many ways. Some ideas are listed below:

  • comments thread on the single post view
  • No Posts by Author message when there is no post by the user on the author profile page
  • numbered pagination on post listing pages
  • better SEO with AngularJS Single Page Applications

We will try to build on these features in future tutorials. But for now, I’m leaving it up to you to play around with the application and extend it with some awesome features. Be sure to provide an online demo for the application in the comments as I’m eager to learn from my readers.

Tags:

Comments

Related Articles