Version 18 (modified by erob@…, 17 years ago) ( diff )

added a note about IframeTransport for file-uploading support

Introduction

Here's a simple recipe that worked for me. It is quite inspired by the AjaxDojoFormSub example―and from this tutorial―except that this recipe is using python-cjson to receive JSON-encoded data.

My initial objective was to display validation errors without doing a page-refresh, while using JSON for carrying errors (or whatever else you could possibly imagine) back to the client browser.

The server view

First thing first, lets write the server view, as its really important to make the forms working without the use of Javascript:

import cjson
from django.http import HttpResponse
from django.template import loader, Context

def register(request):
    # Register or reports any (new)form-validation errors using JSON.
    form = ExampleForm(request.POST)
    t = loader.get_template('myform.html')
    if not form.is_valid():
       # Return JSON object containing the errors object.
       if xhr:
          return HttpResponse(cjson.encode(form.errors), mimetype='text/javascript')
       else:
          # No JSON here!
          return HttpResponse(t.render(Context(form.errors))
    else:
       # Do something when the form has been validated.
       ...    

The client view

Once the server view has been written, the idea is to write down the client UI (or view, depending whether you're a purist or not.. ;-)

Quite frankly, that step is straight-forward, and looks pretty-much like writing down basic HTML:

<script type="text/javascript">
    djConfig = {
        isDebug: true,
        debugAtAllCosts: false
    };
</script>
<script type="text/javascript" src="/media/js/dojo/dojo.js"></script>
<script type="text/javascript">
    dojo.require("dojo.event.*");       // sophisticated AOP event handling
    dojo.require("dojo.io.*");          // for Ajax requests
    dojo.require("dojo.json");          // serialization to JSON
</script>
<!-- Here's the client UI script to play with Dojo  -->
<script type="text/javascript" src="/media/js/ajax.js"></script>

The djConfig.isDebug parameter is important for debugging, so you should consider setting it to "true" when inspecting you're application with Firebug or something else.

To avoid loading the Dojo modules twice (for speed), just roll your own Dojo script, and then remove the implied ("baked") modules from the list of required modules above.

Form validating with dojo.io.bind

Let's complete our application by writing down the core JS file, for doing some-cute-AJAX-related-things-with-Dojo:

ajax.js:

function myinit() {
    // connect the event with the good handler
    var myButton = dojo.byId("xBtn1");
    dojo.event.connect(myButton, "onclick", "sendForm");
};
function sendForm() {
    var fNode = dojo.byId('xForm')
    var fParms = dojo.io.encodeForm(fNode)
    var myErrorDiv = dojo.byId('errorBox1')
    var bindArgs = {
        url: ".",
        mimetype: 'text/plain',
        method: "post",
        preventCache: true,
        transport: "XMLHTTPTransport",
        postContent: fParms,
        error: function(type, error, http){
               // Handle error here
               alert(error.message)
               if (http.responseText)
                   // Return the raw server response
                   // (useful when debugging)
                   document.write(http.responseText)
               return false
        },
        load: function(type, data, http, kwArgs){
              // Handle "successful" responses here
              var errStr = ''
              if(type == 'load'){
                try {
                 var json = eval( '(' + data + ')' )
                } catch (e) {
                  // not json
                  document.write(data)
                  return false
                }
                for (x in json) 
                    errStr += x + ': ' + json[x] + '<br />'
                myErrorDiv.innerHTML = errStr
              }
         }
    };
    var xmlhttp = dojo.io.bind(bindArgs)
    return xmlhttp
};
dojo.addOnLoad(myinit);

Notice the absence of the formNode param for postContent, and the presence of dojo.io.encodeForm to parse/encode the form data into a proper format. That is more than sufficient for validating the form with a XMLHTTPTransport. However, this approach doesn't work with file-uploads. To have file-uploads, you could however change the transport line to IframeTransport. Here's a link to the IframeTransport api.

Have fun! That recipe should work in Firefox 2 and Opera 9.10.

Limitations/Bugs

  • Usability issues: HTML 4.01 vs XHTML 1.0 strict vs No javascript
  • XMLHTTPTransport doesnt support file-uploading.

Notes

Add some notes here.

References

Author

Etienne Robillard <erob@…>

Attachments (2)

Download all attachments as: .zip

Note: See TracWiki for help on using the wiki.
Back to Top