web2py

March 7, 2010

web2py ajax and forms

Filed under: Uncategorized — mdipierro @ 10:06 pm

The web2py scaffolding application “welcome” has a “layout.html” that {{include “web2py_ajax.html”}} within the <head>…</head> tags. “web2py_ajax.html” defines a few useful JavaScript functions and includes all required CSS and JS files (jquery.js, calendar.js, calendar.css).

The functions defined in “web2py_ajax.html” are designed so that you do not need to write any JS in order to use them.

Web2py comes with everything you need for the examples below to work, including jQuery.

Here are some examples:

Calendar and pre-validation

If you have:

<input class = "date" name="fieldname">

when you click on the input field it will automatically show a popup calendar. Similarly class “datetime” shows a calendar with time-picker and “time” shows a time-picker.

If you have:

<input class = "double" name="fieldname">

web2py will prevent you from typing anything that is not a floating point number. Similarly class “integer” will prevent you from typing anything that is not a valid “integer”.

We call this “pre-validation” to avoid confusion with the proper server-side validation.

All forms generated by web2py (SQLFORM) are CSS friendly all <input /> tags have classes that correspond to the type of the corresponding field, therefore they automatically provide the functionality described here.

Flash

If you have

<div class="flash">content</div>

and if content is not empty, it will slide down the content of the flash and will fade it out when you click on it.

Ajax
web2py defines a function called “ajax” built on top of jQuery’s own ajax. Here is a example of usage:

<input name="key" onKeyUp="ajax('callback',['key'],'target');"/>
<div id="target"></div>

OnKeyUp the ajax function

ajax('callback',['key'],'target');

calls the action at the url specified as first argument (for example ‘callback’) and passes as post variables those specified in the second argument (for example the value of <input name=’key’>), then stores the AJAX return value in the html tag with ID specified by the third argument (for example ‘target’). If ‘target’ has a value attribute the AJAX return value goes into value instead of the inner HTML. If ‘target’ is replaced by ‘:eval’, the AJAX return value is interpreted as JS code and executed.

Components and Forms

When applications get more and more complex you may want to build more modular ones. web2py provides a mechanism to build very modular applications by embedding an action into the template of another action and capture form submissions from the inner one.  Here is an example. Consider the following two actions in controller default.py

def index():
   return dict()

def myform():
   form = SQLFORM.factory(Field('name',requires=IS_NOT_EMPTY()))
   if form.accepts(request.vars): return 'Hello %s' % form.vars.name
   return form

and the following template for the index() action in default/index.html:

{{extend 'layout.html'}}
<h1>Page Title</h1>
{{=LOAD('myform',ajax=True)}}

When calling the “index” action (http://127.0.0.1:8000/myapp/default/index) the output of the index() function is rendered by the template which, in turn, embeds the output of “myform” action (http://127.0.0.1:8000/myapp/default/myaction) via ajax. The LOAD function also generated all required JS code to handle forms inside the loaded content (is the example there is a single form). When the form is submitted, only the “myform” action is called and only the LOADed component is re-loaded, not the entire page. If the form does not pass validation, the form is displayed again including validation errors (this is all handled by the accept function). If the form does pass validation, it returns “Hello <your name>”. The text replaces the actual form, again without disturbing the outer HTML. You can LOAD as many components as you like in one page. The LAOD function also takes additional parameters including args=[] and vars={} to be passed to the called action.

The callback function can be any regular web2py action and can have its own template (for the LOADed component only). Just make sure the template of a component does NOT {{extend ‘layout.html’}} since the layout is provided by the LOADing template.

The LOAD function can also load a URL hosted on a different server (and it does not need to be running web2py):

{{=LOAD(url='http://otherdomain/otherapp')}}

Sometimes it happens that your LOADed action needs to return more than HTML/TEXT but also instructions to the calling page, in the form of JS code embedded in the browser. This can be done by storing JS code in an HTTP header returned by “myform”. The following code for example makes the form “fadein” when it appears

def myform():
   form = SQLFORM.factory(Field('name',requires=IS_NOT_EMPTY()),_class='myformclass')
   if form.accepts(request.vars): return 'Hello %s' % form.vars.name
   response.headers['web2py-component-command']='jQuery(".myformclass").fadeIn()'
   return form

JSON

Sometimes you need JSON. Any web2py action can return json. Just call the action with .json.

For example:

def myvalues():
    return dict(values=['a','b','c'])

And call it with

http://127.0.0.1:8000/myapp/default/myvalues.json

(works also for .html and .xml out of the box. For any other user-defined extension, you just need to create a views/generic.ext file to handle it).

Special care must be used when retuning DB Rows objects, since they are not serializable in JSON. They must be serialized in Python first. as_dict() accomplished that.

For example:

def myusers():
    return dict(users=db(db.auth_user.id>0).select().as_dict())

And call it with

http://127.0.0.1:8000/myapp/default/myusers.json

If you want to program lower level web2py includes simplejson in gluon.contrib.simplejson. It has been modified to handle date and datetime.

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: