Need a WordPress website this weekend? Start here...

Thickbox Ajax Form Handling in WordPress

(Reading time: 5 – 8 minutes)

“Code is poetry.”

You’ve probably seen that little epigram floating around the net. If you code, you “get it.” If you don’t code, it’s not hard to understand: whatever intrinsic beauty is latent in a piece of code should be found.

As with poetry, finding that latent beauty is the hard part.

In my Ongoing Quest for World Domination of WordPress recipe formatting, I have plenty of occasion to look for latent beauty.

Lately, that beauty has been lurking in PHP form handling. Specifically, hRecipe provides a spiffy Javascript popup box allowing the WordPress recipe maven a friendly way to enter their recipes for publication on blog posts and pages. This popup box is called a “thickbox” and it’s a component of the nearly ubiquitous jQuery library which ships with every installation of WordPress.

After entering a recipe, it’s easy to send the formatted information directly to a blog post. This is how it’s been done so far, and how the hReview plugin (upon which hRecipe) is based works.

But that’s not good enough. All this recipe data should be in the WordPress database.

PHP vs. Javascript form handling

In general, handling HTML forms is well-understood technology. But the specific details vary enough from platform-to-platform that it’s worth learning new techniques. What follows is a few notes on how to implement form handling using the WordPress Ajax capability.

First the motivation: because of the way thickbox is implemented as a child window of the blog post editor, code for handling the form can be written in the thickbox handler or the class that invokes the thickbox handler.

Which leaves the database out of scope.

Even if you derived a class from the database handler itself, you may still be out of scope with respect to the instance of the current hRecipe class.

Conversely, there’s no easy and elegant way to pass the database handling code into the thickbox handler. The database code is all PHP running on the server, and the thickbox code is mostly Javascript, running in your browser. An ugly problem to be sure.

Succinctly, we want the form data processed such the database is in scope, but the processing is encapsulated within it’s own file.

Enter WordPress.

WordPress Ajax form handling

It turns out that WordPress has an Ajax broker (for lack of a better word) which will pass the form data from the Javascript code to the form handler running on the server. Here’s what that looks like:

1
2
3
4
5
6
7
8
9
$(document).ready(function() {
	$("#hrecipe_form").submit(function() {
		var ajaxurl = "<?php echo admin_url('admin-ajax.php');?>";
		var data = jQuery(this).serialize();
		jQuery.post(ajaxurl, data, function(response) {
    	});
		return false;
	});
});

Simple, right?

Ok, it’s a little more complicated than specifying the action attribute in your form, but I guarantee the tradeoff for power is worth the slight added complexity. Since you’re using Javascript anyway (thickbox), it really isn’t a problem.

Taking it from the top…

  • Line 1: The usual JQuery invocation.
  • Line 2: The id attribute of your form. This should be self-explanatory. If you don’t know what id attributes are, you have some homework to do. In this case, we’re passing an anonymous function into .submit. The usual JQuery way.
  • Line 3: It’s absolutely key to get the admin-ajax.php file included. The methods you need for hooking the WordPress Ajax interface up are in that file. If you implement this, and it doesn’t work, checking for this file should be your first step in debugging.
  • Line 4: This is all of your form data. Every single element. Spiffy!
  • Line 5: The Ajax call. The third argument captures whatever you return from your handler. In this case, I’m choosing not to do anything with the returned data. You could (should) put a Javascript alert box here when you first implement; it’s fun watching this code execute.

And that’s it for the Javascript part.

Now you need to ensure your form has the correct id attribute, and a field for triggering the action handler.

Form data for Ajax

Simple: <form method="post" id="hrecipe_form" action="" >.

You probably don’t need the method attribute, that’s taken care of using Javascript.

Next, add a hidden input field named “action,” like this:
<input type="hidden" name="action" value="thickbox_form" />

Simple, right?

Let’s get the handler installed.

Handling the request with PHP

The cool part is that the PHP side of WordPress won’t know the difference. As far as it’s concerned, it’s $_GET and $_POST as usual. Here’s how to do it.
add_action("wp_ajax_thickbox_form", array ($recipe, 'thickbox_form_handler'));

The key to this action is understanding the wp_ajax tag, which registers the handler given as the second argument to add_action. Nothing new here; even if wp_ajax is new to you, you have seen the pattern before.

Note also that I’m using a class-based design for hRecipe, thus I have to pass add_action the hRecipe class instance ($recipe) where the handler is located. Otherwise, thickbox_form_handler will be out of scope.

The handler code:

103
104
105
function thickbox_form_handler() {
   include ('view/recipe_form.php');
}

The form data is all nicely tucked away into recipe_form.php, which connects to the WordPress database and handles all the messy chores of extracting the values of the form fields.

We’ve solved the problem: recipe_form.php is now in scope, but all it’s ugliness is “under the hood.”

Implementing Ajax in WordPress

If you have arrived here from other pages showing you how to do the same thing, you have probably read that all of this needs to be in the same file. Or perhaps some other limitation must be respected. With all due respect to the authors of other articles, such limitations are artifacts of the main requirement:

Everything must be in scope.

If you have every call and function in scope, it’s as simple as shown here. If this code doesn’t work for you, checking scope should be your first step in debugging. Here’s a checklist:

  1. Ensure your form id matches the Javascript id you’re invoking .submit for.
  2. Check to see that you have an input field named “action” with an appropriate value.
  3. Make sure your add_action is using the same value appended to the wp_ajax tag as you set for your input field with name="action".
  4. Ensure the admin-ajax.php is in your path. This is critical, none of this works without the handlers in that file.

Questions welcome, I’ll do my best to answer.

Comments

  1. angie says:

    Dude, so far over my head! Maybe one day something like that will penetrate this thick skull.

    • Dave Doolin says:

      At the moment, I don’t have anywhere else to put these kinds of articles, and these technical posts do tend to attract search engine traffic.

  2. Patricia says:

    For all the techies out there they will love the post. For the rest of us…..well I look forward to the day my business takes off and I can afford one to do all the techie stuff for me :-)
    You sure write some interesting stuff.
    Patricia Perth Australia
    Patricia´s last post ..Lavender Health-Embracing An Organic Lifestyle