wejotek + vue + wordpress = posts

wejotek + vue.js + wordpress – the setup and more

In my previous post on the subject, we talked about why I would attempt such a ridiculous project as to create a front end for my WordPress blog using Vue.js. So, if you got here first, and you care to know why, go there to find out!

First Step – Setup Vue.js

For the initial setup, I used this simple guide. Well, not at first. Then I wasted an hour trying to setup typescript properly. Deleted everything. Then used this simple guide! – https://medium.com/@karl.lee/vue-cli-3-typescript-a-quick-start-guide-324a18859485

Now that I had a properly configure project, I began to work on the fun stuff. Next step you ask?

Second Step – Get Some Posts

I don’t think like most people. Sometimes I just do things to maintain sanity. Setting up projects is fun and all, but I can only handle so much of that. At some point, I want to do something more interesting. So, I took a break from setup to do something interesting.

The first thing I had to do was look into the WordPress API to figure out how to request posts. Since I am proficient in Google, I quickly came across this – https://developer.wordpress.org/rest-api/reference/posts/#example-request

Bam! Simple as that. Next, I had to decide how I was going to make the requests from my app.

Third Step – The API Request

After a bit of research, it seemed like the general consensus was to use axios ( https://github.com/axios/axios ). It works anywhere javascript can run, uses everybody’s favorite – Promises – and has a slew of other cool features I probably don’t need. But, it works. And that is important…

Forth Step – Render the API Request Results in Vue.js

Time for some code! Let’s look at the request class first. But please be prepared, this is DEEP.

import Vue from 'vue'
import Component from "vue-class-component";
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'

@Component
class WordPress extends Vue {
    private readonly BASE_URL: string = "https://www.wejotek.com/"
    private readonly POSTS_ENDPOINT: string = "wp-json/wp/v2/posts"
    getPosts(maxPosts: number): Promise<AxiosResponse<any>> {
        const config: AxiosRequestConfig = {
            params: {
                "per_page": maxPosts
            }
        }
        return axios.get(this.BASE_URL + this.POSTS_ENDPOINT, config)
    }
}
export default WordPress

I created a class that wraps the axios client and exposed a getPosts method that takes a parameter that specifies that maximum number of posts to return. Pretty straightforward – right?

Unfortunately, not for me. As I began to implement this the Vue.js way, I realized that this API wrapper should really be a Mixin ( https://vuejs.org/v2/guide/mixins.html ). The crummy part about that is that it is not well documented on how to create and consume a Mixin using typescript. After some MORE research, I figured it out. Well, someone else figured it out and I copied it. Same thing, right?

Bottom line is this. I am using the vue-class-component ( https://github.com/vuejs/vue-class-component ) and the docs provided there. But really, on the actual “mixin”, you just have to make sure your class extends Vue.

Now I needed to consume this Mixin from a component. For simplicity, I am using the home component generated by the CLI – with some slight modifications.

<template>
  <div class="home">
    <div v-if="!loaded">loading...</div>
    <div v-else v-for="post in posts" :key="post.id">
      <div v-html="post.title.rendered"></div>
    </div>
  </div>
</template>

<script lang="ts">
import Component, { mixins } from "vue-class-component";
import WordPress from "../mixins/WordPress";

@Component
export default class Home extends mixins(WordPress) {
  loaded: boolean = false;
  posts: [{}] = [{}];
  created() {
    this.getPosts(5)
      .then(response => {
        console.log("Home:created:this.getPosts(5):response", response);
        this.posts = response.data;
        this.$nextTick(() => {
          this.loaded = true;
        });
      })
      .catch(error => {
        console.log("Home:created:this.getPosts(5):error", error);
      });
  }
}
</script>

This is pretty basic stuff for anyone familiar with Vue.js. In case your not, let’s walk through it. Here is our template.

<template>
  <div class="home">
    <div v-if="!loaded">loading...</div>
    <div v-else v-for="post in posts" :key="post.id">
      <div v-html="post.title.rendered"></div>
    </div>
  </div>
</template>

Like I said, basic. I am checking a loaded property and displaying loading text until loaded is true using v-if and v-else. Once loaded is true, I loop through all of my posts and display the title in a div. Simple.

I have a couple of “reactive” properties, loaded and posts.

loaded: boolean = false;
posts: [{}] = [{}];

I got lazy on posts and didn’t create an interface for them yet, but I knew that the time would come when I would have to come back to that. For now, sanity.

When this Home component gets created, I make the API call to get my posts.

created() {
    this.getPosts(5)
      .then(response => {
        this.posts = response.data;
        this.$nextTick(() => {
          this.loaded = true;
        });
      })
      .catch(error => {
        console.log("Home:created:this.getPosts(5):error", error);
      });
  }

I wanted to get the data after nav and show a loading whatever as the posts are being fetched, so I used the created() method of my Vue.js component. The logic for that came from here ( https://router.vuejs.org/guide/advanced/data-fetching.html#fetching-after-navigation ).

I wait for the nextTick, set my posts prop to the data returned from the WordPress API and let Vue.js do the rest! It’s like magic. In no time, all 5 of my post titles show up and the loading text disappears. Bam!

Fifth Step – Go Watch a Movie With My Wife

As fun as all this was, I couldn’t and wouldn’t pass up movie night with my wife. So it’s time to put away my toys and do something meaningful. As I look ahead to what is next, I know I need to look at Vuex and properly maintaining the state of this application. Which propably means all this mixin nonsense goes away in favor of actions and other Vuexy stuff. Until then – later.

Tags: No tags

Comments are closed.