Using Ajax with the BeepBeep Microframework
Building on the extremely basic introduction to BeepBeep, in this second article in the Intro to BeepBeep series we'll take a look at using Ajax with BeepBeep.
Like most simple Ajax examples, this one will be rather contrived, but nonetheless should demonstrate the concept. I won't try to convince the dear reader that the example isn't exceptionally uninspired, we will simply poll the BeepBeep application for the current time and then display it to the user1.
BeepBeep Setup
(If you haven't installed BeepBeep, please refer to the previous Getting Started with BeepBeep tutorial before going further.)
Use BeepBeep to start our new project.
cd ~/git/beepbeep/ script/new_beep.erl BB_Time ../BB_Time
Then navigate to the project's directory.
cd ~/git/BB_Time/bb_time
With that, the project is initialized and ready for our special sauce.
BeepBeep Logic
Next, we need to setup the BeepBeep portion of the application (as opposed to the JavaScript portion, which we'll configure last).
First we need to create two controllers:
- a controller to display the initial page
- a controller that will be polled for the current time.
Open up
src/home_controller.erl
, and replace the existinghandle_request
handler (for bothindex
andshows
) with this code:handle_request("index",[]) -> {_A,B,_C} = erlang:now(), {render,"home/index.html",[{time, B}]};
handle_request("time",[]) -> {A,B,C} = erlang:now(), {render,"home/ajax.html",[{time, B}]}.
The two handles look nearly identical except for rendering different views, which makes a lot of sense, because from the server's perspective Ajax requests are no different than a normal HTTP request.
Also, replace the existing
before_filter
implementation with:before_filter() -> ok.
Then save and close
home_controller.erl
.Next we need to edit the base view. Open up
views/base.html
and change it to:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="content-type" content="text/html;charset=UTF-8" /> <title>Welcome to BeepBeep Ajax</title> <link href="/stylesheets/style.css" rel="stylesheet" type="text/css"/> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"> </script> <script type="text/javascript" src="/js/time.js"></script> </head> <body> {% block content %}{% endblock %} </body> </html>
The signifigant changes are adding the JavaScript import for the non-existant
js/time.js
file (we'll put it together later), and adding the Google hosted jQuery library.Third, create the
views/home/ajax.html
template, which should look like this:<p> Time is { { time }}</p>
Note that we don't start it with a
{% extends "../base.html" %}
block, as we will be injecting this HTML fragment into an existing HTML page.Next edit the
views/home/index.html
template to look like:{% extends "../base.html" %} {% block content %} <div id="time"> {% include "ajax.html" %} </div> {% endblock %}
If you're not familar with Django, you may not have encountered the
include
tag, which injects the contents of another file into the current file, and will evaluate the injected template using the injecting template's context.Note that this also reveals one of the awkward aspects of ErlyDTL, which is that it doesn't understand paths as originating in the
views/
folder, but instead requires them to be relative to the current template. That is to say, thathome/index.html
must write the relative path to../base.html
, and also that the include tag inindex.html
must refer toajax.html
, rather thanhome/ajax.html
. This is a bit of a deviation from expected Django behavior, so be careful.Finally let's verify that our little app works.
make ./start-server.sh
Then go to the http://localhost:8000/ and the http://localhost:8000/ajax pages to see they are rendering the correct pages.
With that, we're quite close to completing our simple Ajax app, missing only the Ajax.
JavaScript Logic
We're already including jQuery into base.html
, we just need
to create and flesh out js/time.js
a bit.
mkdir www/js
emacs www/js/time.js
Then add this code:
var update = function() {
$("#time").load("/home/time");
}
setInterval(update, 1000);
Finally, reload http://localhost:8000/ and you'll see yet another egregious violation of Ajax occuring right before your eyes and powered by BeepBeep!
(You can grab the code for this tutorial at BB_Time
in the BeeBeep Examples repository.)
In the next segment of this tutorial we'll take a look at using BeepBeep along with a persistent data store to bring together the bare minimum components for providing a real service instead of a tinkertoy.
Of course it would be simpler to just use client side JavaScript for the entire ordeal, but... I'm just trying to demonstrate a concept.↩