I’m trying to figure out how I should call a REST API custom endpoint from the JS code of a plugin. Here is the PHP code of a sample plugin I’ve just written to show my issue. The filename is rest-api-sample.php:

<?php
/**
 * @link              https://www.virtualbit.it
 * @since             1.0.0
 * @package           Rest-API-Sample
 *
 * @wordpress-plugin
 * Plugin Name:       Rest API Sample
 * Plugin URI:        https://www.virtualbit.it/rest-api-sample
 * Description:       Just a code sample
 * Version:           1.0.4
 * Author:            Lucio Crusca
 * Author URI:        https://www.virtualbit.it
 * License:           GPL-2.0+
 * License URI:       http://www.gnu.org/licenses/gpl-2.0.txt
 * Text Domain:       rest-api-sample
 * Domain Path:       /languages
 */

class IESRestEndpoint 
{
  private $namespace = "ies/v1";
  public function __construct()  {
     add_action( 'rest_api_init', array($this, 'registerRoutes')); 
     add_action( 'wp_enqueue_scripts', array($this, 'enqueue_scripts'));
  }

  public function istermactive(WP_REST_Request $request)  {
    $result = true;
    return $result; // this is my controller.
  }

  public function registerRoutes()  {
    register_rest_route( $this->namespace, 
                         '/istermactive/', 
                          array('methods' => 'GET',
                                'callback' => array($this, 'istermactive')
                               )
                       );
  }

  public function enqueue_scripts() {    
    $handle = "ies-rest-api";
    $jsfileurl = plugin_dir_url( __FILE__ ) . '/ies.js';
    wp_register_script($handle, $jsfileurl, array("underscore", "backbone", "wp-api"));    
    $local_data = array('apiRoot' => get_rest_url(), "namespace" => $this->namespace);
    wp_localize_script($handle, "ies_rest", $local_data);
    wp_enqueue_script($handle);
  }  
}

$ies_endpoint = new IESRestEndpoint();

And here is the ies.js code:

(function( $ ) {
  'use strict';

  $(document).ready(function()
  {  
    wp.api.init({'versionString' : ies_rest.namespace,  'apiRoot': ies_rest.apiRoot}).done(function()
    { 
      wp.api.loadPromise.done(function () 
      {
        wp.api.namespace(ies_rest.namespace).istermactive().done(function (active)
        {
          alert(active);
        });
      });
    });    
  });

})( jQuery );

However this JS code, in WP 4.7.4/4.7.5, throws an exception in the JS console after the call to wp.api.init() and before it reaches the call to wp.api.loadPromise():

Uncaught TypeError: _.includes is not a function
    at wp-api.min.js?ver=4.7.4:1
    at Function.h.each.h.forEach (underscore-min.js?ver=4.7.4:1)
    at Object.wp.api.utils.decorateFromRoute (wp-api.min.js?ver=4.7.4:1)
    at wp-api.min.js?ver=4.7.4:1
    at Function.h.each.h.forEach (underscore-min.js?ver=4.7.4:1)
    at n.constructFromSchema (wp-api.min.js?ver=4.7.4:1)
    at n.<anonymous> (wp-api.min.js?ver=4.7.4:1)
    at n.<anonymous> (backbone.min.js?ver=1.2.3:1)
    at n.<anonymous> (underscore.min.js?ver=1.8.3:5)
    at _ (backbone.min.js?ver=1.2.3:1)

The same code, using WP 4.8beta2, seems to work at least until it reaches the wp.api.namespace() call, where I get:

Uncaught TypeError: wp.api.namespace is not a function
    at Object.<anonymous> (https://www.virtualbit.it/wp-content/plugins/rest-api-sample//ies.js?ver=4.8-beta2:10:16)
    at i (https://www.virtualbit.it/wp-includes/js/jquery/jquery.js?ver=1.12.4:2:27449)
    at Object.add [as done] (https://www.virtualbit.it/wp-includes/js/jquery/jquery.js?ver=1.12.4:2:27748)
    at Object.<anonymous> (https://www.virtualbit.it/wp-content/plugins/rest-api-sample//ies.js?ver=4.8-beta2:8:26)
    at i (https://www.virtualbit.it/wp-includes/js/jquery/jquery.js?ver=1.12.4:2:27449)
    at Object.fireWith [as resolveWith] (https://www.virtualbit.it/wp-includes/js/jquery/jquery.js?ver=1.12.4:2:28213)
    at Object.e.(anonymous function) [as resolve] (https://www.virtualbit.it/wp-includes/js/jquery/jquery.js?ver=1.12.4:2:29192)
    at Object.<anonymous> (https://www.virtualbit.it/wp-includes/js/wp-api.min.js?ver=4.8-beta2:1:13404)
    at i (https://www.virtualbit.it/wp-includes/js/jquery/jquery.js?ver=1.12.4:2:27449)
    at Object.fireWith [as resolveWith] (https://www.virtualbit.it/wp-includes/js/jquery/jquery.js?ver=1.12.4:2:28213)

My JS file (ies.js) is not even mentioned in the stack trace of the 4.7.x exception, while in 4.8beta2 it seems a simple syntax error, but I don’t know how should I otherwise call my endpoint.

I thought it could be a WP bug (maybe a documentation bug), and I opened a bug report. It turned out it’s NOT a WP bug, so this question still needs an answer, but Adam, who replied to my bug report, gave us some valuable informations.

As for the suggestion birgire gave in comments, unfortunately I have no clue about how to use the QUnit code, maybe you can walk me through that?

If you want to try this sample plugin, you can find it here, and, just in case you are interested, you can debug the JS code at my website homepage, where this sample plugin is already installed (WP version is 4.8beta2 as of time of this writing).

4 s
4

It looks like you are trying to send a POST request to the /istermactive endpoint, is that correct? (I think you may want to remove the trailing slash from the endpoint?)

I’m not really sure the wp-api client is the right tool for a standard ajax POST, you may want to use jQuery.ajax or use WordPress’s helper wp-ajax.

The wp-api client is designed to help you when you want to interact with a collection of items or a single item (eg posts or a post) when retrieved from the WP-API. It creates Backbone models and collections by parsing the API schema. Check here for some docs (which are in need of some updates).

Leave a Reply

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