=== Introduction ===
Here's a simple recipe that worked for me. It is quite inspired by the [wiki:AjaxDojoFormSub] example―and from [http://www.b-list.org/weblog/2006/07/31/django-tips-simple-ajax-example-part-1 this tutorial]―except that this recipe is expected to use python-cjson for receiving JSON data.
My initial objective was to display validation errors without doing a page-refresh, by 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:
# vanilla Http response fallback
return HttpResponse(t.render(Context({'errors' : form.errors }))
else:
# Do something when the form has been validated.
...
}}}
=== The client view ===
Now that the server view is writtent, we could try next to arrange the client code to fit into one, unportable template chunk, however it's
usually best to split the work in smaller pieces, at least for being nice to the maintainers (You). :-)
So let's move on in writing our own Dojo template, where we will make an abstraction of all our applied Dojo concepts.
Quite frankly, that part is going straight-forward, as we're only writing HTML:
{{{
#!text/html
}}}
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.
Optionally, you can "bake" your own Dojo file, and substract the baked modules
from the list of required modules above, so we wont load the already compiled
Dojo modules twice.
=== Form validating w/ dojo.io.bind ===
Let's complete our application by writing down the core JS file,
for doing some-cute-AJAX-related-things-with-Dojo:
{{{
function validate() {
var fNode = dojo.byId('xForm')
var fParms = dojo.io.encodeForm(fNode)
var bindArgs = {
url: ".",
mimetype: 'text/json',
method: "post",
preventCache: true,
transport: "XMLHTTPTransport",
postContent: fParms,
error: function(type, error){
// Handle errors for the XMLHTTPTransport here.
alert(error.message)
return false
},
load: function(type, data, evt){
// handle successful response here
if(type == 'load'){
var myDiv = dojo.byId('errorBox1')
// XXX Not sure what to do if the data is JSON or
// something else..
var json = dojo.json.evalJson(data)
if(json){
errStr = ''
for(x in json){
errStr += x + ': ' + json[x] + ' '
}
myDiv.innerHTML = errStr
}else{
myDiv.innerHTML = "hello, world!"
}}
}}
var xmlhttp = dojo.io.bind(bindArgs)
return xmlhttp
}
}}}
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 all required for having the {{{XMLHTTPRequest}}}
object handled by the Dojo toolkit.
To connect the input submit button with the JS callback, use the following
line:
{{{
#!text/html
}}}
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
* How to display other mimetype(s) when JSON is not used?
=== Notes ===
Add some notes here.
=== References ===
* [http://cheeseshop.python.org/pypi/python-cjson/ python-cjson]
* [http://dojotoolkit.org/ Dojo, the Javascript Toolkit]
* [http://www.w3.org/TR/html401/ HTML 4.01 Specification]
* [http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference Core Javascript 1.5 Reference (mozilla)]
* [http://www.opera.com/docs/specs/opera9/js/ecma/ ECMAScript support in Opera 9]