Building a WordPress-Powered Front End: Bootstrapping, Routing, and Services

In the previous part of this series about building a WordPress-powered front end with the WP REST API and AngularJS, we analyzed project requirements, assessed wireframes, downloaded and compiled the HTML package, and built the companion plugin for WordPress that modifies responses for the Posts and Users resources.

Having laid a solid foundation for our project, we are now ready to begin working on the front end and set up basic configurations for our application with AngularJS.

In the current part of the series, we will:

  • bootstrap the AngularJS app
  • dissect templates for different views in the HTML package
  • configure routing for our app
  • configure services for different resources in the WP REST API

Let’s begin by initializing the AngularJS app and dissecting templates for views including post listing, single post, and categories.

Bootstrapping the AngularJS App

The first thing we need to do in order to build our WP REST API powered application is to bootstrap it with the ng-app AngularJS directive. The ng-app directive is used to auto-bootstrap the application, and it takes the name of the AngularJS module as an optional value.

But before you begin modifying any files, be sure that you have run the gulp command by navigating into the quiescent-rest-api-html directory. This will ensure that any changes you make in the /src directory are immediately compiled into the /dist directory by the gulp watch command. And besides that, I would also encourage you to navigate into the /dist directory in another console window and run the http-server command that will run the Node.js HTTP server for that directory, and you could preview your site in the browser by just typing a web address as simple as 127.0.0.1:8080.

The ng-app directive is usually placed in the root element, i.e. the <html> tag. Hence, we will modify the <html> tag in the src/index.html file to the following:

Here, quiescentApp is the name of our main AngularJS module that we will initialize next in our src/js/app.js file.

The src/js/app.js file currently contains only one line of code for initializing the JavaScript functionality provided by Zurb Foundation. We can modify this file to include the following code for the main module of our AngularJS application:

The first thing in the above code is the self-invoking anonymous function that is represented by the following:

As the name suggests, the above function is anonymous, i.e. it has no name and it invokes itself immediately executing all the code that’s inside its body. It’s a good way to limit the scope of our variables and functions so they are not accessible globally for any manipulation.

Inside the anonymous function, we initialize our AngularJS module using the angular.module() method. The angular.module() function takes the name of the module as the first argument and an array of dependencies as the second argument.

The dependencies we passed in the second argument as an array are ngRoute, ngSanitize, and ngResource. Here is what each of them does:

  • ngRoute: This module provides routing and deep-linking services for our application. It’s found in the angular-route.js file in the AngularJS package as downloaded from the official site.
  • ngResource: This module provides supports for interacting with RESTful services. Since we are planning to use the WP REST API, this will be the single most important module in our application as we will use this module to interact with resources including posts, categories, and users.
  • ngSanitize: This module provides functionality for sanitizing the HTML. We will need this module when outputting HTML on the page. Examples include the post title, post content, and excerpt.

Please note that, before injecting these modules as dependencies in our main module, their respective files must be included into the HTML document. But you don’t need to worry about that as we have already that configured in our gulp.js file.

After putting the above code in your app.js file, head over to the address provided by the Node.js HTTP server. Also open the developer tools in your browser, and if you see no JavaScript errors, we are good to go!

Now that we have successfully initialized our AngularJS application, we can work on the templating part and dissect templates for different views.

Dissecting Templates for Different Views

Since we are building a Single Page Application (SPA), we need to configure templates for different views that load dynamically into the page when someone clicks on a link.

Currently, we have multiple pages in our HTML, including those of post listing, single post, author, and category. The HTML has been structured such that the header, footer, and the main container is the same for all of these pages. The main container in our case is div.columns.medium-8 inside the div.main.row tag. AngularJS allows us to configure different templates for different routes in the application. But before we configure routing, we need to dissect these templates from the existing HTML files.

So instead of using four different pages for the index page, single post, author, and category, we can use one main HTML page and let it load templates for different views depending on the current route.

Let’s start by dissecting the template for the post listing view. Open up the /src/index.html file in the code editor of your choice and cut all the code that’s inside the div.columns.medium-8 container. Create a new file called listing.html inside the /src/views directory and paste the code into that file.

This template will serve as a view for our listing page. We can repeat the procedure for each of the post-single.html, author.html, and category.html files. Open each of these files in your code editor and cut the contents of the div.columns.medium-8 container and paste them in new files created inside the /src/views directory. The names of the template files would be single.html, author.html, and category.html respectively.

Create a new file in the /src/views directory for the 404 page and name it 404.html. It doesn’t have to contain anything special but just the following line of code:

We can now safely remove the /src/post-single.html, /src/author.html, and /src/category.html files. We will preserve the /src/index.html file, which will serve as the main entry point for our application.

The last thing we need to do now is to tell AngularJS the place where to load these templates. And we can do this by adding the ng-view directive in the div.columns.medium-8 container inside the /src/index.html file:

The ng-view directive tells AngularJS where to load the contents of the template files.

We can also add the auto-scroll="true" attribute on the div.columns.medium-8 container so that when we navigate back and forth between views, the browser will take us to the point from which we left.

Go back to your browser and refresh it, and you should see a page containing only the header and the footer. This is because we haven’t configured routing yet. And that’s what we do next.

Configuring Routing for Our Application

Having created templates for different views in our application, it’s time to tell AngularJS how and when to load these templates. For this purpose, AngularJS provides a provider component called $routeProvider. The $routeProvider provides us a method called .when() that can be used to configure routes along with their templates and some other properties.

Consider the following code:

Here we are configuring our application using the .config() method by injecting $routeProvider into it. The function takes an argument—$route—for the $routeProvider, and then we use it for configuring different routes.

The .when() method configures a new route, and it takes two parameters for the $path and the $route respectively. The $path argument is a string representing the path for which we are configuring the route. The $route argument is an object containing information like the template URL to be used, the controller, the controller identifier, etc.

In the code above, we have configured four routes for post listing, single post, author, and category views respectively. We have just assigned them their respective template URLs, and we will configure their controllers later in this series when we build them. So we will be progressively building upon this code from this point.

In the above code, note the named groups followed by a colon : for the single post, author, and category routes. These are stored in the $routeParams service and will be made available to any directive or controller that wants to use them. We will look at that in more detail, but for now, just think of them as places where a post slug, a user ID or a category ID, as provided by the user in the URL, can be accessed.

Apart from the four routes, we have configured the 404 template by using the .otherwise() method. This method tells AngularJS to redirect the user to a particular template if none of the configured routes were matched.

You can find more about the AngularJS routing service and its different methods and arguments in the official documentation.

Now you can open any of the following four URLs in your browser, and should see the proper template being loaded:

The address http://127.0.0.1:8080 may be different in your case. The ID/slug we are providing here (in this case 10) doesn’t matter at this point.

The last thing we need to do now is to create services for resources like posts, users, and categories.

Creating RESTful Services for Resources

AngularJS provides us with the ngResource module, which lets us build RESTful service around a given endpoint for a resource. But before we delve into writing any code for creating services, let’s create some configuration variables that store some basic information.

The server path may be different in your case, and I recommend that you change it accordingly. Declaring these variables allows us to configure the server path only in one place instead of writing it separately for each service. The above code should be placed inside the anonymous function, and I’ve placed it immediately after my quiescentApp module declaration.

Creating a service around an endpoint in AngularJS is as simple as the following code:

The above code creates a service around the Posts resource in WP REST API. Here, quiescentApp is the name of our main module that we defined at the very beginning.

The .factory() method takes the name as the first argument, and the second argument is an array containing a list of dependencies and a function. The function accepts the arguments passed as dependencies. Since we provided $resource as a dependency for our service, it is passed to the function as an argument, and then we use it to create a service for the Posts resource.

We have already declared a variable for the API path, so we can replace the path with the following:

Now that we have created a service for the Posts resource, we can inject this service as a dependency in our directives and controllers and start using its methods like Posts.query(), Posts.get(), etc. We will learn more about these methods and what they do in the following parts of the series, but if you are curious, you can always check the official documentation.

For creating a service for the Posts resource, we have provided the /wp/v2/posts route. This route points to the collection of the posts and can also be used for creating a single post. But in our application, we also need to retrieve a single post based on its slug. To account for this feature, we can modify the code to the following:

This is called a parameterized URL template, and the parameters are suffixed using colon :.

This modification allows us to retrieve a collection of posts using the /wp/v2/posts route, as well as retrieving a single post by its slug using the /posts?slug=<slug> argument.

Apart from posts, we will be retrieving categories and users by their IDs. So the following code creates services for the Users and Categories resources:

Hence, the code for all three services is the following:

And our /src/js/app.js file looks something like the following so far:

The .get() method on a RESTful service returns a single object by using the GET HTTP method. The .query() method uses the same GET HTTP method, but it returns an array. There are three more predefined methods provided by the service, namely .save(), .remove(), and .delete(), that use POST and DELETE methods. But we will only deal with the .get() and .query() methods in this series as we are only dealing with retrieving data.

And this wraps up our tutorial for today.

What’s Up Next?

In the current tutorial, we wrote a lot of JavaScript code for bootstrapping our application, configuring routes, and creating RESTful services. We also dissected templates for different views in our application.

In the next part of the series, we will be building a custom AngularJS directive for the post listing feature using the Posts service we created. This will enable us to include the post listing feature in many locations without repeating ourselves. So stay tuned...

Tags:

Comments

Related Articles