Sneaky Abstractions

Subscribe to my Feed, follow me on , recommend me on Working With Rails or see my code on GitHub

Unobtrusive Ajax patterns: the remote form

Posted on June 30, 2008 11:17 Tagged with unobtrusive, javascript, ajax, ajax patterns.

I’ve decided to adapt a more “stream of consciousness” style of writing, because my yearning for perfection has so far only resulted in lots of posts that never get finished or even started. Yeah, no such thing as perfection.. Who would’ve thought? This is the first in what may become a series of posts showing how you can apply common Ajax or JavaScript patterns unobtrusively to your HTML.

A “remote form” is a form which submits asynchronously and acts upon the response. To make a normal form “remote”, stop the “submit” event and send off an Ajax request.

The form, with a “remote” class to identify it (and others!):

<form action="/articles" class="remote" method="post">
  <input id="article_title" name="article[title]" />
  <textarea id="article_body" name="article[body]"></textarea>
  <input type="submit" value="Save" />
</form>

The JavaScript finds all forms with the “remote” class and hijacks them so that they’re submitted asynchronously:

document.observe('dom:loaded', function(){

  $$('form.remote').each(function(form){
    form.observe('submit', function(e){
      e.stop(); //Stop the default action, which is to submit the form the normal way
      form.addClassName('enhanced');
      form.request({
        onComplete: function(res){
          doSomethingWith(res.responseText);
        }
      });
    });
  });

});

You could add a “link” class to have the form replaced with a link:

<form action="/articles" class="remote link" method="post">
<!- ... ->
</form>
document.observe('dom:loaded', function(){

  $$('form.remote').each(function(form){
    if (form.hasClassName('link') {//Replace with a link
      var link = new Element('a', {href:'#'})
      //Use the value of the submit button as the value for the link
      link.update(form.down('input[type=submit]'));
      //When the link is clicked, it should submit the form
      //The form will catch the submit event and submit asynchronously
      link.observe('click', function(e){ e.stop(); form.submit(); });
      //Insert the link _after_ the form
      form.insert({after:link});
    }
    form.observe('submit', function(e){
      /* Same as above. The form will catch the submit event fired
         by the link and submit asynchronously */
    });
  });

});

Note that nothing is done to the form in the case where it has the “link” class name. The form receives the “enhanced” class name regardless of if it’s a link or not, and with that we can target it with CSS and hide the form:

form.remote.enhanced.link {
  display: none;
}

The noise of mankind has become too much, I am losing sleep over their racket