While web2py is mainly for server-side development, the welcome scaffolding app comes with the base jQuery library32, jQuery calendars (date picker, datetime picker and clock), the "superfish.js" menu, and some additional JavaScript functions based on jQuery.
Nothing in web2py prevents you from using other Ajax libraries such as Prototype, ExtJS, or YUI, but we decided to package jQuery because we find it to be easier to use and more powerful than other equivalent libraries. We also find that it captures the web2py spirit of being functional and concise.
The scaffolding web2py application "welcome" includes a file called
1. | views/web2py_ajax.html |
This file is included in the HEAD of the default "layout.html" and it provides the following services:
static/jquery.js.static/calendar.js and static/calendar.css, if they exist.ajax function (based on jQuery $.ajax).web2py_ajax_component, a very important tool that will be described in Chapter 13.It also includes popup, collapse, and fade functions for backward compatibility.
Here is an an example of how the other effects play well together.
Consider a test app with the following model:
1. | db = DAL("sqlite://db.db") |
with this "default.py" controller:
1. | def index(): |
and the following "default/index.html" view:
1. | {{extend 'layout.html}} |
The "index" action generates the following form:

If an invalid form is submitted, the server returns the page with a modified form containing error messages. The error messages are DIVs of class "error", and because of the above web2py_ajax code, the errors appears with a slide-down effect:

The color of the errors is given in the CSS code in "layout.html".
The web2py_ajax code prevents you from typing an invalid value in the input field. This is done before and in addition to, not as a substitute for, the server-side validation.
The web2py_ajax code displays a date picker when you enter an INPUT field of class "date", and it displays a datetime picker when you enter an INPUT field of class "datetime". Here is an example:

The web2py_ajax code also displays the following time picker when you try to edit an INPUT field of class "time":

Upon submission, the controller action sets the response flash to the message "record inserted". The default layout renders this message in a DIV with id="flash". The web2py_ajax code is responsible for making this DIV appear and making it disappear when you click on it:

These and other effects are accessible programmatically in the views and via helpers in controllers.
The basic effects described here do not require any additional files; everything you need is already included in web2py_ajax.html.
HTML/XHTML objects can be identified by their type (for example a DIV), their classes, or their id. For example:
1. | <div class="one" id="a">Hello</div> |
They belong to class "one" and "two" respectively. They have ids equal to "a" and "b" respectively.
In jQuery you can refer to the former with the following a CSS-like equivalent notations
1. | jQuery('.one') // address object by class "one" |
and to the latter with
1. | jQuery('.two') |
or you can refer to both with
1. | jQuery('DIV') |
Tag objects are associated to events, such as "onclick". jQuery allows linking these events to effects, for example "slideToggle":
1. | <div class="one" id="a" onclick="jQuery('.two').slideToggle()">Hello</div> |
Now if you click on "Hello", "World" disappears. If you click again, "World" reappears. You can make a tag hidden by default by giving it a hidden class:
1. | <div class="one" id="a" onclick="jQuery('.two').slideToggle()">Hello</div> |
You can also link actions to events outside the tag itself. The previous code can be rewritten as follows:
1. | <div class="one" id="a">Hello</div> |
Effects return the calling object, so they can be chained.
When the click sets the callback function to be called on click. Similarly for change, keyup, keydown, mouseover, etc.
A common situation is the need to execute some JavaScript code only after the entire document has been loaded. This is usually done by the onload attribute of BODY but jQuery provides an alternative way that does not require editing the layout:
1. | <div class="one" id="a">Hello</div> |
The body of the unnamed function is executed only when the document is ready, after it has been fully loaded.
Here is a list of useful event names:
Here is a list of useful effects defined by jQuery:
The speed argument is usually "slow", "fast" or omitted (the default). The callback is an optional function that is called when the effect is completed.
jQuery effects can also easily be embedded in helpers, for example, in a view:
1. | {{=DIV('click me!', _onclick="jQuery(this).fadeOut()")}} |
jQuery is a very compact and concise Ajax library; therefore web2py does not need an additional abstraction layer on top of jQuery (except for the ajax function discussed below). The jQuery APIs are accessible and readily available in their native form when needed.
Consult the documentation for more information about these effects and other jQuery APIs.
The jQuery library can also be extended using plugins and User Interface Widgets. This topic is not covered here; see ref.76 for details.
A typical application of jQuery effects is a form that changes its appearance based on the value of its fields.
This is easy in web2py because the SQLFORM helper generates forms that are "CSS friendly". The form contains a table with rows. Each row contains a label, an input field, and an optional third column. The items have ids derived strictly from the name of the table and names of the fields.
The convention is that every INPUT field has an id tablename_fieldname and is contained in a row with id tablename_fieldname__row.
As an example, create an input form that asks for a taxpayer's name and for the name of the taxpayer's spouse, but only if he/she is married.
Create a test application with the following model:
1. | db = DAL('sqlite://db.db') |
the following "default.py" controller:
1. | def index(): |
and the following "default/index.html" view:
1. | {{extend 'layout.html'}} |
The script in the view has the effect of hiding the row containing the spouse's name:

When the taxpayer checks the "married" checkbox, the spouse's name field reappears:

Here "taxpayer_married" is the checkbox associated to the "boolean" field "married" of table "taxpayer". "taxpayer_spouse_name__row" is the row containing the input field for "spouse_name" of table "taxpayer".
Another useful application is requiring confirmation when checking a "delete" checkbox such as the delete checkbox that appears in edit forms.
Consider the above example and add the following controller action:
1. | def edit(): |
and the corresponding view "default/edit.html"
1. | {{extend 'layout.html'}} |
deletable=True argument in the SQLFORM constructor instructs web2py to display a "delete" checkbox in the edit form. It is False by default.web2py's "web2py_ajax.html" includes the following code:
1. | jQuery(document).ready(function(){ |
By convention this checkbox has a class equal to "delete". The jQuery code above connects the onclick event of this checkbox with a confirmation dialog (standard in JavaScript) and unchecks the checkbox if the taxpayer does not confirm:

ajax FunctionIn web2py_ajax.html, web2py defines a function called ajax which is based on, but should not be confused with, the jQuery function $.ajax. The latter is much more powerful than the former, and for its usage, we refer you to ref.32 and ref.75. However, the former function is sufficient for many complex tasks, and is easier to use.
The ajax function is a JavaScript function that has the following syntax:
1. | ajax(url, [id1, id2, ...], target) |
It asynchronously calls the url (first argument), passes the values of the fields with the id equal to one of the ids in the list (second argument), then stores the response in the innerHTML of the tag with the id equal to target (the third argument).
Here is an example of a default controller:
1. | def one(): |
and the associated "default/one.html" view:
1. | {{extend 'layout.html'}} |
When you type something in the INPUT field, as soon as you release a key (onkeyup), the ajax function is called, and the value of the id="name" field is passed to the action "echo", which sends the text back to the view. The ajax function receives the response and displays the echo response in the "target" DIV.
The third argument of the ajax function can be the string ":eval". This means that the string returned by server will not be embedded in the document but it will be evaluated instead.
Here is an example of a default controller:
1. | def one(): |
and the associated "default/one.html" view:
1. | {{extend 'layout.html'}} |
This allows for more articulated responses than simple strings.
Web2py contains a built-in autocomplete widget, described in the chapter about Forms. Here we will build a simpler one from scratch.
Another application of the above ajax function is auto-completion. Here we wish to create an input field that expects a month name and, when the visitor types an incomplete name, performs auto-completion via an Ajax request. In response, an auto-completion drop-box appears below the input field.
This can be achieved via the following default controller:
1. | def month_input(): |
and the corresponding "default/month_input.html" view:
1. | {{extend 'layout.html'}} |
The jQuery script in the view triggers the Ajax request each time the visitor types something in the "month" input field. The value of the input field is submitted with the Ajax request to the "month_selector" action. This action finds a list of month names that start with the submitted text (selected), builds a list of DIVs (each one containing a suggested month name), and returns a string with the serialized DIVs. The view displays the response HTML in the "suggestions" DIV. The "month_selector" action generates both the suggestions and the JavaScript code embedded in the DIVs that must be executed when the visitor clicks on each suggestion. For example when the visitor types "Ma" the callback action returns:
1. | <div onclick="jQuery('#month').val('February')" |
Here is the final effect:

If the months are stored in a database table such as:
1. | db.define_table('month', Field('name')) |
then simply replace the month_selector action with:
1. | def month_input(): |
jQuery provides an optional Auto-complete Plugin with additional functionalities, but that is not discussed here.
Here we consider a page that allows the visitor to submit messages using Ajax without reloading the entire page. Web2py provides a better mechanism for doing it than described here using the LOAD helper and it will be described in Chapter 13, yet here we want to show you how to do it simply using jQuery.
It contains a form "myform" and a "target" DIV. When the form is submitted, the server may accept it (and perform a database insert) or reject it (because it did not pass validation). The corresponding notification is returned with the Ajax response and displayed in the "target" DIV.
Build a test application with the following model:
1. | db = DAL('sqlite://db.db') |
Notice that each post has a single field "your_message" that is required to be not-empty.
Edit the default.py controller and write two actions:
1. | def index(): |
The first action does nothing other than return a view.
The second action is the Ajax callback. It expects the form variables in request.vars, processes them and returns DIV("Message posted") upon success or a TABLE of error messages upon failure.
Now edit the "default/index.html" view:
1. | {{extend 'layout.html'}} |
Notice how in this example the form is created manually using HTML, but it is processed by the SQLFORM in a different action than the one that displays the form. The SQLFORM object is never serialized in HTML. SQLFORM.accepts in this case does not take a session and sets formname=None, because we chose not to set the form name and a form key in the manual HTML form.
The script at the bottom of the view connects the "myform" submit button to an inline function which submits the INPUT with id="your_message" using the web2py ajax function, and displays the answer inside the DIV with id="target".
Another Ajax application is voting or rating items in a page. Here we consider an application that allows visitors to vote on posted images. The application consists of a single page that displays the images sorted according to their vote. We will allow visitors to vote multiple times, although it is easy to change this behavior if visitors are authenticated, by keeping track of the individual votes in the database and associating them with the request.env.remote_addr of the voter.
Here is a sample model:
1. | db = DAL('sqlite://images.db') |
Here is the default controller:
1. | def list_items(): |
The download action is necessary to allow the list_items view to download images stored in the "uploads" folder. The votes action is used for the Ajax callback.
Here is the "default/list_items.html" view:
1. | {{extend 'layout.html'}} |
When the visitor clicks on "[vote up]" the JavaScript code stores the item.id in the hidden "id" INPUT field and submits this value to the server via an Ajax request. The server increases the votes counter for the corresponding record and returns the new vote count as a string. This value is then inserted in the target item{{=item.id}} SPAN.
Ajax callbacks can be used to perform computations in the background, but we recommend using cron or a background process instead (discussed in chapter 4), since the web server enforces a timeout on threads. If the computation takes too long, the web server kills it. Refer to your web server parameters to set the timeout value.