Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Ajax and XML: Ajax for forms

Use Ajax techniques to create input forms

Jack D Herrington (jherr@pobox.com), Senior Software Engineer, Leverage Software Inc.
Jack D. Herrington is a senior software engineer with more than 20 years of experience. He's the author of three books: Code Generation in Action, Podcasting Hacks, and PHP Hacks. He has also written more than 30 articles. You can reach Jack at jherr@pobox.com.

Summary:  Augmenting your HTML forms with Asynchronous JavaScript™ + XML (Ajax) callbacks to the server is a practical way to add Web 2.0 functionality to your application. Discover a variety of techniques to add Ajax code and enhance the user experience for PHP applications.

View more content in this series

Date:  22 Jan 2008
Level:  Intermediate
Also available in:   Chinese  Russian  Japanese  Vietnamese

Activity:  47398 views
Comments:  

When you think about Web 2.0 applications, often the most glamorous of them come to mind: the video of YouTube, the über-cool scrolling map of Google Maps, the geo-location functionality in Flikr. Often overlooked in such sites, however, is the humble HTML form that has undergone a big transformation with the popularization of Ajax technology.

In this article, I show you how to use the Prototype.js JavaScript library to solve common user experience problems as you augment forms with Ajax code.

Simple Ajax form submission

Start with something really simple: a multi-field registration form that you want to submit with Ajax instead of using the regular Web form posting path. This simple forms page is shown in Listing 1.


Listing 1. index.html
                
<html>
<head>
<script src="prototype.js"></script>
</head>
<body>
<form id="myform">
<table>
  <tr><td>First</td><td><input type="text" name="first"></td></tr>
  <tr><td>Last</td><td><input type="text" name="last"></td></tr>
  <tr><td>Email</td><td><input type="text" name="email"></td></tr>
</table>
<input type="button" onclick="dosubmit()" value="Submit">
</form>
<div id="result" style="padding:5px;">
</div>
<script>
function dosubmit( ) {
  new Ajax.Updater( 'result', 'add.php', { method: 'post',
    parameters: $('myform').serialize() } );
  $('myform').reset();
}
</script>
</body>
</html>

At the top of the file, I include the prototype.js JavaScript file, which will do all the Ajax work for me. After that is a traditional HTML form with three fields: first, last, and email. Below that is the button that submits the form using the dosubmit() JavaScript function.

This dosubmit() function uses the Ajax.Updater class to post the data to the add.php script. Then, you add options to the call. In this case, I set the method of submission to post and add the parameters from the form by using the serialize() method on the form. This serialize() method is not standard JavaScript code: The JavaScript library provides it.

The first item in the call to Ajax.Updater is the ID of the <div> tag, which receives the HTML that the add.php script returns. It's the easiest way to get notification back to the user about what happened when he or she clicked the button.

The add.php script is shown in Listing 2.


Listing 2. add.php
                
Thanks <?php echo( $_POST['first'] ) ?> <?php echo( $_POST['last'] ) ?>!

All it does is echo back what was posted from the form. In reality, this would likely add a record to a database, but you can handle that kind of business logic work for yourself.

When I first load the form, I see something like Figure 1 in my browser.


Figure 1. A simple Ajax form
A simple Ajax form

I then click Submit, which sends the form data to the page, and I get the returned HTML from the add.php page right below the Submit button, as shown in Figure 2.


Figure 2. The response following the submission
The response following the submission

Another variation on forms with Ajax is the auto-fillin form, which updates field values depending on the value of some key fields—for example, typing a customer's ID, clicking a button, and then getting the current customer records in the other fields.

This type of auto-fillin form is shown in Listing 3.


Listing 3. index.html
                
<html>
<head>
<script src="prototype.js"></script>
</head>
<body>
<form id="myform">
<table>
  <tr><td>ID</td><td><input 
    type="text" name="id"></td></tr>
  <tr><td>First</td><td><input type="text" 
    name="first" id="elFirst"></td></tr>
  <tr><td>Last</td><td><input type="text" 
    name="last" id="elLast"></td></tr>
  <tr><td>Email</td><td><input type="text" 
    name="email" id="elEmail"></td></tr>
</table>
<input type="button" onclick="dofill()" value="Fill Fields">
</form>
<script>
function dofill( ) {
  new Ajax.Updater( 'result', 'getdata.php', 
    { method: 'post', parameters: $('myform').serialize(),
  onSuccess: function( transport ) {
    $('elFirst').value = transport.responseXML.getElementsByTagName('first')
      [0].firstChild.nodeValue;
    $('elLast').value = transport.responseXML.getElementsByTagName('last')
      [0].firstChild.nodeValue;
    $('elEmail').value = transport.responseXML.getElementsByTagName('email')
      [0].firstChild.nodeValue;
  } } );
}
</script>
</body>
</html>

I've added a new field to the original form from Listing 1 called ID. That's where you put in the customer's ID. Then, the new dofill() function calls the getdata.php page, which returns XML code that has the first name, last name, and e-mail address for the given customer ID.

The onSuccess handler that I send to the Ajax.Updater call uses the native Document Object Model (DOM) functions available in all browsers to crack the downloaded XML data. It then sets the value of the elFirst, elLast, and elEmail <input> items to the values returned in the XML.

The getdata.php page is shown in Listing 4.


Listing 4. getdata.php
                
<?php
header( "content-type: text/xml" );

$first = ' ';
$last = ' ';
$email = ' ';

if ( $_POST['id'] == '1' )
{
  $first = 'Jack';
  $last = 'Herrington';
  $email = 'jherr@pobox.com';
}
?>
<data>
<first><?php echo( $first ) ?></first>
<last><?php echo( $last ) ?></last>
<email><?php echo( $email ) ?></email>
</data>

It's really just a stub method of code that normally calls the database to get the first name, last name, and e-mail address of the given record.

When I first bring up the page, I see something like Figure 3.


Figure 3. A fill-in form
Fill-in form

I then type 1 in the ID field and click Fill Fields, which goes off to the getdata.php page to get the first name, last name, and e-mail address and update the corresponding fields. This is shown in Figure 4.


Figure 4. The script fills in the fields based on the ID
The script fills in the fields based       on the ID

For my next Ajax slight-of-hand, I create an update in-place to-do list.


Lists that update in-place

One of the common demos for Ruby on Rails is the to-do list, which updates in-place. That means that the list of items is at the top of the page, and there is a text box below the list. When I type something into the text box and click Submit, the list at the top of the page updates with the new item without changing the page. And the text box in which I typed the text resets so that I can keep adding stuff with little effort.

It's actually a terribly difficult trick, so I figured I show off how to do it in PHP. The page for the to-do list is shown in Listing 5.


Listing 5. index.php
                
<html>
<head>
<script src="prototype.js"></script>
</head>
<body>

<div id="result" style="padding:5px;">
<?php
$fh = fopen( 'list.txt', 'r' );
while( $str = fgets( $fh ) ) {
?>
<?php echo( $str ); ?><br/>
<?php
}
?>
</div>

<form id="myform">
<input type="text" name="todo">
</form>

<input type="button" onclick="dosubmit()" value="Submit">

<script>
function dosubmit( ) {
  new Ajax.Updater( 'result', 'add.php',
    { method: 'post', parameters: $('myform').serialize() } );
  $('myform').reset();
}
</script>

</body>
</html>

Instead of holding the to-do list in a database, I just use a flat text file called list.txt to store the items one per line. So, to put the list on the top of the page, I simply open the file and read each line in to the <div> tag with the ID of result.

Below that is the form with the text input for the to-do item. And below that is the button that calls the dosubmit() JavaScript function. That JavaScript function uses the Ajax.Updater class to call the add.php page, which adds the item and returns the new list with the item appended to it.

This add.php script is shown in Listing 6.


Listing 6. add.php
                
<?php
$total = '';

$fh = fopen( 'list.txt', 'r' );
while( $str = fgets( $fh ) ) {
?>
<?php echo( $str ); ?><br/>
<?php
  $total .= $str;
}

if ( array_key_exists( 'todo', $_POST ) )
{
?>
<?php echo( $_POST['todo'] ); ?><br/>
<?php
  $fh = fopen( 'list.txt', 'w' );
  fwrite( $fh, $total."\n".$_POST['todo'] );
  fclose( $fh );
}
?>

My silly list of to-do items is shown in Listing 7.


Listing 7. list.txt
                
Get swim goggles
Practice swimming
Swim in race

When I first go to the page, I see something like Figure 5.


Figure 5. Preparing to add a to-do item
Preparing to add a to-do item

I type Finish in record time, and then click Submit. Then, without a page refresh, I see the result shown in Figure 6.


Figure 6. The page after inserting a record
The page after inserting a record

Of course, this isn't the only cool thing in the Rails demo of a to-do list. But it's one part of the Web 2.0 "wow" factor. Actually, if you haven't tried Rails, I strongly recommend it for any Web engineer. Even if you don't use it in your own projects, it's really interesting to see how applications are organized, how the model-view-controller (MVC) mechanism is used, and how easy the database persistence model is.

Another common Web requirement is the expanding list of fields. I call these expando lists.


Expando lists

What happens when you can have an unlimited number of keywords associated with a record? Well, one way to handle it is to use commas to separate the keywords. Another way is to have a button that adds new keyword fields on the fly to allow users to add as many keywords as they want. I use the second approach in Listing 8.


Listing 8. index.html
                
<html>
<head>
<script src="prototype.js"></script>
</head>
<body>
<form id="myform">
<table id="keytable">
  <tr><td>Keyword</td><td><input type="text" 
    name="keyword_1"></td></tr>
</table>
</form>

<input type="button" onclick="addkeyword()" value="Add Keyword">
<input type="button" onclick="dosubmit()" value="Submit">

<div id="result" style="padding:5px;">
</div>

<script>
var nextkeyid = 2;
function addkeyword()
{
  var elTR = $('keytable').insertRow( -1 );

  var elTitleTD = elTR.insertCell( -1 );
  elTitleTD.appendChild( document.createTextNode( 'Keyword' ) );

  var elInput = document.createElement( 'input' );
  elInput.type = 'text';
  elInput.name = 'keyword_'+nextkeyid;
  nextkeyid++;

  var elInputTD = elTR.insertCell( -1 );
  elInputTD.appendChild( elInput );
}
function dosubmit( ) {
  new Ajax.Updater( 'result', 'add.php', 
    { method: 'post', parameters: $('myform').serialize() } );
}
</script>
</body>
</html>

The real trick here is in the addkeyword() function, which uses insertRow and insertCell to create a new row in the table of keywords. Then, it uses document.createElement to create a new input field to hold the keyword. The Ajax.Updater code, which is called when users click Submit, calls the add.php script. This add.php script simply returns the list of keywords that the form gives it. This script is shown in Listing 9.


Listing 9. add.php
                
Post Result:<br/>
<?php var_export( $_POST ) ?>

When I bring up the page in my browser, I first see something like Figure 7.


Figure 7. The keyword form with a single keyword
The keyword form with a single keyword

I click Add Keyword a few times to add new fields, then click Submit. I get the screen shown in Figure 8.


Figure 8. The keyword form after adding keywords and clicking Submit
The keyword form after adding keywords and clicking Submit

This is an ideal way to allow users to add multiple values associated with a single record for things like phone numbers, keywords, and addresses. Another common use of Ajax is to implement login forms.


Login forms

Login forms in Ajax are particularly cool, because they can give you instant feedback on whether you were able to log in and also because they can perform in-place logins. Imagine that you're looking at an article on which you want to comment, but you aren't logged in. With Ajax, you could log in while you're still looking at the article. If your credentials are accepted, a new form appears that you can use to add a comment. This process is much easier than having to track which article a person was looking at through the login flow to redirect the person after a successful login.

My simple version of the Ajax login is shown in Listing 10.


Listing 10. index.html
                
<html>
<head>
<script src="prototype.js"></script>
</head>
<body>
<form id="logform">
User: <input type="text" name="user"><br/>
Password: <input type="password" name="password"><br/>
<input type="button" onclick="login()" value="Login">
</form>
<div id="noway" style="display:none;">
  No way!
</div>
<script>
function login() {
  new Ajax.Request( 'login.php',
  {
    method: 'post',
    postBody: $('logform').serialize(),
    onSuccess: function( transport ) {
      if( transport.responseText.match( /\<ok\/\>/ ) )
        window.location = 'home.html';
      else
        $('noway').style.display='block';
    }
  } );
}
</script>
</body>
</html>

The User and Password fields are in the form at the top of the file. Below those is a <div> tag with the ID noway, which will be shown if the login is not accepted. The login() JavaScript method makes the login attempt using the Ajax.Request class. If the returned XML from login.php is <ok />, the form redirects the user to the home page. Otherwise, it brings up the noway text.

The login.php code is shown in Listing 11.


Listing 11. login.php
                
<?php
header( 'Content-type: text/xml' );
if ( $_POST['user'] == 'jack' && $_POST['password'] == 'password' )
  echo( "<ok/>" );
else
  echo( "<bad/>" );
?>

This simple code checks against a hard-coded value for the user and password, then returns ok if there is a match and bad otherwise.

For completeness, the home page code is shown in Listing 12.


Listing 12. home.html
                
<html>
<body>
  You are logged in and this is your home page.
</body>
</html>

To start the example in the browser, I bring up the page, type an invalid user name and password, and click Login. The result is shown in Figure 9.


Figure 9. The login page after typing an incorrect password
The login page after typing an       incorrect password

Then, when I change the user name and password to the correct values and click Login, I'm redirected to the home page shown in Figure 10.


Figure 10. The login page after typing the correct user name and password
The login page after typing the       correct user name and password

My last example for this article is an XForms-based Ajax article.


XForms Ajax

I wouldn't consider myself an XForms expert, but I do find it a cool standard. In this article, I blend the client-side XForms stuff with Protoype.js and Ajax techniques.

The code for my simple XForms example is shown in Listing 13.


Listing 13. index.xhtml
                
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:xforms="http://www.w3.org/2002/xforms">
<head>
<title>XForms AJAX Example</title>
<xforms:model id="modelData">
 <xforms:instance xmlns="">
  <Data>
   <First>First</First>
   <Last>Last</Last>
   <Email>email@email.com</Email>
  </Data>
 </xforms:instance>
</xforms:model>
<script src="prototype.js"></script>
</head>
<body>
<xforms:input ref="/Data/First">
<xforms:label>First: </xforms:label>
</xforms:input><br/>
<xforms:input ref="/Data/Last">
<xforms:label>Last: </xforms:label>
</xforms:input><br/>
<xforms:input ref="/Data/Email">
<xforms:label>Email: </xforms:label>
</xforms:input><br/><br/>

<button onclick="submit()">Submit</button>
<script>
function submit()
{
 var m = $('modelData');
 var base = m.getElementsByTagName('Data')[0];
 var s = new XMLSerializer();
 var data = ( s.serializeToString( base ) ).toString();
 new Ajax.Updater( 'result', 'params.php', 
   { method: 'post', parameters: 'data='+escape( data ) } );
}
</script>

<br/><br/>
<div id="result">
</div>

</body></html>

At the top of the file is the XML model for the XForm. Then, there is a set of XForms labels and inputs that make up the form itself. The Submit button calls the submit() JavaScript function. This function then uses the XMLSerializer JavaScript object to turn the XForms data model into an XML string, which is then posted to params.php. The params.php script, shown in Listing 14, returns the XML as HTML so that you can see what comes out of the page.


Listing 14. params.php
                
<?php
echo( htmlentities( $_POST['data'] ) );
?>

When I bring up the XForms page in my browser (with the XForms add-on installed), I see something like Figure 11.


Figure 11. An Ajax-enabled XForms page
An Ajax-enabled XForms page

Then, when I fill in the form and click Submit, I see something like Figure 12.


Figure 12. The page after clicking Submit
The page after clicking Submit

This shows the data model that was turned into XML text, sent across to params.php, then returned into the result <div> tag.


Conclusion

You can do so much with Ajax to enable HTML forms, and this article just scratches the surface. However, it should give you some ideas and practical examples of what you can do in your own applications with relatively easy modifications to your page code.



Download

DescriptionNameSizeDownload method
Source code for forms applicationx-ajaxxml9-forms.zip101KB HTTP

Information about download methods


Resources

Learn

Discuss

About the author

Jack D. Herrington is a senior software engineer with more than 20 years of experience. He's the author of three books: Code Generation in Action, Podcasting Hacks, and PHP Hacks. He has also written more than 30 articles. You can reach Jack at jherr@pobox.com.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=XML, Web development
ArticleID=280275
ArticleTitle=Ajax and XML: Ajax for forms
publish-date=01222008
author1-email=jherr@pobox.com
author1-email-cc=dwxed@us.ibm.com