神刀安全网

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.

  1. So first, let’s have yeoman create a new factory for us, called contentService :
    yo angular:factory contentService 
  2. Open app/scripts/services/contentservice.js .
  3. Add $http to the argument list of the callback function:

    .factory('contentService', function ($http) { 
  4. Replace the body of the callback function with this:
    var service = {     get: getContent };  return service;  function getContent(page) {     return $http.get('http://some.site/wp-json/wp/v2/pages/?filter[name]=' + page)     .then(getPageSuccess);      function getPageSuccess(response) {         if (response.data && response.data[0]) {             return response.data[0];         } else {             throw response.status;         }     } } 

Resolve the contentService

  1. Now in app/scripts/app.js , add contentService to the getPage argument list:
    pageContent: function getPage($route, $http, contentService) { 
  2. Next, replace the body of the getPage

    function with the following:

    var pathname = $route.current.pathParams.routename;  return contentService(pathname) .then(getPageSuccess);  function getPageSuccess(response) {     return response; } 

    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.

  1. Let’s start by having Yeoman make the service (factory) for us:
    yo angular:factory featuredImageService 
  2. 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.

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

    /**  * 1.  */ var service = {     get: getImageId,     set: setImageId },  /**  * 2.  */ images = [];  /**  * 3.  */ return service;  /**  * THE IMPLEMENTATION  */  /**  * METHOD: featuredImageService.get()  *   * This method takes an id as an argument and first looks for that id in  * our stored images array, then failing that, fetches that id from our  * WordPress API.  *   * If fetching from the API is successful, we call the setImageId function,  * which stores details of that image in our images array.  */ function getImageId(id) {     /**      * 4. & 5.      */     var pos, deferred = $q.defer();       /**      * 6.      */     if (id) {         /**          * 7.          */         pos = images.map(function(e) { return e.id; }).indexOf(id);          /**          * 8.          */         if (pos > -1) {             deferred.resolve(images[pos].url);             return deferred.promise;         }          /**          * 9. & 10.          */         return $http.get('http://adam.merrifield.ca/wp-json/wp/v2/media/' + id)         .then(setImageId);     }      /**      * 11.      */     deferred.reject('Unable to get featured image');     return deferred.promise; }  /**  * METHOD: featuredImageService.set()  *   * This method is primarily used by featuredImageService.get() but could be  * useful as a public method. As such, it accepts an object as an argument,  * and we test to see if that argument is a config object  * `{id: '1234', url: 'some.url/image.jpg'}` or a callback response object   * from our XHR.  *  * Finally, we push that configuration into our images array.  */ function setImageId(config) {     var image;      if (config) {         if (config.data) {             image = {                 id: config.data.id,                 url: config.data.source_url             }         } else {             image = {                 id: config.id,                 url: config.url             }         }          images.push(image);          return image.url;     }      return false; } 

    Detailed Explanation

    1. 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.

    2. 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.

    3. We set our service into motion.

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

    5. 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).

    6. Test if an id was passed as an argument.

    7. 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 .

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

    9. 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.

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

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

Bind to Our View

  1. 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:

    .controller('DynamicCtrl', function (pageContent, metaService, featuredImageService) { 
  2. Next, check to see if our resolved pageContent has a .featured_media property that isn’t 0 :
    if (pageContent.featured_media) {  } 
  3. Now we’ll call our featuredImageService and bind the results to our view model:
    if (pageContent.featured_media) {     featuredImageService.get(pageContent.featured_media)     .then(function (response) {         dynamic.featuredImage = response     }); } 
  4. Finally, let’s add this image to our dynamic page markup. Open app/views/dynamic.html and add an image tag that uses dynamic.featuredImage as the ng-src

    :

    <div class="jumbotron">     <h1 ng-bind-html="dynamic.title"></h1>     <img ng-if="dynamic.featuredImage" class="img-responsive" ng-src="{{ dynamic.featuredImage }}"> </div> 

    And there you have it…

    Using WordPress Featured Images in AngularJS

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.

Other Posts in this Series

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » Using WordPress Featured Images in AngularJS

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
分享按钮