Using WordPress Featured Images in AngularJS

Table of Contents:

Introduction

Over the past 7 posts we’ve been making an AngularJS application with a WordPress backend, but everything we’ve had to utilize so far has been neatly bundled in a single XHR request from WordPress. What if our WordPress page makes use of the Featured Image functionality? Wouldn’t it be nice if we could capture that too? Well we can, but it’s going to take a second request, after we get the first one.

In part 8 of this series we will make a content service to replace our existing vanilla $http requests in our route resolves, and then we’ll make an additional service to go fetch the relevant media associated with a featured image. Then we’ll conditionally display the featured image below our post title if one exists.

Set Some Images

First things first, we need some featured images to fetch. Go into your WordPress install and add a featured image to each of the test pages we’re fetching.

If you use an image more than once in multiple pages, we can test if we have fetched that information already and use it’s url from memory instead of fetching it again. More on that later.

Content Service

Currently we have an $http.get resolving in our default route. This is fine in the short term, but we really ought to move this to it’s own service. This is especially true now as we’ll be looking to do more work once that request is successful.

So first, let’s have yeoman create a new factory for us, called contentService:

All we’ve done here is move everything we were already doing to a reusable service.

Featured Image Service

If you spent any time exploring the returned data from our content requests, you may have noticed a property called featured_media. If your WordPress page makes use of the featured image, that property will have a value greater than 0. That value is what we will use to make another XHR to WordPress to get back all kinds of data about that image.

We’re going to make a setter/getter service to store the some of that data. But since we hope our visitors will bounce around a bit on our site, we’re going to store an array of data so that we don’t have to look up images we’ve seen before.

Let’s start by having Yeoman make the service (factory) for us:

yo angular:factory featuredImageService

Open the resulting file app/scripts/services/featuredimageservice.js and add $http and $q to the callback function argument list:

.factory('featuredImageService', function ($http, $q) {

We’re using $q so that we can return a promise regardless of whether we make an XHR or not. Again, more on that later.

Replace the callback function body with this (explanation numbers in the comments):

Detailed Explanation

We have two public methods, get and set. featuredImageService.get() will fetch an image from WordPress or serve it from memory if it exists already.

featuredImageService.set() will store an images data in memory for use later. We’ll primarily use this privately, but it could be useful publicly, so we account for that.

An empty image array that we’ll fill with image data as we fetch them. We’ll reference this array before ever making an XHR.

We set our service into motion.

Declare pos, a variable we’ll use to determine what position our our pre-fetched image is in, if it exists.

Define deferred as our promise object. As mentioned before, we are using this promise in the event that we’ve already fetched an image and do not need to make an XHR (which would require a promise by default).

Test if an id was passed as an argument.

Get the position of the passed id in the array of image objects.

NOTE: Array.prototype.map is supported in IE9 and up. If you require more support than that, use this pollyfill.

If a previous image is found, resolve that url in a promise, and return the promise. The function will exit here if true.

If the above test failed, then we are making an XHR to our WordPress instance. This time though, we are querying the media API instead of the pages API.

We use the id contained in a fetched page object as as the id to fetch from the media query. We’ll see that in action later.

We use setImageId, our otherwise public featuredImageService.set() method, as our callback handler.

If we got this far, no previous image was found or id was not passed as an argument.

Bind to Our View

First we’ll inject our featuredimageservice into our DynamicCtrl. Open app/scripts/controllers/dynamic.js and add featuredImageService to the argument list of the callback function:

Summary

In this post we created a contentService to fetch our content in a repeatable fashion, making it easier to fetch other things once that feature is resolved. Then we made a featuredImageService that can set and get featured images from a known featured_media id.