Live Form - Ajax Patterns

Live Form

From Ajax Patterns

Evidence: 2/3

Tags: Dynamic Live Real-Time Validation


Contents

In A Blink

Diagram: ticks and crosses, a "validating ..." message next to a recent field, a modified field.


Goal Story

Tracy is applying for a new online brokerage account. Upon declaring her place of residence, some additional regulation-related questions appear, specific to her region. Several asset classes can be traded. She ticks a box to indicate she want to trade in bonds, and further questions specifically for that asset class. She then clicks on another box, for options. A moment later, a warning appears that new users can only trade in one of options or bonds. After further refinement, she successfully submits the form and sees it fade into a welcome message.


Problem

How can the user submit data as quickly as possible?


Forces

  • Most data submission tasks require some flexibility. A particular answer for one item will necessitate further questions. Often, this must occur server-side, where business logic and data usually reside.
  • Most data submission requires validation. This must occur server-side to prevent browser-side manipulation of inputs.
  • Users get frustrated waiting for data to be validated and continuously refining data upon each explicit submission.


Solution

Validate and modify a form throughout the entire interaction, instead of waiting for an explicit submission. Each significant user event results in some browser-side processing, often leading to an XMLHttpRequest Call. The form may then be modified as a result.

Modifying the form is similar to responding to a Microlink - there's usually a server call followed by some Page Rearrangement. Typical modifications:

  • New controls appear.
  • Controls become disabled.
  • Information and error messages appear.

The result is a more interactive form. The user doesn't have to wait for a page reload to find out if a form field is invalid, because it's validated as soon as they enter the value. Due to the asynchronous nature of XMLHttpRequest Call, the validation occurs as a background process, while the user carries on entering data further down the form. If there's an error, the user will find out about it while filling out a field further down the form. As long as errors don't happen too often, that's no great inconvenience.

Validation doesn't always occur at field level though. Sometimes, it's the combination of data that's a problem. This can be handled by checking validation rules only when the user's provided any input for all related fields. A validation error can result in a general, form-level, error message or a message next to one or more of the offending fields.

A Live Form usually ends with an Explicit Submission, allowing the user to confirm everything's valid. Note, that unlike a conventional form, the Explicit Submission does not perform a standard HTTP form submission, but posts the contents as an XMLHttpRequest Call.


Decisions


Real-World Examples

WPLicense

WPLicense is a WordPress plugin allowing users to specify a copyright license for their blog content. Refer to the Cross-Domain Proxy for details on the plugin and the Code Examples below for a walkthrough of its Live Search implementation.

Betfair

Betfair lets the user make a bet using a Live Form. You can try this even as a non-registered user, by opening up a bet from the Drilldown menu. There are three columns on the page: the left column shows the current bet topic within the Drilldown, the centre column shows odds for all candidates, and the right column shows your stake in this bet. Clicking on a candidate causes it to appear in your stake form, where you can then set how much you're placing. As you change your stake, there's also a Status Area that shows your total liability. Also, another column shows your profit if each event occurs. There are also some "meta" controls. For instance, clicking on "Back All" creates an editable row for every candidate.

MoveableType Comment Hack

Simian Design is a blog where you can add comments, Ajax style. As you type into the textbox, a live preview appears underneath and takes markup into account. Clicking on Preview or Post, the text fades and an animated Progress Indicator bar shows the server is processing. The result is then embedded in the page with some Page Rearrangement.


Code Examples

WPLicense

WPLicense is a form with a live component. Initially, the "License Type" field simply shows the current license, if any. But when the user clicks on the update link, a new block opens up and a conversation between the browser and server ensues to establish the precise details of the license. (More precisely, the conversation is between the browser and the Creative Commons website - see the corresponding example in Cross-Domain Proxy). Each license type has associated questions, so the license options are fetched according to the user's license type selection.

When the user launches the plugin, a PHP function begins by drawing the Live Form. In this case, the form is ultimately submitted as a conventional POST upload, so the form has a conventional declaration:

  <form name="license_options" method="post" action="' . $_SERVER[REQUEST_URI] . '">
   ...
   <input type="submit" value="save" />
   <input type="reset"  value="cancel" id="cancel" />
   ...
  </form>

The current license is shown, loaded with initial values, along with the link that triggers the cross-domain mediation to update the license setting.

  <tr><th>Current License:</th><td>
   <a href="'.get_option('cc_content_license_uri').'">'.get_option('cc_content_license').'</a>
   ...

The form includes hidden input fields to capture information gleaned during the Ajaxian interaction. They will be populated from Javascript event-handlers.

  <input name="license_name" type="hidden" 
         value="'.get_option('cc_content_license').'" />
  

As well, there's an initially-invisible div which will be shown once the user decides to change the license. Don't confuse this with the hidden input fields - those will never be shown to the user, while this just happens to have a hidden style when the page initially loads. Most critically, the div contains a selection field:

    <select id="licenseClass"> <option id="-">(none)</option>
    ...
    foreach($license_classes as $key => $l_id) {
      echo '<option value="' . $key . '" >' . $l_id . '</option>';
    }; // for each...
    ...
    </select>
  

Now, I said that each license has different options, so how are those options shown to the user? The "licenseClass" selector is associated with retrieveQuestions, a function which fetches the questions corresponding to the chosen license. The call is made courtesy of the Sack library, which paints the server's HTML directly onto the license_options DIV.

   el.onchange = function() {
      retrieveQuestions();
   } // onchange
 
  function retrieveQuestions() {
    ajax = new sack(blog_url);
    ajax.element='license_options';
    ajax.setVar('func', 'questions');
    ajax.setVar('class', cmbLC.value); ''Current license passed to server''
    ajax.runAJAX();
    ...
  }

The server determines the appropriate questions to ask, and outputs them as HTML Responses. (See the Cross-Domain Proxy example for details.)

Now, how about those hidden fields? Well, the thing is, not all the information related to the options are hidden: the license URL is shown to the user, so that also needs to be updated after an option is chosen. Each time the user changes the server-generated options, the server is called to get a bunch of information about the current selection (admin.js:updateLicense()). That information then comes back to the browser, and the callback function updates both the hidden fields and the URL accordingly:

   *** Updating the hidden fields ***
   document.license_options.license_name.value = licenseInfo['name'];
   document.license_options.license_uri.value  = licenseInfo['uri'];
   document.license_options.license_rdf.value  = licenseInfo['rdf'];
   document.license_options.license_html.value = licenseInfo['html'];
  
   *** Updating the visible license URL ***
   href_text = '<a href="' + licenseInfo['uri'] + '">' + licenseInfo['name'] + '</a>';
   document.getElementById("newlicense_name").innerHTML = href_text;

Now, what's changed so far, on a permanent basis? Well, nothing. Everything so far has been setting up the form itself. But that's fine here, because the form is submitted in the conventional manner. So as soon as the user clicks on the Submit button, all those hidden fields will be uploaded and processed as standard HTTP form data.


Alternatives

Alternative


Related Patterns

Microlink

Like Live Forms, Microlinks open up new content directly on the page. Indeed, a Microlink can be used on a Microlink to provide some supporting information.

Live Search

Consider including a Live search when users need to perform a search within the Live Form.

Suggestion

Consider offering Suggestions to help users complete fields within the Live Form.

Drilldown

Consider including a Drilldown when users need to identify an item within a hierarchy.

Progress Indicator

Show the server is working to process a field with a Progress Indicator.

One-Second Spotlight

Since Live Forms are usually submitted with an XMLHttpRequest Call, a One-Second Spotlight effect, such as Fade Out is a good way to convey the form's been submitted.


Visual Metaphor

Filling out a Live Form is like being interviewed by someone smart enough to listen, give feedback, and improvise on the content.


Want to Know More?