One of the many things I deal with on a day to day basis is WordPress. Over 31% of the web is currently powered by WordPress. I try to explore many ways that I can use it's awesome administration system in order to build a really useful dataset for the front end. The way I am going to demonstrate this is by building a posts search filter.

I am going to take Posts, a default content type from WordPress and instead of using PHP template functions and methods like query_posts() and WP_Query($args), I am going to load the posts via JavaScript so there is no page refreshes. We will be making GET requests using Axios and the WordPress REST API. The requests will return JSON data which we can parse and manipulate with Vue.

I will be making these requests on an install of WordPress at https://www.njcfiles.com. The reason I am working with a hosted site instead of a local site is so that I can access the site through CodePen.

The first request we want to make would to be get all posts. In a fresh install of WordPress, there is a sample post called Hello World!.

I am going to remove this and add my own posts into the system. For each post, I have filled out the post title field, the content (WYSIWYG) area and selected a category from a list of dummy categories.

I have added 3 posts. These now should show up in the JSON data by hitting the following url.

https://www.njcfiles.com/wp-json/wp/v2/posts

Now that we have the JSON data ready, we can now commence with displaying the posts and building the Search filter within CodePen, away from WordPress.


Now that we are in CodePen, the first thing we want to do is add the VueJS and Axios libraries through a CDN, this is possible by going into the JS settings in the pen and going to the Add External Scripts/Pens section. Now we can create a new Vue instance. We will attach this to a div with and id of app.

  <div id="app">

</div>

  var app = new Vue({
  el: '#app',
  data: {
  },
});

We can test to see if Vue has been initialised properly by placing a {{ message }} inside the div and then creating a data property called message with a string as it's value. If the data passes through and displays, we know Vue is working. As we will be creating a search filter, we will need a search input field. We can add an input and bind it's value to a data property using v-model.

  <div id="app">
  <input type="text" v-model="searchTerm">
  <p>{{ searchTerm }}</p>
</div>

  var app = new Vue({
  el: '#app',
  data: {
    searchTerm:'',
  },
});

The paragraph tag within the template should now output whatever is typed in the input field. We can now remove this as it was only used to check if the binding had worked.

We need to create two arrays. One which is going to hold the results of the JSON request and then one to hold our filtered (by the search input) array of posts. I've called the one from the request, allPosts and the other just posts. We can add these after searchTerm.

  var app = new Vue({
  el: '#app',
  data: {
    searchTerm:'',
    allPosts: {},
    posts:{},
  },
});

We want to add a method to Vue to get all posts. We can add this under the methods array. In this function we want to make an Axios request then set the result of that request as our data array allPosts. We can also set posts to be the same result as this is the array we will be showing in the list and we want posts to be there when the request has finished, not just after the user has filtered by search. I will name this method, getAllPosts.

  var app = new Vue({
  el: '#app',
  data: {
  searchTerm:'',
  allPosts: {},
  posts:{},
  },
  methods: { 
    getAllPosts() {
      var _this = this; 
      axios.get('https://www.njcfiles.com/wp-json/wp/v2/posts')
      .then(function (response) {
        _this.allPosts = response.data;
        _this.posts = response.data;
      })
      .catch(function (error) {
        console.log(error);
      });
    }
  }
});

Under the methods array, we can call this function within, created() which is a method that runs once the instance has been created. We would call our getAllPosts function within this using, this.getAllPosts().

We can now display the posts array in the frontend template. I will use an unordered list with a v-for directive to output the posts.

  <ul v-for="post in posts">
  <li v-html="post.title.rendered"></li>
</ul>

The last thing we want to do is to filter these post titles by whatever is searched. We can create a new method called updateSearch and run this method on a keyup event of the text input. We would add this to the input, v-on:keyup="updateSearch".

The updateSearch method in Vue would look similar to this,

  updateSearch() {
  var _this = this;
    _this.posts = _this.allPosts.filter(post => post.title.rendered.toUpperCase().includes(_this.searchTerm.toUpperCase()));
}

All we are doing in this method is using the Vue filter function to check each post title (converted to uppercase) and see if it includes the searchTerm data value. posts is a result of this filter which will mean the frontend list will update with the filtered posts.

The overall template will be

  <div id="app">
  <input type="text" v-model="searchTerm" v-on:keyup="updateSearch">
  <ul v-for="post in posts">
    <li v-html="post.title.rendered"></li>
  </ul>
</div>

and the corresponding Vue instance would be

  var app = new Vue({
  el: '#app',
  data: {
    searchTerm:'',
    allPosts: {},
    posts: {}
  },
  methods: {
    getAllPosts() {
      var _this = this; 
      axios.get('https://www.njcfiles.com/wp-json/wp/v2/posts')
      .then(function (response) {
        _this.allPosts = response.data;
        _this.posts = response.data;
      })
      .catch(function (error) {
        console.log(error);
      });
   },
   updateSearch() {
     var _this = this;
     _this.posts = _this.allPosts.filter(post => post.title.rendered.toUpperCase().includes(_this.searchTerm.toUpperCase()));
   }
  },
  created() {
    this.getAllPosts();
  }
});

The CodePen example link for this tutorial:  CodePen - Out with the old, in with the Vue


1,332 2 17