Form submission with Ajax is a powerful technique that provides a way to send web forms without reloading the browser window. The jQuery library lets you take Ajax form submission a step farther by providing a way to quickly and easily produce Ajax-enabled web forms with minimal code. In this article, learn how to create basic Ajax form submissions with jQuery before discovering how to use this technique to authenticate a user. The article then demonstrates user registration techniques with Ajax using jQuery, such as checking for user name availability and suggesting user names when a chosen user name is already taken. Neither technique requires form submission or page reloads.
If you're not familiar with jQuery, it's essentially a JavaScript library that makes JavaScript development easier. It minimizes the code you need to write, because it has many built-in features that you would otherwise need to write custom functions or objects for. For more information and a link to download the jQuery library, see Resources; or, as you'll see in all the sample code, you can embed the current version of the jQuery library directly.
Submitting a form without reloading the browser can be useful in a number of
scenarios. For example, you can use it to validate form fields with JavaScript
code before submitting the form, to submit a form in a one-page web application,
or—as this article shows—to determine whether a user name
already exists during user registration. There are two ways to trigger a form
submission using jQuery: using the submit handler
or the click handler. Listing 1
shows how to submit a form using the submit handler.
Listing 1. Form submission with jQuery’s submit handler
<script type="text/javascript" src="http://code.jquery.com/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#submitForm').submit(function(e) {
alert($('#sample').attr('value'));
return e.preventDefault();
});
});
</script>
<form id="submitForm" method="post">
<input type="text" name="sample" id="sample" value="Enter something" />
<input type="submit" id="submitBtn" value="Submit" />
</form>
|
Listing 2 shows how to submit a form using the
click handler.
Listing 2. Form submission with jQuery’s click handler
<script type="text/javascript"
src="http://code.jquery.com/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#submitBtn').click(function(e) {
alert($('#sample').attr('value'));
return e.preventDefault();
});
});
</script>
<form id="submitForm" method="post">
<input type="text" name="sample" id="sample" value="Enter something" />
<input type="submit" id="submitBtn" value="Submit" />
</form>
|
These two listings are nearly identical: They both embed the jQuery library, use
the ready handler to ensure that the page is
loaded before trying to access any elements, and include the same code
within their handler functions. The only difference between the two is the
handler and the element that the handler is assigned to. The
submit handler needs to be assigned to a form
element, while the click handler can be assigned to
any element that can be clicked—in this case, the Submit
button. To prevent the form submission from refreshing the page, you must use
the preventDefault function. To access the
preventDefault function, you must pass the handler
event through as a parameter and use it to access the function.
Although both of the above options are valid, the submit
handler is more commonly used. However, in some cases, you may have more
than one Submit button, which would require a
click handler on each button. Listing 3
shows a scenario in which using the click handler is
necessary, because two Submit buttons can trigger the form
submission.
Listing 3. Form submission with two submit buttons
<script type="text/javascript"
src="http://code.jquery.com/jquery.js"></script>
<script type="text/javascript" src="register.js"></script>
<div id="container">
<div id="message"></div>
<form method="post" id="mainform">
<label for="username">Username</label>
<input type="text" name="username" id="username" value="" />
<label for="password">Password</label>
<input type="password" name="password" value="" />
<input type="submit" name="action" id="login" value="Log in" />
<h2>Extra options (registration only)</h2>
<label for="firstname">First name</label>
<input type="text" name="firstname" value="" />
<label for="lastname">Last name</label>
<input type="text" name="lastname" value="" />
<label for="email">Email</label>
<input type="text" name="email" value="" />
<input type="submit" name="action" id="register" value="Register" />
</form>
</div>
|
In this example, notice that multiple actions can be taken with this one form: An
existing user can sign in, and a new user can register by entering additional
account information. Using a submit handler on the
form wouldn't work in this scenario because it would not be possible to determine
which button triggered the form submission. Therefore, Listing 4
uses the click handler for each button to determine
what action to take so that you can then process the data accordingly.
Listing 4. Click handlers for the submit buttons in register.js
$(document).ready(function() {
$("#register, #login").click(function(e) {
var name = ($(event.target).attr('id') == 'register') ? 'Registration' : 'Login';
return e.preventDefault();
});
});
|
When the document is ready, you assign the click handler
to the Register and Login buttons. The
click handler receives a parameter, which has been
named e (for event). This event object
is later used to prevent default form submission, as in the earlier code listings.
When the click handler is invoked, the ID of the
current element being clicked is accessed and used to determine whether this is
going to be a user logging in or a new registration.
Now that you know how to submit forms using jQuery, take a look at how to authenticate a user using Ajax with jQuery and PHP.
Registering and authenticating a user using Ajax with jQuery
To authenticate and register a user, you need a server-side language and a database. In this article, PHP will be the server-side language and MySQL will be the database, although you don't need to use any specific server-side language or database to create this function.
You begin by writing additional code in the JavaScript file that sends the form post
using Ajax to a PHP file. The code in Listing 5 starts similarly
to Listing 4, as it includes the ready
handler and the click handlers for the buttons, and it
determines which button was clicked. You then use the slideUp
function to close the message element if it is open already. The Ajax
call may not be apparent at first glance, especially if you're used to creating Ajax
calls without jQuery. Because you're using a shorthand function to send the call,
there isn't even any mention of Ajax in the code.
Listing 5. Submitting a web form using Ajax with jQuery
$(document).ready(function() {
$("#register, #login").click(function(e) {
var name = ($(event.target).attr('id') == 'register') ? 'Registration' : 'Login';
$('#message').slideUp('fast');
$.post('service.php', $('#mainform').serialize()
+'&action='+ $(event.target).attr('id'), function(data) {
var code = $(data)[0].nodeName.toLowerCase();
$('#message').removeClass('error');
$('#message').removeClass('success');
$('#message').addClass(code);
if(code == 'success') {
$('#message').html(name + ' was successful.');
}
else if(code == 'error') {
$('#message').html('An error occurred, please try again.');
}
$('#message').slideDown('fast');
});
return e.preventDefault();
});
});
|
The post function is a shorthand function equivalent to
the code in Listing 6. It takes the file path to the file being
requested, the serialized form data, and finally a callback function. Serializing the
form data is easy with jQuery: You simply access the form
element and call the serialize function to get a
standard query string. The callback function first determines whether the call was
a success or a failure by accessing the first node in the response: The PHP file
returns this result as a node named success or error. After the status
has been determined, you remove any classes that may have been left on the
message element from a previous form submission,
then add a class that corresponds to the success of the response. The
message element is appended with HTML that states
the success or error message, and you open the message
using jQuery’s slideDown function.
Listing 6. jQuery Ajax function
$.ajax({
type: 'POST',
url: url,
data: data,
success: success
dataType: dataType
});
|
Before you create the PHP file that will interact with the database, you need to set
up the database that you plan on saving new users to and selecting existing users
from. Listing 7 includes the SQL code you need to create
the MySQL table named ibm_user_auth. It includes an ID, user name,
password, first name, last name, and email address. The ID is set to auto-increment
and is used as the primary key. The other values are all tinytext
except for the password, which is set to varchar(32),
because you'll use it later to save a Message-Digest algorithm 5 (MD5)-encrypted
value.
Listing 7. SQL code to create a MySQL database table for users
CREATE TABLE `ibm_user_auth` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` tinytext NOT NULL, `password` varchar(32) NOT NULL, `firstname` tinytext NOT NULL, `lastname` tinytext NOT NULL, `email` tinytext NOT NULL, PRIMARY KEY (`id`) ); |
After the table is set up, you can start writing the PHP code that will be used to
interact with the database. You'll call this file—named service.php—in
your Ajax post function. Listing 8
shows the code that makes up this file. It starts by defining database connection
variables. After the database information is set, be sure that a user name and
password were passed through the form post; if so, you extract the post data
and connect to the database. Now that you're connected to the database, you
need to determine whether to attempt to use the post data to log in an existing
user or register him or her as a new user. You can make this determination
simply by checking the action variable that was
extracted from the post data and sent by the Ajax form post.
If you determine that this is a new-user registration, you also want to be sure that the first name, last name, and email address have been sent. Otherwise, you'll simply get an error. When all the requirements are met, make sure that the user name does not already exist in the database. If it does, you return an error. Otherwise, move on to validate the email address, insert the new-user data into the database, and return a success message.
If you determine that this is an existing user attempting to log in, make sure the user exists in the database. If so, save the user's data to a session, and return a success message.
Listing 8. The server-side PHP code that interacts with the JavaScript code and the database
// Database connection values
define('DB_HOST', 'localhost');
define('DB_USERNAME', 'YOUR_USERNAME');
define('DB_PASSWORD', 'YOUR_PASSWORD');
define('DB_NAME', 'YOUR_DB_NAME');
if(isset($_POST['username'], $_POST['password'])) {
extract($_POST);
$db = mysql_connect(DB_HOST, DB_USERNAME, DB_PASSWORD);
mysql_select_db(DB_NAME, $db);
if($action == 'register'
&& isset($_POST['firstname'], $_POST['lastname'], $_POST['email'])) {
// Verify that the username is unique
$query = mysql_query("select count(id)
from ibm_user_auth where username='$username'");
$result = mysql_fetch_row($query);
if ( $result[0] > 0 ) {
die("<error id='0' />");
}
// Validate email
if( !preg_match("^[a-z0-9,!#\$%&'\*\+/=\?\^_`\{\|}~-]+(\.[a-z0-9,!#\$%&
'\*\+/=\?\^_`\{\|}~-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*\.([a-z]{2,})$^",
$_POST['email']) ) {
die("<error id='1' />");
}
mysql_query("insert into ibm_user_auth
(username, password, firstname, lastname, email)
VALUES ('$username', MD5('$password'), '$firstname', '$lastname', '$email')");
die("<success />");
}
else if($action == 'login') {
$query = mysql_query("select count(id) from ibm_user_auth where
username='$username' and password=md5('$password')");
$result = mysql_fetch_row($query);
if($result[0] == 1) {
session_start();
$_SESSION['username'] = $username;
die("<success />");
}
else die("<error id='2' />");
}
}
?>
|
Now that you've got the essentials working, it's probably a good idea to consider
usability. The biggest issue with this code is that you're not telling the user
what went wrong if an error occurs. However, you probably noticed that each error
response includes an id attribute. The next section
shows how to use these values to write an error response for each scenario in
addition to suggesting user names during registration.
Handling errors and suggesting user names during registration
Handling errors with the code already covered is fairly easy at this point, especially because you're already returning errors with specific IDs that point to the problem. You already have the IDs set up, so begin by adding the PHP code that suggests user names before getting back into the JavaScript code. Listing 9 provides an example of how to create user name suggestions based on user-submitted data—in this case, the first and last names.
Listing 9. Creating user name suggestions using user-submitted data
// Database connection values
define('DB_HOST', 'localhost');
define('DB_USERNAME', 'YOUR_USERNAME');
define('DB_PASSWORD', 'YOUR_PASSWORD');
define('DB_NAME', 'YOUR_DB_NAME');
if(isset($_POST['username'], $_POST['password'])) {
extract($_POST);
$db = mysql_connect(DB_HOST, DB_USERNAME, DB_PASSWORD);
mysql_select_db(DB_NAME, $db);
if($action == 'register'
&& isset($_POST['firstname'], $_POST['lastname'], $_POST['email'])) {
// Verify that the username is unique
$query = mysql_query("select count(id)
from ibm_user_auth where username='$username'");
$result = mysql_fetch_row($query);
if ( $result[0] > 0 ) {
$out = "<error id='0'><suggestions>";
$out .= "<suggestion>" . $firstname . $lastname . "</suggestion>";
$out .= "<suggestion>" . $firstname . "_" . $lastname . "</suggestion>";
$out .= "<suggestion>" . $lastname . $firstname . "</suggestion>";
$out .= "<suggestion>" . $lastname . "_" . $firstname . "</suggestion>";
$out .= "</suggestions></result>";
die($out);
}
// Validate email
if( !preg_match("^[a-z0-9,!#\$%&'\*\+/=\?\^_`\{\|}~-]+(\.[a-z0-9,!#\$%&
'\*\+/=\?\^_`\{\|}~-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*\.([a-z]{2,})$^",
$_POST['email']) ) {
die("<error id='1' />");
}
mysql_query("insert into ibm_user_auth
(username, password, firstname, lastname, email)
VALUES ('$username', MD5('$password'), '$firstname', '$lastname', '$email')");
die("<success />");
}
else if($action == 'login') {
$query = mysql_query("select count(id) from ibm_user_auth
where username='$username'
and password=md5('$password')");
$result = mysql_fetch_row($query);
if($result[0] == 1) {
session_start();
$_SESSION['username'] = $username;
die("<success />");
}
else die("<error id='2' />");
}
}
?>
|
Notice that now when a user name already exists during registration, you create an XML structure that includes various combinations of user-submitted data that make up suggested user names. You could even take this a step farther by ensuring that suggestions don't exist in the database before returning them.
Listing 10 shows how you handle displaying the suggested names using jQuery.
Listing 10. Displaying suggested user names using jQuery
$(document).ready(function() {
$("#register, #login").click(function(e) {
var name = ($(event.target).attr('id') == 'register') ? 'Registration' : 'Login';
$('#message').slideUp('fast');
$.post('service.php',
$('#mainform').serialize() +'&action='+ $(event.target).attr('id'),
function(data) {
var code = $(data)[0].nodeName.toLowerCase();
$('#message').removeClass('error');
$('#message').removeClass('success');
$('#message').addClass(code);
if(code == 'success') {
$('#message').html(name + ' was successful.');
}
else if(code == 'error') {
var id = parseInt($(data).attr('id'));
switch(id) {
case 0:
$('#message').html('This user name has already been taken.
Try some of these suggestions: |
Now, when an error is returned, you check for the error ID rather than simply displaying a default error message that isn't helpful to the user. First, you parse the ID from the XML structure returned from PHP, then you use a switch statement to direct the error to the appropriate message or associated code. The first error ID is for when a user name already exists in the system. This is where you access the suggested user names and display them for the user to choose a new name. Start by accessing the suggestions nodes and iterating through each one. During iteration, you create a radio button and a label that includes the suggestion, then you append it to a custom error message and display it to the user. At this point, the user can choose a suggested name, which will automatically be added to the user name text input, and then proceed with registration.
The next error ID is for invalid email addresses. The associated code simply displays a custom error message telling the user what went wrong. You could even add a line of code to highlight the incorrect field. Next is a custom error message for failed logins. The code uses a message that is more ambiguous in this case, because for security reasons you don't want to tell just anyone which field was incorrect. Finally, the default message is the same message you displayed in Listing 5. This message will most likely never be used, but it's good to have as a fall-back.
User authentication with Ajax is becoming increasingly more common and is almost a requirement for single-page web applications. It's also extremely beneficial for suggesting user names, as you did in this article, because it gives a user false hope when a page is submitted, only to refresh with error messages. This way, responses are more automatic and user friendly, providing a more usable web experience.
| Description | Name | Size | Download method |
|---|---|---|---|
| Sample Ajax scripts used in this article | AjaxUserAuthentication.zip | 5KB | HTTP |
Information about download methods
Learn
-
Learn more about jQuery's philosophy, features, and functions in
"Simplify
Ajax development with jQuery" (developerWorks, April 2007).
-
Learn more about Ajax programming in the
Ajax resource center.
-
Find more information about the jQuery library at the jQuery
site.
-
Web development zone: The
developerWorks Web development zone specializes in articles covering various
web-based solutions.
-
IBM
technical events and webcasts: Stay current with developerWorks' technical
events and webcasts.
-
developerWorks on-demand
demos: Watch demos ranging from product installation and setup for beginners
to advanced functionality for experienced developers.
Get products and technologies
-
Directly embed the current version of the jQuery library from the
jQuery site.
-
Download IBM product evaluation
versions or explore
the online trials in the IBM SOA Sandbox and get your hands on application
development tools and middleware products from DB2®, Lotus®, Rational®,
Tivoli®, and WebSphere®.
Discuss
- Create your My developerWorks profile today and set up a watchlist on Ajax or jQuery.
Get connected and stay connected with My developerWorks.
- Find other developerWorks members interested in web development.
- Share what you know: Join one of our developerWorks groups focused on web topics.
- Roland Barcia talks about Web 2.0 and middleware in his blog.
- Follow developerWorks' members' shared bookmarks on web topics.
- Get answers quickly: Visit the Web 2.0 Apps forum.
- Get answers quickly: Visit the Ajax forum.

Kris Hadlock has been a contract web developer and designer since 1996. He has worked on projects for companies such as SPIN Magazine, IKEA, United Airlines, JP Morgan Chase, GoDaddy Software, and Fire Mountain Gems. He is the author of Ajax for Web Application Developers (Sams) and The ActionScript Migration Guide (New Riders) as well as a featured columnist and writer for numerous websites and design magazines, including Peachpit.com, InformIT.com, and Practical Web Design magazine. Kris is also the founder of www.studiosedition.com, a web design and software development studio specializing in fusion of form and function.




