Setup

WordPress Ajax Autocomplete works essentially the same as it does when you are creating a site from scratch. You create a list of terms in JSON format and provide those as a source. There are two main differences with WordPress Ajax Autocomplete and building from scratch:

  1. For the source instead of linking a file you localize a script. What that means is WordPress creates an Object with the values listed and writes it directly in the HTML about the script that requires it. If you are confused, see the image above.
  2. For the Ajax call you don’t create a custom page. Instead you make a post request to the admin-ajax.php file which is located inside of the wp-admin directory.

The code for this tutorial can be downloaded from GitHub here.

Alright, let’s get to it!

In this tutorial we will create a custom post type called bands. Each band will have a custom meta field for the guitarist, singer, bass player and drummer. When a user visits our band page and starts typing musicians our application will pull from the custom meta fields of each post using WordPress Ajax Autocomplete. When a selection is made, the page will display the content of the custom post type which will be a Bootstrap 3 panel. This tutorial makes use of jQuery for Ajax.┬áBecause we are using the panels we will need a theme that supports Bootstrap3. Download the theme ‘Echo Magazine‘ and activate it.

Open your IDE of choice (I recommend PHPStorm) and navigate to the plugins directory (wp-content/plugins). Create a new directory called ‘bands’. Inside of that directory create a file called bands.php.

Creating the Custom Post Type

Let’s create the custom post type. In your bands.php file paste in the following code

<?php
/*
* Plugin Name: Heady Bands
* Description: Creates a custom post type 'bands' with meta fields and an Ajax autocomplete field.
* Version: 1.0
* Author: Brian Abbott
* Author URI: http://brianabbott.com
*/

Go to the plugins page on your WP admin. You should see the plugin ‘Heady Bands’ listed as a plugin. Go ahead and activate it.

After that enter the following code on bands.php.

//////// Create Bands Custom Post
function heady_bands_custom_post() {
$labels = array(
'name'               => _x( 'Bands', 'post type general name' ),
'singular_name'      => _x( 'Band', 'post type singular name' ),
'add_new'            => _x( 'Add New Band', 'Group' ),
'add_new_item'       => __( 'Add New Band' ),
'edit_item'          => __( 'Edit Band' ),
'new_item'           => __( 'New Band' ),
'all_items'          => __( 'All Bands' ),
'view_item'          => __( 'View Band' ),
'search_items'       => __( 'Search Bands' ),
'not_found'          => __( 'No Bands found' ),
'not_found_in_trash' => __( 'No Bands found in the Trash' ),
'parent_item_colon'  => '',
'menu_name'          => 'Bands'
);
$args = array(
'labels'        => $labels,
'description'   => 'Menu area to add Bands',
'public'        => true,
'publicly_queryable' => true,
'menu_position' => 35,
'menu_icon'     => 'dashicons-format-audio',
'supports'      => array( 'title', 'thumbnail', 'page-attributes', 'editor' ),
'has_archive'   => false,
'show_in_rest' => false
);

register_post_type( 'bands', $args );
}
add_action( 'init', 'heady_bands_custom_post' );

This should create a custom post type called ‘Bands’. You will need to flush your permalinks to use this post type. Go to settings > permalinks and click save.

WordPress custom post type
We have now created a custom post type called bands.

Populating Data

Let’s fill out the information. I’ve written some HTML in a text document. Follow the instructions and make sure to paste the HTML into the ‘text’ section of your editor. When you are done push publish.

WordPress editor without styles.
The editor is not displaying the Bootstrap CSS while you edit. We’re going to fix this.

The editor is not showing the Bootstrap panel styles, we want to display the styles in the editor. To begin with I’ve added the styles to a CSS file you can download here. Add this file to the ‘bands’ directory you created. Next, in your bands.php page enter the following:

//////// Adds Panel Styles to the Editor
function rates_editor_style($mce_css) {
	$mce_css .= ', ' . plugins_url( 'custom-editor-style.css', __FILE__ );
	return $mce_css;
}

add_action( 'mce_css', 'rates_editor_style' );
WP Custom post type with styles
The editor is now displaying the styles.

Next we need to add Custom Meta Fields.

Custom Meta Fields

Custom meta fields are versatile. You can take any form input and store data with that post. They can also be repeatable which is useful for some situations. We will be using text inputs. We will have an input for guitarist, singer, bassist and drummer and we will use these values in our Ajax Autocomplete text field. When one of these is selected we will display the content of the custom post (the Bootstrap panel) that corresponds with the custom meta field.

To add a meta box you use the ‘add_meta_boxes’ filter. Paste the following on your bands.php file

function heady_bands_musicians_meta_box() {
	add_meta_box(
		'musicians', // id
		'Musicians', // title
		'heady_bands_fields', // callback
		'bands', // screen
		'normal', // $context
		'high' // $priority
	);
}
add_action( 'add_meta_boxes', 'heady_bands_musicians_meta_box' );

Now we will create the callback function

function heady_bands_fields() {
   global $post;
   $meta_guitarist = get_post_meta( $post->ID, 'guitarist', true );
   $meta_bassist = get_post_meta( $post->ID, 'bassist', true );
   $meta_singer = get_post_meta( $post->ID, 'singer', true );
   $meta_drummer = get_post_meta( $post->ID, 'drummer', true ); ?>

   <input type="hidden" name="your_meta_box_nonce" value="<?php echo wp_create_nonce( basename(__FILE__) ); ?>">

    <p>
        <label for="guitarist">Guitarist</label>
        <br>
        <input type="text" name="guitarist" id="guitarist" class="guitarist" value="<?php echo $meta_guitarist; ?>">
    </p>
    <p>
        <label for="bassist">Bassist</label>
        <br>
        <input type="bassist" name="bassist" id="bassist" class="regular-text" value="<?php echo $meta_bassist; ?>">
    </p>
    <p>
        <label for="singer">Singer</label>
        <br>
        <input type="text" name="singer" id="singer" class="regular-text" value="<?php echo $meta_singer; ?>">
    </p>
    <p>
        <label for="drummer">Drummer</label>
        <br>
        <input type="text" name="drummer" id="drummer" class="regular-text" value="<?php echo $meta_drummer; ?>">
    </p>

<?php }

Next we will create a function to save the custom meta fields.

function save_your_fields_meta( $post_id ) {
   // verify nonce
   if ( !wp_verify_nonce( $_POST['your_meta_box_nonce'], basename(__FILE__) ) ) {
      return $post_id;
   }
   // check autosave
   if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
      return $post_id;
   }
   // check permissions
   if ( 'bands' === $_POST['post_type'] ) {
      if ( !current_user_can( 'edit_page', $post_id ) ) {
         return $post_id;
      } elseif ( !current_user_can( 'edit_post', $post_id ) ) {
         return $post_id;
      }
   }

   $guitarist = $_POST['guitarist'];
   $singer = $_POST['singer'];
   $bassist = $_POST['bassist'];
   $drummer = $_POST['drummer'];

      update_post_meta( $post_id, 'guitarist', $guitarist );
      update_post_meta( $post_id, 'singer', $singer );
      update_post_meta( $post_id, 'bassist', $bassist );
      update_post_meta( $post_id, 'drummer', $drummer );

}
add_action( 'save_post', 'save_your_fields_meta' );

Add each of the members from the custom post text to the meta fields. Once you have filled out the fields you are ready for the final step.

custom meta fields
Custom Meta Fields that have been completed.

WordPress Ajax Autocomplete

We have created a custom post type and completed a few of these with some HTML. We added some custom meta fields and completed these. The custom meta fields will be used as the autocomplete suggestions. When a user searches on a form they will be given the meta fields as suggestions. When they select one, the page will use Ajax to load the content of the custom post type.

To accomplish this we need to do is enqueue scripts. We will be using our own versions of jQuery and jQuery-ui due to compatibility issues.

After that we have to localize the autocomplete suggestions. The reason we are doing this is because WordPress uses Apache mod rewrite. Instead of linking to a URL that generates the JSON we will paste it in the body of the HTML as a JavaScript variable. This will give our script access to the JSON.

Let’s start by creating the function that will generate the JSON that will be used by the autocomplete.

function bands_generate_selections() {
   $json_array = array();
   $args = array( 'post_type' => 'bands', 'posts_per_page' => 100 );
   $loop = new WP_Query( $args );
   while ( $loop->have_posts() ) : $loop->the_post();
      $guitarist = get_post_meta($loop->post->ID, 'guitarist', true);
         $array = array('label' => $guitarist, 'value' => $loop->post->ID);
         $json_array[] = $array;
      $singer = get_post_meta($loop->post->ID, 'singer', true);
         $array = array('label' => $singer, 'value' => $loop->post->ID);
         $json_array[] = $array;
      $bassist = get_post_meta($loop->post->ID, 'bassist', true);
         $array = array('label' => $bassist, 'value' => $loop->post->ID);
         $json_array[] = $array;
      $drummer = get_post_meta($loop->post->ID, 'drummer', true);
         $array = array('label' => $drummer, 'value' => $loop->post->ID);
   endwhile;
   $json_data = json_encode($json_array);
   return $json_data;
}

Next we will create a file called ‘bands.js’ inside of our bands directory.

After that we will create a file to enqueue our JavaScript and CSS files.

function bands_enqeue_scripts() {
   wp_register_style('jquery-ui-style', 'https://code.jquery.com/ui/1.12.0/themes/smoothness/jquery-ui.css');
   wp_enqueue_style('jquery-ui-style');
   wp_deregister_script( 'jquery' );
   wp_register_script( 'jquery', 'https://code.jquery.com/jquery-3.3.1.min.js', null, '3.3.1', true);
   wp_enqueue_script('jquery');
   wp_register_script('jquery-ui', 'https://code.jquery.com/ui/1.12.1/jquery-ui.min.js', 'jquery', '1.12.1', true);
   wp_enqueue_script('jquery-ui');
   wp_enqueue_script( 'bands', plugin_dir_url( __FILE__ ) . 'bands.js',array('jquery', 'jquery-ui'), '1.0', true );
   $bands_autocomplete = bands_generate_selections();
   wp_localize_script('bands', 'band_members', array('autocomplete' => $bands_autocomplete ) );
}
add_action('wp_enqueue_scripts', 'bands_enqeue_scripts');

If you’ve done everything correctly, you should be able to load a web page, view the source, and see the JSON in the source.

The JSON inside of the HTML docucment.
The JSON inside of the HTML docucment.

The next thing we will do is create a function that will configure WP for our Ajax call. WordPress has a dedicated file for Ajax and we need to configure it with a hook.

function bands_ajax_listing() {
   $args = array(
      'p'         => $_POST['id'], // ID of a page, post, or custom type
      'post_type' => 'any'
   );
   $loop = new WP_Query( $args );
   while ( $loop->have_posts() ) : $loop->the_post();
      $post = the_content();
   endwhile;

   echo $post;

   die(); //stop "0" from being output
}

add_action('wp_ajax_get_listing_names', 'bands_ajax_listing');

Now we are almost done, we just need to create the jQuery for the bands.js file, and add some HTML.

Let’s start by adding some HTML. Create a new page called bands. Inside of your text editor add this (as text not visual)

<input id="bands-input" class="float-left" name="bands-input" size="29" type="text" placeholder="Search by band members" >
<div class="bands"
<div id="bands" class="text-center">Please make a selection.</div>
</div>

Finally add this to your bands.js file

$(function() {
    let band_id;
    let autocomplete_terms = JSON.parse( band_members.autocomplete );
    $('#bands-input').autocomplete({
        source: autocomplete_terms,
        minLength: 1,
        select: function( event, ui ) {
            band_id = ui.item.value;
            if (event.type === 'click')
                band_id = ui.item.value;
            $.ajax({
                type: "POST",
                url: '/wp-admin/admin-ajax.php',
                data: 'action=get_listing_names&id='+band_id,
                success: function(data) {
                    $('#bands').html(data);
                }

            });
        },
    });
});

That’s it. You should now have a working WordPress Ajax Autocomplete.

The suggestions are added by jQuery autocomplete
The suggestions are added by jQuery autocomplete
WordPress uses Ajax to dynamically render the post content into the page.
WordPress uses Ajax to dynamically render the post content into the page.

Published by burnedfaceless

Brian Abbott is studying IT and Music Composition at Georgia Southern University.

Leave a comment

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