Using the WordPress JavaScript APIs for fun and profit - The beginning

With the recent release of WordPress 5.0, a new editor was introduced into the WordPress ecosystem. Based on a new tech stack that includes React and Redux, WordPress now allows for richer, more intuitive interfaces and simplifies the overall editing process. But that's not all! With the recent changes, it's also become much easier for plugins to integrate with one another through the WordPress JavaScript APIs.

The goal

The goal for this tutorial series is to make a plugin that’s fully interoperable with the WordPress JavaScript API. But what does interoperability mean? Interoperability means that various computer systems can use and exchange data amongst themselves. A good example of plugins that have a lot to gain from becoming fully interoperable with WordPress 5.0, are page builders. Page builders have a long history of interoperability issues within the ecosystem when it comes to properly working together with other plugins, especially when exchanging of data comes into play. By using the new API, we can overcome most of these issues and make them a thing of the past.

How?

To make this series of posts a bit more structured, we’ll be using a case study where we're going to create a simple custom content editor with the following fields:

  • A title field.
  • A slug field.
  • A content area.
  • An excerpt field.

Although this content editor is rather simple, it’ll touch on all the crucial parts of the generic WordPress editing experience. It will allow us to create a project that will emulate this experience while remaining fully compatible and open to other plugins to read and write data. This can be highly beneficial for the aforementioned situation with page builders.

Throughout the series, you’ll see both examples in jQuery and React. Please note that we consider React the standard all this, but that we feel the jQuery examples can be highly beneficial for plugins that haven’t made the switch (yet) and still want to be compatible with the new WordPress editing experience and the APIs.

The WordPress JavaScript API system

One of the big improvements with the release of WordPress 5.0 is the uniform way in which data is tracked when editing in WordPress. By using Redux, application state can be stored and retrieved in simple, reliable ways by developers. This allows them to extend or implement the editing experience in various different ways or use the data in some shape or form.

Lets start building!

Prerequisites

Before we start working on our project, there are a few things you need to set up. If you decide to go down the jQuery route, you can skip the following paragraph and continue at the Setting up section.

At Yoast, we use Webpack to bundle our JavaScript files. Bundling is necessary because we write React files which are written following the ES6 specifications. Via the power of Babel, we ensure that our code is compatible with all major browsers without losing all the cool benefits that ES6 gives us. If you plan on following the React examples, feel free to use Webpack or any other bundler for your own code. Additionally, we prefer Yarn over NPM, but this too is mostly a matter of personal taste.

For this post, we'll be using the following Webpack configuration, which can also be found in the repository:

const path = require( "path" );

module.exports = {
    mode: process.env.NODE_ENV,
    entry: {
        reactApp: "./js/src/app.js",
    },
    output: {
        path: path.resolve( "js", "dist" ),
        filename: "[name].js",
    },
    externals: {
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                use: [
                    "babel-loader",
                ]
            }
        ]
    },
};

Setting up

To make things a bit easier, we've created a separate repository on GitHub that contains all the code samples used throughout the article, written so that you can see what the code should look like as we progress through the series. Note that for every chapter within the series, there are two different HTML and two different JavaScript files: One of them contains the examples written with jQuery, the other with React.

If you've checked out the repository we've created, you should have the following folder structure available to you:

The initial form

Because we want to process user input, we first need to make it possible for users to add input. The easiest and most straightforward way to do that is through a simple form.

React

In the js/src directory, we'll create a new file called simple-form-react.js which contains the following code:

import React from 'react';

/**
 * Class that creates a simple input form.
 */
class SimpleForm extends React.Component {
    /**
     * Renders the form.
     *
     * @returns {JSX} The Rendered form.
     */
    render() {
        return (
            <div>
                <section>
                    <label htmlFor="title">Title</label>
                    <input type="text" id="title" />
                </section>

                <section>
                    <label htmlFor="slug">Slug</label>
                    <input type="text" id="slug" />
                </section>

                <section>
                    <label htmlFor="content">Content</label>
                    <textarea name="content" id="content" cols="60" rows="10"></textarea>
                </section>

                <section>
                    <label htmlFor="excerpt">Excerpt</label>
                    <textarea name="excerpt" id="excerpt" cols="60" rows="10"></textarea>
                </section>
            </div>
        );
    }
}

export default SimpleForm;

Additionally, we'll create a file called app.js in the src/js directory which will render the above form.

import React from 'react';
import ReactDOM from "react-dom";

import SimpleForm from "./simple-form-react";

class App extends React.Component {
    render() {
        return ( <SimpleForm /> );
    }
}

ReactDOM.render( <App/>, document.getElementById( "root" ) );

Make sure you run yarn build-dev to ensure the code is compiled by Webpack and Babel. Pro-tip: if you append --watch to the command, Webpack will automatically recompile every time you edit and save the file!

Now open up index-react.html in your favorite browser and see as your creation… Oh wait, there's nothing there!? That's correct. The last line in the above code sample looks for an HTML element with the id of "root", but we haven't added that just yet. Open up index-react.html in your editor and add the following to the <body> section:

<div id="root"></div>
<script type="text/javascript" src="js/dist/reactApp.js"></script>

Refresh the page in your browser and you should now see a very basic looking form.

jQuery

In the js/src directory, we'll create a new file called simple-form.js which contains the following code:

$( function () {} );

The above code is just up getting the jQuery side of things ready. Nothing is actually happening just yet.

Next, lets add the HTML to the index.html file, within the <div id=“root”></div> tag:

<div>
    <section>
        <label for="title">Title</label>
        <input type="text" id="title" name="title"/>
    </section>
    <section>
        <label for="slug">Slug</label>
        <input type="text" id="slug" name="slug" />
    </section>
    <section>
        <label for="content">Content</label>
        <textarea name="content" id="content" cols="60" rows="10"></textarea>
    </section>
    <section>
        <label for="excerpt"></label>
        <textarea name="excerpt" id="excerpt" cols="60" rows="10"></textarea>
    </section>
</div>

After closing the ‘root’ div, add the following two lines:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="js/src/simple-form.js"></script>

This concludes the jQuery side of things!

The next steps

That's all for part one of this series. As you may have noticed, the form we built doesn't really do anything yet. In the following post, we'll get started with connecting the data that we fill in this form, to a central data store by using Redux, allowing us to more easily share data and state across our application.

Read more: Our revolutionary solution to Schema.org markup »