Employee Post

How To Create an Auto-Updating Widget Using WP-API

In my last post, I gave you an overview of WP-API. Read through that post if you need a primer on the capabilities of WP-API. For this post, I will offer an example of API usage and how it can benefit site owners by creating more dynamic content.

In this post, we will go over creating a comment widget that auto-updates via WP-API without refreshing the page, and how to use AJAX to poll the API for new comments and then display those comments in a sidebar widget.

Here’s a gif of the widget in action as it would look in the Twenty Twelve theme:

TestyAntiqueHoatzin

The first thing you will need is to install the WP-API plugin. WordPress has not included this in core yet as it is still in active development. (Make sure it is the correct plugin by Ryan McCue!)

Activate the WP-API plugin. There are no settings for this plugin. Visit your site’s API URL (yoursite.com/wp-json) to verify the API is active and working. If you want to learn more about the API, visit the previous post in this series or peruse the WP-API getting started guide.

After you have verified the API is working and returning JSON data, you can install the example project plugin outlined in this post. This is a fully working plugin. You can look through the plugin code base to understand how it works or read the rest of the post that highlights how this plugin was created so you can learn how to create your own dynamic content using the WP-API.

WHY JSON?

Normally, when you load a WordPress page, the dynamic content is compiled on the server and then displayed. In laymen’s terms, PHP is like a bunch of ingredients and the server mixes it together to give you something to consume. The PHP in WordPress templates produces dynamic content that can supply posts, pages, media, comments, or some other content type.

PHP processes before the page load, so there is a possibility that it could slow down the page load. Anything that helps a website’s time to first render is a good thing. We all hate when the page loads are slow. Search engines (hi Google, how ya doin’?) are even against slow loading sites. Page caching helps with page load but also, is the opposite of what we want to achieve–which is is live updated content.

Using JSON to display dynamic content instead of replying on the server to process the PHP frees up the page loading. You might not necessarily see the dynamic content any faster, but the time to display non-dynamic parts of a page can load faster with a perceived snappier user experience. Lazy loaded images are an example of not loading content at first to allow faster page rendering.

If your content is updated frequently, using JSON to display dynamically loaded content on the page will work well for you. You may want a user to get the most timely content as possible without requiring a full page refresh; this is where a JSON API comes in handy. Pinging a JSON API for data is the simplest method possible.

THE CODE

We are not going to go over the code line by line, but I will highlight the parts that are important. The example plugin uses a Widget Boilerplate maintained by WebDevStudios.

The current WP-API plugin does not contain a comments endpoint to access all comments, but it’s in development for version 2.0. No problemo–the API allows custom endpoint creation and we can supply any data your WordPress lovin’ heart desires.

To add endpoints to the API, we can add a filter to ‘json_endpoints’, passing an array with information on how the endpoint should be structured. In the routes function, we tell it what function to run when we are at the endpoint on the site. Visit url/wp-json/comments and the get_items() function runs. Though we have used “comments” as the endpoint, this may cause a collision if another plugin or even the WP-API itself registered the same endpoint. If you create your own endpoints make sure they are unique. You can find the following three functions in file comments-api-endpoints.php.

– Register endpoint

function wds_api_comments_init() {
    $wds_api_comments = new WDS_API_COMMENTS();
    add_filter( 'json_endpoints', array( $wds_api_comments, 'register_routes' ) );
}
add_action( 'wp_json_server_before_serve', 'wds_api_comments_init' );

– Register route

function register_routes( $routes ) {
    $routes['/comments'] = array(
array( array( $this, 'get_items'), WP_JSON_Server::READABLE ),
);
    return $routes;
}

After a route is registered, we need to return a JSON array of data. Since we are getting the last few comments, WordPress has the function get_comments(). Pass in a few parameters and then convert the results into JSON. The endpoint data functions can be as complex as needed to return any type of data in your database. This function is lacking a bit of error handling if no comments exists. We could return a message if there are no comments.

– Get comments

function get_items() {
    $comments = get_comments( apply_filters( 'widget_comments_args', array(
'number' => 5,
'status' => 'approve',
'post_status' => 'publish'
) ) );

    return wp_send_json( $comments );
}

Now that we have an endpoint with data, we use AJAX to get the comments and display them in our widget. First thing is to enqueue our JavaScript file that has our AJAX for pinging the API for comment data. We have a check to see if the widget is active and we are on the front of the site. We don’t want to ping the API unnecessarily. Also, we need to add the API URL to the header as a script variable to be used by jQuery AJAX.

– Enqueue scripts

function scripts() {
    
    $jsfile = WDS_COMMENT_WIDGET_PLUGIN_URL . 'inc/comment-widget.js';
        
    if ( is_active_widget( false, false, $this->widget_slug, true ) && ! is_admin()  ) {
        wp_enqueue_script( 'script-name', $jsfile, array(), WDS_COMMENT_WIDGET_VERSION, true );
      }
}

We will also need to add an API variable; we can retrieve it later in our AJAX. We hook this to wp_head so its ready when the page loads.

– API url

function apiurl() {
    ?>
    <script type="text/javascript">
    var apiurl = '<?php echo trailingslashit( site_url('wp-json') ) ?>';
    </script>
    <?php
}

Now let’s take a look at that JavaScript file we enqueued. It contains jQuery $.ajax to ping our endpoint, get comment data, and process it. We have an on success function to process the data into HTML and add it to our widget. You might see a set interval–this is to set a specific amount of time to run our AJAX. We run the AJAX on page load then set an interval, after two minutes kill set interval so the API isn’t pinged constantly. This is a simple method. Another (possibly better) way might be to detect mouse moves (scrolling or click event) to see if a user is still active before killing the set interval. You could also use the heartbeat API to run our AJAX in intervals.

– AJAX

(function($) {

    // run get comment function and poll api for comments
    get_comments();

    // set interval to check every 15 seconds
    var refresh = setInterval( function() {
        get_comments();
    }, 15000);


    // after 2 mins kill api check
    setTimeout( function() {
        clearInterval(refresh);
    }, 120000);


    /**
     * get_comments function.
     * 
     */
    function get_comments() {
    
        // borrow the admin loading spinner
        $('#wds-comment-widget').html( '<img src="/wp-admin/images/wpspin_light.gif">' );
    
        $.ajax({
            url: apiurl + 'comments',
            dataType: 'json',
            type: 'GET',
            success: function(data) {
                // send data to processing function
                process_comment_data( data );
            },
            error: function() {
               console.log('Error with API');
               $('#wds-comment-widget').html( 'No comments' );
            }
        });
        
    }



    /**
     * process_comment_data function.
     * 
     */
    function process_comment_data( data ) {
        
        // start an array for comments
        var comments = [];
        
        $.each( data, function( index, value ){
        
            comments += '<li postid="' + data[index]['ID'] + '">' + data[index]['comment_author'] + ' on <a href="' + data[index]['guid'] + '">' + data[index]['post_title'] + '</a></li>';
        
        });
        
        setTimeout( function() {
            $('#wds-comment-widget').html( '<ul>' + comments + '<ul>' );
        }, 500);
        
    }
    
    
 })(jQuery);

That’s all there is to it! Check out the example plugin for the full code. Hopefully this post helps you to use WP-API on your site, and allows you to offer viewers more dynamic content!

2 thoughts on “How To Create an Auto-Updating Widget Using WP-API

  1. I get the following notice when activating the example plugin:
    Notice: Undefined property: WDS_AutoUpdate_Comment_Widget::$plugin_dir in /srv/www/wordpress-default/wp-content/plugins/wds-auto-update-comment-widget/wds-auto-update-comment-widget.php on line 101

Have a comment?

Your email address will not be published. Required fields are marked *