Easy Ajax Forms with Fancybox

Note: The fancybox jQuery plugin can be found here.

Last week we rolled out a new design for yipit, which I’m really excited about. It looks awesome. Sam Brown did an amazing job. In a few different places we decided to use modal forms that would submit via Ajax. I think technique provides great UX, but  if the forms require server-side validation,  displaying the appropriate HTML can be a bit of a headache.

First Attempts

The initial strategy was to have the server respond with JSON containing any errors and then show them appropriately to the user. This is a totally valid approach, but every form is different, which meant writing form specific code both server and client-side. I also find injecting HTML into an existing page to be pretty tedious, so having to write JavaScript to do exactly that for every form was not a solution I was happy with.

In addition, if the form did validate, it was unclear where the success HTML should live. We could have the server return it, but this made for an awkward transaction since we also needed to pass back whether or not the form had validated. The HTML could be part of the JavaScript, but this would break MVC and not allow us to leverage Django’s templating system. Either way, the django views we were using looked very different than the views for standard pages, and having to switch gears slows down development.

I wanted to find a solution that met these criteria:

  1. Minimal custom JavaScript
  2. Familiar server-side code
  3. Adhere to MVC

Change of Plans

Fancybox makes it really easy to draw an overlay with HTML returned via Ajax. Fancybox also only allows one overlay at a time. This is a limitation, but it does make it really easy to replace one overlay with another. Leveraging both these behaviors, we realized we could have every call to the server result in a new fancybox that would replace one currently being displayed. This way we cold write traditional Django views to handle the Ajax request and take full advantage of the Django templating system, including the display of form errors.

The first iteration of this involved every fancybox containing the javascript necessary to launch the next fancybox. This worked really well on Firefox, Safari, and Chrome, but IE was no so cooperative. In IE, we could show a second fancybox, if that fancybox contained JavaScript, the browser would crash. Also, it didn’t satisfy the requirement of not having to write custom JavaScript for every form. Using a little client-side recursion (who knew there were practical applications?) and a couple of guidelines, we were able to launch new fancyboxes without new scripts.

Guidelines

  1. Every <a> tag that launches a fancybox form must share common class.
  2. Every fancybox that contains a form must share a common class.
  3. Every form must have an explicit action containing the destination URL for the Ajax request.
  4. Every response contains the html for a new fancybox (and must adhere to guidelines 2 and 3 to allow for chaining)

Sample Code

Django View:
Django Template:
Javascript (assumes jQuery 1.4 and fancybox 1.3.1):

Any server-side implementation will work if you adhere to the guidelines. The real meat is in the JavaScript .

You can leave a response, or trackback from your own site.
  • Freethrow

    Hello. I appreciate your taking the time to post this. I find working with modal forms and Django very strange. Could you upload a piece of the code somewhere?

  • Konceptsoftware Delhi

    $document.ready…..
    it was soooo boring using $document.ready

  • Baatar

    Great post, Zach. But I have a question: is there something special with url in urls.py?

blog comments powered by Disqus