Paulund

Create Category Page - VueJS WordPress Theme

The next tutorial in the VueJS WordPress theme series we're going to create the category pages for the theme. So far in the theme, we've created the homepage, the blog post page, and the static pages. For the category pages they are similar to the Homepage being that it will list all the posts within a certain category.

WordPress REST API

Before we get started with displaying the list of posts for a specific category we need to understand how the WordPress API works. There is an endpoint to get information on categories if you want to get a list of all categories you use the following endpoint.


/wp-json/wp/v2/categories

We can use this same endpoint to search for a specific category by using a few options. In this example we're going to use the slug option in the querystring to search for a category with the slug we find in the route URL, this is done by using this endpoint.


/wp-json/wp/v2/categories?slug={CATEGORY_SLUG}

The reason we're using the slug option is because in the tutorial to setup routes for the WordPress theme we created a route for the category.


    {
      name: 'Category',
      path: '/c/:categorySlug',
      component: CategoryPage
    }

On Paulund I have a category for tutorials on the URL of https://paulund.co.uk/c/tutorials we now have the same route on the VueJS WordPress theme and it will display the CategoryPage component.

Category Component

The category component will be loaded when we navigate to the category URL, there are a few things we need to do when this is loaded. First, we need to get the information for the category that we navigated to, we do this by using the endpoint /wp-json/wp/v2/categories?slug={CATEGORY_SLUG} using the slug in the URL. This will return all the data for this specific category, we can then use the category information to search for posts under this category. Looking into the REST API we get can a list of posts from a certain category by using the posts endpoint with the option categories and can use the value of the category ID.


/wp-json/wp/v2/posts?categories=' + this.category.id

In the template tag of the category component we're going to display the name of the category and then use the list-post component created on the Homepage tutorial and pass in an array of the posts from this category.


<template>
    <div id="category">
        <h2 class="title is-2">{{ category.name }}</h2>

        <list-posts v-bind:posts="posts"></list-posts>
    </div>
</template>

Within the script tag of the component we need to import the axios library to make API calls and the ListPost component.


import axios from 'axios'
import ListPosts from '../global/ListPosts.vue'

The data section of the VueJS component consists of title, category and posts. The title is used to change the document title tag of the page, the category variable is used to store the category information from the API, the posts variable will be an array of all posts within this category.


  data () {
    return {
      title: '',
      category: [],
      posts: []
    }
  },

On the created state of this component, we'll need to call the getCategory() method to fetch all the data for the page.


  created () {
    this.getCategory()
  },

Now we can create the getCategory method to fetch the data. Below is the code for the category, first we get the current route path this.$route.path and we use this to fetch the category data for this route axios.get(process.env.API_URL + '/wp-json/wp/v2/categories?slug=' + path[path.length - 1]). If the response is successful then we store this into the category variable, if category doesn't exist then we can redirect to the NotFound page this.$router.push({name: 'NotFound'}). If the category response is successful then we can take the category name and use this in the document.title. With the category data in place we can now fetch the posts for this category by calling the getPosts() method. This method will then use the posts endpoint with the option of the category ID to only fetch posts on this category for us to pass into the ListPost component.


  methods: {
    getCategory () {
      var path = this.$route.path.split('/')
      axios.get(process.env.API_URL + '/wp-json/wp/v2/categories?slug=' + path[path.length - 1])
      .then(response => {
        this.category = response.data[0]

        if (this.category === undefined) {
          this.$router.push({name: 'NotFound'})
        }
        document.title = this.category.name
        this.getPosts()
      })
      .catch(e => {
        console.log(e)
      })
    },

    getPosts () {
      axios.get(process.env.API_URL + '/wp-json/wp/v2/posts?categories=' + this.category.id)
      .then(response => {
        this.posts = response.data
      })
      .catch(e => {
        console.log(e)
      })
    }
  },

Below is the full code for the category page component.


<template>
    <div id="category">
        <h2 class="title is-2">{{ category.name }}</h2>

        <list-posts v-bind:posts="posts"></list-posts>
    </div>
</template>