This is part II of using Vue.js to create a UI component for WordPress. See part I here. In this article we will first alter our CodePen.io to include some hidden inputs that will hold the data we want to pass into WordPress and then we will take this vue component from Codepen.io and place it into WordPress by creating a plugin.
Adding values that will be POSTed to WordPress
This Vue component is going to be placed on the Post edit screen. This screen is like one big <form>
element. When the user clicks the ‘Publish’ or ‘Update’ button all the form values are POSTed to WordPress. From there, the PHP code of WordPress can read in the POSTed values using the global $_POST
associative array. We need to place the values we want to be posted. Actually, this is easy. Any <input>
element will be POSTed to WordPress. Since our <input>
‘s will be with a plethora of other <input>
‘s from other plugins, we do want to make sure we don’t create an <input>
with the same name as another. So we add a unique prefix to all our name values. This is called namespacing.
In our component we have multiple ‘screens’ and we will have no control of when the user presses ‘Publish’. What if they ‘accidentally’ press it while they are on the ‘edit’ screen before they press OK or Cancel. We don’t want this incomplete data overwriting the location data. This is why we create a temporary location object and use that just for the Edit ‘screen’ of our Vue component. Only when component’s ‘OK’ button is pressed does it get copied to the loc
object. It is this loc
object we want to POST to WordPress.
Now understand that ALL <input>
‘s are going to be POSTed to WordPress even the temporary object on the component’s Edit ‘screen’. For ease, we will keep all the values we’ll need for WordPress together in one place with all of them set type="hidden"
. We also give them a slightly different prefix than the other <input>
‘s in our component so we can easily grab only those values if we are POSTing using AJAX.
Here is a section of our Vue component containing our hidden inputs. It contains the loc
object and some boolean flags we will set to help us determine if the location was changed or deleted. (Remember we are using PUG here that will be compiled to HTML)
...previous pug/html code
#loc-8-post-inputs
//-
If this component is in WP admin page it will be in a form
These contain the values to be returned via $_POST
if there is a submit.
Remember to add the WP nonce - we will have WP append the nonce to this html when it is requested
input(type="hidden" v-model="loc.lat" name="loc-8-lat")
input(type="hidden" v-model="loc.long" name="loc-8-long")
input(type="hidden" v-model="loc.address" name="loc-8-address")
input(type="hidden" v-model="loc.address2" name="loc-8-address2")
input(type="hidden" v-model="loc.city" name="loc-8-city")
input(type="hidden" v-model="loc.state" name="loc-8-state")
input(type="hidden" v-model="loc.zip" name="loc-8-zip")
input(type="hidden" v-model="loc.country" name="loc-8-country")
input(type="hidden" v-model="addressChanged" name="loc-8-changed")
input(type="hidden" v-model="addressDeleted" name="loc-8-deleted")
Creating the initial WordPress plugin and development environment
Initially, we created a folder called jhts_loc_8
under our WordPress plugins
folder. We then added a file called jhts_loc_8.php
. In this file we created the proper comment section to give this plugin a name and created a php class containing our code for the plugin. Here’s a shell of it in our jhts_loc_8.php
:
Now let's move some code from Codepen.io to our WordPress plugin.
Moving our HTML/PUG code to our plugin
We can do this multiple ways. The easiest would be in Codepen.io on the HTML banner of the edit screen, click the downward arrow and choose "View Compiled HTML" and then copy and paste into a file in our plugin folder.
(click image to load 168KB GIF)
We are going to create a folder in our plugin folder called views
and in this folder we will create a file called loc-8-component.html
. In this file we will paste our compiled HTML.
If you have a development environment, another way of doing this would be to copy the PUG code into a file called loc-8-component.pug
and use a task runner like gulp and a plugin called gulp-pug to automatically compile the pug file to loc-8-component.html
. If you are interested in learning more about our development environment, send us a comment below.
Placing our HTML on the Edit Post screen
Let's add code to our plugin that will place this html on the Edit Post screen. In the __construct function we'll add two hooks: one to create our meta box on the Edit Post screen, and one to create our meta box on the New Post screen. This will set things up so eventually we'll get to our function loc_8_meta_box()
that writes out the html to our meta box. It adds a nonce field first and then our component html. Here's the code we add to our plugin class:
class Jhts_loc_8 {
//...previous code
public function __construct() {
// Load our meta box containing our loc-8 component
add_action( 'load-post.php', array( $this, 'loc_8_meta_box_setup' ) );
add_action( 'load-post-new.php', array( $this, 'loc_8_meta_box_setup' ) );
}
public function loc_8_meta_box_setup() {
add_action( 'add_meta_boxes', array( $this, 'loc_8_add_meta_box' ) );
}
public function loc_8_add_meta_box() {
add_meta_box( 'loc_8_meta_box', __( 'Location', 'loc-8' ), array(
$this,
'loc_8_meta_box'
), 'post', 'normal', 'core' );
}
//output of our Loc-8 meta box
public function loc_8_meta_box() {
wp_nonce_field( 'loc-8-', 'loc-8-nonce' );
include( 'views/loc-8-component.html' );
}
}
Moving our JavaScript from CodePen.io to our plugin
First, we will want to get a copy of vue.min.js and put this in our plugin folder. We'll create a js
folder under our plugin folder and then a vendor
folder under that where we will copy the vue.min.js file.
Second, we need to copy our Vue component JavaScript code. We are using ES2015 JavaScript in our CodePen.io so we will need to choose the "View Compiled JS" option and copy this code.
We will create a file called 'scripts.js' under the js
folder and paste this code into this file.
Alternatively, one can setup a task runner and transpile the ES2015 code to standard JavaScript automatically for us.
We do need to make a couple of changes to the javaScript. First, we need to remove the objects we created that represented the data we would get from WordPress. For example, the initial location data. We'll show how we get WordPress to give us this initial location data below.
Second, we need to make sure our JavaScript runs after the DOM is fully loaded. WordPress uses JQuery and so we will put our code into an immediate function and use jQuery to run our component when the document is ready.
(function( $ ){
$(document).ready(function() {
/* Will run after page is loaded in the DOM */
/* Our JavaScript code goes here */
});
})(jQuery);
Placing our JavaScript on our Edit Post page
Similar with adding our HTML, let's add a hook to add our JavaScript code. We only want it on the Edit Post page so we will test for that before we actually output our scripts. We also will be needing leaflet.js since our Vue map-component needs it to create the maps. We'll place that in our vendor
folder as well.
class Jhts_loc_8 {
//...previous code
public function __construct() {
// Load our meta box containing our loc-8 component
add_action( 'load-post.php', array( $this, 'loc_8_meta_box_setup' ) );
add_action( 'load-post-new.php', array( $this, 'loc_8_meta_box_setup' ) );
// Add our scripts to the Edit Post page
add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
}
//...previous code
// Load our javaScript in admin when edit.php is run
public function admin_scripts( $hook ) {
global $post;
// if we are not in the Edit Post page, we don't need to do this function so leave
if ( 'post.php' !== $hook ) {
return;
}
wp_enqueue_script( 'vuejs', plugins_url( '/js/vendor/vue-@2.1.10.min.js', __FILE__ ),
array(), 1.0.0', true );
wp_enqueue_script( 'leafletjs', plugins_url( '/js/vendor/leaflet@1.0.3/leaflet.js', __FILE__ ), array(), '1.0.0', true );
wp_enqueue_script( 'scripts', plugins_url( '/js/scripts.js', __FILE__ ), array(
'jquery',
'vuejs',
'leafletjs'
), '1.0.0', true );
}
Adding code to give vue component initial values
Let's get WordPress to setup a local JavaScript object that contains the info we need for our vue component. We'll need the location of the post if it has it already. The object also contains our Ajax URL (we will create the AJAX part later) and it has a bunch of initialization strings for our leaflet map. The eventual goal would be to have an options page on the WordPress dashboard that would allow the user to customize these settings. For now, we will still hard code them in. (NOTE: You may need to get your own MapBox API for this to work)
We will get into how to add location to a post using custom fields and how to retrieve them in the next article, but for now just to get this component working, we will hard code in the initial location as well.
Our function will create a PHP array using the same key names as the JavaScript object we had used, then the wp_localize_script will make this a JavaScript variable with the name loc_8_fwp
.
This is what our admin_scripts
function will look like now.
//...previous code
// Load our javaScript in admin when edit.php is run
public function admin_scripts( $hook ) {
global $post;
// if we are not in the Edit Post page, we don't need to do this function so leave
if ( 'post.php' !== $hook ) {
return;
}
wp_enqueue_script( 'vuejs', plugins_url( '/js/vendor/vue-@2.1.10.min.js', __FILE__ ),
array(), 1.0.0', true );
wp_enqueue_script( 'leafletjs', plugins_url( '/js/vendor/leaflet@1.0.3/leaflet.js', __FILE__ ), array(), '1.0.0', true );
wp_enqueue_script( 'scripts', plugins_url( '/js/scripts.js', __FILE__ ), array(
'jquery',
'vuejs',
'leafletjs'
), '1.0.0', true );
$result = [];
$result['lat']= '32.3336368';
$result['long']= '-95.2930722';
$result['address']= '1329 S Beckham Ave';
$result['address2']= '';
$result['city']= 'Tyler';
$result['state']= 'TX';
$result['zip']= '75701';
$result['country']= 'USA';
$local_vars = [];
$local_vars['result'] = $result;
$local_vars['canEdit'] = true;
$local_vars['ajax_url'] = admin_url( 'admin-ajax.php' );
$local_vars['action'] = 'loc_8_geocode';
$local_vars['mapTileLayer'] = 'https://api.mapbox.com/styles/v1/mapbox/streets-v10/tiles/256/{z}/{x}/{y}?access_token={accessToken}';
$local_vars['mapAttribution'] = 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © Mapbox';
$local_vars['mapAccessId'] = 'loc_8_wp';
$local_vars['mapMaxZoom'] = 18;
$local_vars['mapAccessToken'] = 'pk.eyJ1IjoiamVyMGRoIiwiYSI6ImNpeGo3MGRjaTAwNGIyd280ODJ0dzA1bm4ifQ.tFc-Mw0uY6Zf5056W_R5qw';
$local_vars['_ajax_nonce'] = wp_create_nonce( 'loc-8-ajax' );
wp_localize_script( 'scripts', 'loc_8_fwp', $local_vars );
}
Moving the CSS from our Codepen.io to our plugin
We created a css
folder under out plugin folder and copied the css from the codepen.io to a file called style.css
. We will also copy the necessary leaflet.css file as well, but keep this in the same folder as the leaflet.js file for quick replacement when leaflet updates.
Placing the CSS onto our edit page
This is pretty much the same as placing the javascript. We just add the wp_enqueue_style
functions.
//...previous code
// Load our javaScript in admin when edit.php is run
public function admin_scripts( $hook ) {
global $post;
// if we are not in the Edit Post page, we don't need to do this function so leave
if ( 'post.php' !== $hook ) {
return;
}
wp_enqueue_script( 'vuejs', plugins_url( '/js/vendor/vue-@2.1.10.min.js', __FILE__ ),
array(), 1.0.0', true );
wp_enqueue_script( 'leafletjs', plugins_url( '/js/vendor/leaflet@1.0.3/leaflet.js', __FILE__ ), array(), '1.0.0', true );
wp_enqueue_script( 'scripts', plugins_url( '/js/scripts.js', __FILE__ ), array(
'jquery',
'vuejs',
'leafletjs'
), '1.0.0', true );
wp_enqueue_style( 'leafletcss', plugins_url( '/js/vendor/leaflet@1.0.3/leaflet.css', __FILE__ ) );
wp_enqueue_style( 'loc8styles', plugins_url( '/css/style.css', __FILE__ ) );
//...previous code
}
That's the end of this section. We have moved our prototype from Codepen.io and it is now on our Edit Post screen in the WordPress dashboard. In the next article we will add functionality to our WordPress plugin this component will need: Retrieving and saving data from/to WordPress for the vue component. Future articles will implement the Ajax endpoint and the geocode function in the Vue Component.