Create a dynamic XHTML page with mod_wxjs

This little tutorial shows you how you can use mod_wxjs to build a dynamic webpage. This tutorial uses the modules SQLite and TPL. The goal of this tutorial is to show a list of all the books on the shelf.

Before you start

Make sure that mod_wxjs is correctly installed. You don't need to create a database. SQLite will look for a database and will create one when it doesn't exist. Make sure that the modules sqlite and tpl are loaded. Your modules scriptfile may look like this:

// Relative paths are made absolute to the directory of this script
wxjs.modules.tpl = new Module("../modules/wxjs_tpl.dll");
wxjs.modules.tpl.load();

wxjs.modules.sqlite = new Module("../modules/wxjs_sqlite.dll");
wxjs.modules.sqlite.load();

wxjs.modules.io = new Module("../modules/wxjs_io.dll");
wxjs.modules.io.load();

Connect to a database

Instantiate a sqlite.Database object. When the database doesn't exist, SQLite will create a new one. How do we know that a new file is created? You can use the PRAGMA statement for this. When this statement returns 0, the database is created. When the statement returns 1, the database was already created. Put the following code in a separate scriptfile 'db.wxjs'.

var handle = new sqlite.Database("books.db");
if ( handle.opened )
{
  var pragmaStmt = handle.prepare("PRAGMA user_version");
  var pragma = pragmaStmt.fetchArray();
  if ( pragma[0] == 0 )
  {
    // Create the tables and insert some example data
    handle.exec("CREATE TABLE authors(id INTEGER PRIMARY KEY, " +
                "firstname TEXT, lastname INTEGER)");
    handle.exec("CREATE TABLE books(id INTEGER PRIMARY KEY, " +
                "title TEXT, fk_author_id INTEGER)");
    handle.exec("PRAGMA user_version = 1");
    handle.exec("INSERT INTO authors(id, firstname, lastname) " +
                "VALUES(1, 'JRR', 'Tolkien')");
    handle.exec("INSERT INTO authors(id, firstname, lastname) " + 
                "VALUES(2, 'John', 'Grisham')");
    handle.exec("INSERT INTO books(id, title, author) " +
                "VALUES(1, 'Lords of the ring', 1)");
    handle.exec("INSERT INTO books(id, title, author) " +
                "VALUES(2, 'The firm', 2)");
  }
}
else
{
  handle = null;
}

Create a template

To separate the view logic from the model logic a template is used. Create a file 'books.tpl' with the following contents:

        <template name="page">
         <html>
          <title>List of books on my shelf</title>
          <body>
           <h1>List of books on my shelf</h1>
           <table>
            <tr>
             <th>Author</th>
             <th>Title</th>
            </tr>
            {rows}
           </table>
          </body>
         </html>
        </template>
        
        <template name="row">
          <tr>
           <td>{author}</td>
           <td>{title}</td>
          </tr>
        </template>
       

The file contains two templates: one template for each row of the table and one template for the webpage.

Create the page

This script includes the 'db.wxjs' file to connect to the database. When a database is available, the data is read using the prepare method. For each row the template 'row' is parsed and the result is added to the 'rows' element.

var db = include('db.wxjs');
if ( db.handle )
{
  var template = new tpl.Engine();
  template.load('books.tpl');

  var stmt = db.handle.prepare("SELECT firstname, " +
                               "       lastname,  " +
                               "       title      " +
                               "  FROM books,     " +
                               "       authors    " +
                               " WHERE books.author = authors.id");
  if ( stmt )
  {                                       
    var row;
    while( row = stmt.fetchObject() )
    {
      // Set the elements of the row template
      template.author = row.firstname + " " + row.lastname;
      template.title = row.title;
      // Parse the 'row' template and append the result to the
      // 'rows' element
      template.parse("row", "rows", true);
    }
    
    // Parse the page template and store it in the 'html' element
    template.parse("page", "html", false);
    
    // Send the page to the client
    response.print(template.html);
  }
}