I’ve continued to play around with using Vue and WordPress’s API. The Vue stuff is entirely new to me but it’s pushing my javascript knowledge.
The main reason I’m excited about the WordPress/Vue (or whatever framework) combinations is simply speed. If you have any doubts give the pagination at the bottom of this demo site a shot. Crazy fast . . . and running stock on shared hosting. No caching plugins etc. The site is running the Vuetiful WordPress theme which has been an interesting thing to look at and see how it all works. Github is such a good thing.
Below or linked here is the WP JSON/Vue pagination I eventually got working. It’s forked from this demo by Brian Krosgard.1
Even with that large head start, a few things hung me up.
First, the navigation of the JSON elements is a bit tricky if you’re not used to it.
You’ll want to use the _embed parameter2 to get access to the featured image data. That’s an option I didn’t know about previously.
https://anth101.com/wp-json/wp/v2/posts?_embed&per_page=24&page=1
Since I named my main JSON objects ‘post’– to access the thumbnail URL, I’d use
post._embedded[‘wp:featuredmedia’][0].media_details.sizes.thumbnail.source_url
The part you need to pay attention to is the square brackets and the number following it. Notice there is no period between _embedded and [‘wp:featuredmedia’]. You might also want to look at the image of the JSON feed above and you’ll see the square bracket indicating an array of objects. That’s what we’re navigating into. These more complex nested JSON structures were a complete mystery to me starting off but I’m sort of getting the hang of it now.
Secondly, missing JSON objects arrays are not your friend. For instance, if you ask for a thumbnail and there is no thumbnail image then things break when it returns an invalid response. There are a variety of ways to check for them but I was confused about how to do it properly in Vue. Turns out you want a method. Which is basically, maybe entirely, a function. My thumbnail-image-checker ended up looking like this.
hasThumbnail: function(post) { if (post._embedded['wp:featuredmedia'] && post._embedded['wp:featuredmedia'][0].media_details && post._embedded['wp:featuredmedia'][0].media_details.sizes){ return post._embedded['wp:featuredmedia'][0].media_details.sizes.thumbnail;} }
It checks three elements sequentially. Initially I had only the first and third but ran into a scenario where some posts have featured images but they were too small to generate additional sizes and so I’d get an undefined error. Hat tip to Joel Eisner for getting me started down this road.
Pagination
The WordPress API makes pagination pretty easy. You can determine how many posts are on a page and what page you’re on via the URL.3
https://anth101.com/wp-json/wp/v2/posts?_embed&per_page=24&page=1
So to get at page navigation I just have to change the number at the end of the URL.4
It wasn’t too different than what was going on in the original demo I forked this from.
I did that by adding a data element creatively named ‘currentPage’ and setting it to equal 1 initially.
Incrementing the page variable up and down turned out to be pretty easy. The v-on:click elements below take care of that for us.
<div class="page-nav"> <div class="button" v-on:click="currentPage -= 1">- </div> <label>You're on page: {{ currentPage }}</label> <div class="button" v-on:click="currentPage += 1">+</div> </div>
Loading Animation
One element that I wanted was a loading icon for while the data was being fetched. Turns out that wasn’t too bad either. I used the Font Awesome spinner which was a nice little trick.
<div class="loading"><i v-if="!posts" class="fa fa-spinner fa-spin"></i></div>
The next goal was to set the spinner to show if the data element posts was not returning a value. That worked out of the box with the first load but failed on subsequent loads because posts had a value. Turns out I could just staple a function to my pagination buttons to set posts to null prior to fetching the new data and we were in business.
<div class="page-nav"> <div class="button" v-on:click="currentPage -= 1, posts = null">- </div> <label>You're on page: {{ currentPage }}</label> <div class="button" v-on:click="currentPage += 1, posts = null">+</div> </div>
Clearly it’s very ugly still but it’s a pretty decent functional example and I continue to bang away at it during random nights.
See the Pen vue json test pagination ANTH101 by Tom (@twwoodward) on CodePen.
1 It’s hard to tell I forked it though. I’m puzzled by all that.
2 I don’t really know the word for a variable expressed in a URL. That sounds about right. You can see it just after the question mark and prior to the first ampersand. Feel free to ask a question about octothorpes.
3 Maybe that’s a URI. Maybe you call that an API endpoint. It’s probably all of those things. If you want certainty . . . this is the wrong blog to read.
4 URI/magic font o’ information
Hello,
When I try to get my featured image with post._embedded[‘wp:featuredmedia’][0].media_details.sizes.thumbnail.source_url
I get the error: “TypeError: Cannot read property ‘0’ of undefined”
Have you ever encountered this error?
Yeah . . . essentially it means you don’t have an image that meets those requirements. The hasThumbnail function is supposed to check for that. Is that in place or no?