Autocomplete with AJAX in WordPress

Autocomplete with AJAX in WordPress: 2019

David Nash code, tutorial, wordpress Leave a Comment

This is the second part of Create an autocomplete field in WordPress: 2019, which works well if you don’t have that many options. If you have less than 10 options, use a select element. Less than 100-1000 (depending), you don’t need AJAX. If you have more than 100-1000, you’ll probably need to use autocomplete with AJAX.

This means the page will load faster, and we’ll limit the data to entries that more closely match what the user is looking for.

We didn’t even need Javascript for the previous part. What we’re doing now is a bit more complex, so we’ll need it now. I’m not going to use jQuery, and I recommend you stop using it too. If you know jQuery then Plain Javascript is a great site to help you with the transition.

I’ve created a branch of the wp-autocomplete theme on github, and again will link to the commits for each step. And continuing in the theme of making small, easy steps, let’s get started with the first one!

Let’s look at the Awesomplete documentation

Fortunately Awesomplete provides an example of how to implement autocomplete with AJAX, which is so short I’ll show it here:

Looks pretty straight-forward. We can use that, and just update the URL and the input selector to match our page.

In order to run that code, we need a couple of things:

  1. Update our theme to run the Javascript, which we’ll copy and paste from the example
  2. Set up an AJAX endpoint function so that our theme returns some data for Awesomplete
  3. Modify the above function so that what we see come from our WordPress database

Load custom javascript

This is pretty simple, but it’s our first step towards our goal of autocomplete with AJAX.

So let’s create the js directory within the theme, and then within that a file called wp-autocomplete.js. And then we’ll edit functions.php to tell our theme to load that javascript file.

And in wp-autocomplete.js, we’ll just have it output a message to the developer console:

Let’s refresh the page to make sure it does… and success!

You can see the changes in this commit on github.

Clean up index.php and do a basic autocomplete without AJAX

We can strip index.php down to the following very simple code:

Simple is good! Much less that can go wrong. But then we’ll update the javascript to look like this:

Now when we reload the page we should still see our “loaded” message, and then when we test out the autocomplete field, we should see this:

Autocomplete in WordPress - using Javascript but not AJAX, yet
Autocomplete without AJAX

Have a look at the code changes with this github commit.

Autocomplete with AJAX (but not our own data)

Now that this is working, let’s jump back to the Awesomplete AJAX demo and update our javascript so that it looks like this:

I’ve made a couple of changes from the demo code they supply. I’ve changed their querySelector() to getElementById() and used the ID of our input field element. And because I thought it was fun I changed the language from fr (French) to en (English). Also, having more results makes for a better screenshot:

Autocomplete with AJAX
Autocomplete with AJAX – but not our data

Sweet! And here’s the github commit showing the code changes for this step. Next we’ll take a bit of a sideways step and get WordPress to respond to AJAX requests.

Set up our theme to handle AJAX requests

When we want to build something up, sometimes it means knocking things down. So let’s forget about Awesomplete for the moment.

First, let’s look at functions.php. We can leave the Awesomplete style and script enqueue stuff, because we don’t mind if that’s loaded. But we need a way of telling our theme JS file where WordPress’s AJAX URL is. So we add this code inside add_theme_scripts():

Next we need to add our AJAX function inside functions.php:

To break it down, starting from add_action() at the bottom:

When admin-ajax.php receives a request with action=autocomplete_data, it calls get_autocomplete() in functions.php. The wp_ajax_ and wp_ajax_nopriv_ hooks mean that it’ll work whether or not the user is logged in as an admin user.

I know, this is still really confusing. Bear with me. It’s just one of those bits of WordPress that’s hard to understand.

Then, in our get_autocomplete() function, we just want to send back whatever it was that we received from some other POST variable. I’ve called it user_input.

We’re still in a state where we can’t see if this works yet, so let’s take a deep breath and move on to the next step.

Simple WordPress AJAX javascript

Let’s totally change our existing js/wp-autocomplete.js script, so that it looks like this:

Open the web developer console, and first you should see this:

ajax_url: http://wp-autocomplete.localhost/wp-admin/admin-ajax.php

And on the next line you should see this:

this is a test

Here’s the commit for these changes.

I encourage you to play around with this. Change the “this is a test” text and you should see the same text sent back to you. In functions.php you could also have get_autocomplete() do something other than just echo the text – maybe try this instead:

echo strtoupper( $_POST['user_input'] );

Whatever you do, just make one change at a time and reload your page to make sure it works. If it does, try to work out why it broke. If it doesn’t, make another change!

Let’s get more complex and get data from the field

Now we’ll be a bit more interactive. Let’s add an event listener so that when our input field changes, we then make the AJAX request.

Here’s get_autocomplete() in our functions.php file:

And what we’re saying above is “if the user has inputted something, return the array”. I’ve used ‘aa’ at the start of each so that we can type ‘aa’ into our autocomplete field and get some results.

I needed to write a bit of code to get XMLHttpRequest() working, and now I think I should have gone with the simpler Fetch API. Fetch is now supported in all major browsers except Internet Explorer, and we could use a polyfill for the ~2.5% of IE holdouts. But I digress…

Hopefully it’s commented well enough for you to get an idea of what’s going on here. And here’s the commit for these updates.

Let’s get some data from the dang database already!

We’re almost there! Let’s get our autocomplete values from the database. Our javascript doesn’t need to be changed. And here’s our get_autocomplete() in functions.php:

I’ve provided three options for the MySQL like statement, and used the one that most people are most likely to want – searching for the user’s input anywhere in the post title string. We’re only using one, $input_contains.

To give you more flexibility, I’ve used an SQL statement. This could be applied to any database table. If we were really looking for posts, it’d be better to use native WordPress functions for that.

Have a look at the new code in this commit.

This is all very exciting to see it working, but it doesn’t really do anything. When the user clicks a title, nothing happens. Let’s fix that.

Trigger an event on autocomplete item click

After lots of build-up, here’s what you came for. At the moment we’re just sending labels to awesomplete via AJAX. Let’s also send the post’s URL for each result.

At the end of the Basic Usage section of the Awesomplete documentation, it show us how to send label/value pairs. We’ll keep the post name as the label, and then use the post URL for the value.

But instead of replacing the input field with the key, we’ll override that so that clicking on a suggestion will act as if we clicked a link.

In functions.php we modify the results loop to look like this (and change the $post_titles variable to $post_data so it more accurately reflects what it contains):

Then in our javascript we add the following, so that instead of putting the value into the input field, it redirects the browser:

Here’s the changes for this step. Please note I realised that I’d spelt the library as “Awesomeplete”, but the correct spelling is “Awesomplete” (without the ‘e’) and I’ve fixed that too.

I’ve also updated our simple index.php to show the title of the page that we’re currently on.

Here’s the commit on github. And here’s the finished result:

Autocomplete with AJAX: Conclusion

Creating something you’ve never done before can be complex. But if we take it in small, simple steps, that complexity is greatly reduced. There’s still the odd bit of frustration. I went through it myself while creating this post. But if you just do a little bit at a time, and verify each step along the way, you take one big problem and turn it into lots of little ones.

I hope you’ve enjoyed this post. I’ve stuck with native Javascript, but I suspect a lot of WordPress developers are still much more comfortable with jQuery.

Would you like to see something like this in jQuery? Is there something I missed here? Is there anything you’d like to add? Please let me know in the comments!

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.