04 - HTML Templates

HTML templates are really just HTML files. They live right in your public_html/ directory and filenames should be named ending with a .html extension. So what makes them different from plain old HTML files?

ZenTools does some neat things for us:

  • The .html extension is omitted from the URLs
  • Templates can be wrapped in a layout file
  • "Page Settings" can be used to override some elements in the layout
  • Controller methods can target template elements and populate or manipulate them

Layout parsing

The default layout is named _layout.html. Template files starting with an underscore by convention are files which are included rather than directly navigated to. The _layout.html should contain everything but the content for standard pages of the site. Every layout file must contain a block with a named id of "content" like this:

<div id="content">
  (content will appear here)
</div>

The "(content will appear here)" text is just there to make the template more understandable. You can put anything you like or nothing at all there. The important thing is that there be a <div id="content"></div> so that ZenTools has a place to put the content of the template.

So let's say our public_html/ directory has these two files:

public_html/
   _layout.html
   index.html

Our simple layout looks like this:

_layout.html

<html>
  <head><title>My Website</title></head>
  <body>
    <div id="content">
      (content will appear here)
    </div>
  </body>
</html>

And the index file looks like this:

index.html

<h1>Welcome to my website</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing.</p>

Now to see it all wrapped together, we can just browse to /index and we'll find that the content of index.html has been transplanted into the layout's "content" element. Of course, since this file is the index file, we can just browse to / instead. And it all works beautifully without a bunch of ugly include header/footer code all over the place. You can also create other layouts as needed and simply tell your template to use a different layout. The way to do that involves using Page Settings.

Page Settings

Let's say we've created an alternate layout called _layout-alt.html which we want to use for our index.html instead of our default layout. Here's the modified code for index.html to use _layout-alt.html:

index.html

Layout: /_layout-alt.html

<h1>Welcome to my website</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing.</p>

The first line at the top of the file is called a Page Setting. You can use Page Settings to specify the layout (or set Layout: None), or change the page title, include a CSS file, etc. Here's a complete list of Page Settings:

Layout: (Path to layout file or None)

Layout: /_layout-for-popup.html
Layout: None

Title: (Replace content of the layout's title tag)

Title: My Neato ZenTools Website

Extra CSS: (path to add'l CSS file to import)

Extra CSS: /css/pages/product-view.css

Extra JS: (path to add'l JavaScript file to import)

Extra JS: /js/jquery.js

Keywords: (Comma separated list of keywords for layout's meta keywords tag)

Keywords: ZenTools, zentools, python, framework

Description: (Set the content of layout's meta description tag)

Description: Everything you never wanted to know about ZenTools!

Hide: (ID name of element to remove from HTML)

Hide: login-box

Include: (ID name of element AND path of file to populate it with)

Include: sidebar /_sidebar.html

Include Doc: (ID name of element AND URL of content to populate it with)

Include Doc: blog-posts http://some-blog.com/posts.php
Include Doc: php-info /php-info.php

Body ID: (Set the layout's body ID attribute)

Body ID: product-info

Body Class: (Set the layout's body class attribute)

Body Class: product-info

Header: (Set arbitrary HTTP headers)

Header: Cache-Control: no-cache

Add Class: (Add a class to any element with an id)

Add Class: product-nav selected

Selected: (Add the class 'selected' to any element with an id)

Selected: product-nav

A typical template page might start with a few Page Settings like this:

monkeys.html

Title: Monkeys in New York
Keywords: Monkeys, New York, Big Apple
Description: Amazing photos of NYC's burgeoning wild monkey population.

<h1>Monkeys in New York</h1>

...etc

Note that since no layout was defined, and since we also didn't specify Layout: None, this page will automatically inherit the default _layout.html file.

Templates without templating

ZenTools templates are essentially pure, valid HMTL. There is no templating language. So how do you get dynamic data into your template? By targeting elements from the controller using named ID tags in the template. Here's a simple example:

example.html

<h1>This is our email address</h1>
<p id="admin-email">admin@email.com</p>

So as it is, it's a perfectly readable template with no clutter. The "admin@email.com" text is really just to make the template more understandable. The controller method will later replace the contents of this <p> tag with the actual data. We'll learn more about that in the next section.

Formatting Elements

A typical situation in any web app is to grab an object from the model and format (populate) your template with that data.

Here's an example template to display our customer-info:

customer-info.html

Title: Customer Info

<h1>Customer Info</h1>

<div id="customer-info">
  <p>Name: (customer.name)</p>
  <p>Email: (customer.email)</p>
  <p>Phone: (customer.phone)</p>
</div>

The corresponding controller method will replace these placeholders with actual data.

So the two primary ways of getting data into a template are: 1) Give an element a named id attribute 2) Use (foo.bar) style placeholders where "foo" is the name of the object and "bar" is the attribute.

The ZenTools template placeholders are quite natural and understandable even to non-programmers who might need to occasionally make simple tweaks to the template. You can use as many (foo.bar) formatted placeholders as you want without fear of breaking anything. If there's no controller method trying to format those placeholders, they are simply ignored and treated as normal text. This means you can easily create your templates as you like, then come back and add the controller code later.

Formatting Rows

What if you want to display a list of customers? One for each record in the database? Rather than cluttering up our template code with loops and formatting logic, we'll just create one row as a template and give it a name. Then let the controller method do all the heavy lifting from behind the scenes. Here's an example of a customers list page with a table containing rows of customer records.

customers-list.html

Title: Customers

<h1>Customers</h1>

<table>
  <tr>
    <th>Name</th>
    <th>Email</th>
    <th>Phone</th>
  </tr>
  <tr id="customer-row">
    <td>(customer.name)</td>
    <td>(customer.email)</td>
    <td>(customer.phone)</td>
  </tr>
</table>

Notice that the template row has a named id="customer-row". By simply giving a named id attribute to the row, we've provided the necessary hook for the controller code to grab that row and use it as a template for cloning and formatting the placeholders with real data.

Forms

To make forms easily populated and manipulated from the controller method, just make your HTML form as you normally would, making sure to give the form tag a named id attribute. For the elements within the form, ZenTools uses the name attributes for receiving data as well as for populating those elements. Here's what a typical form might look like:

new-customer.html

Title: New Customer

<h1>New Customer</h1>

<form id="customer-form" action="" method="post">
  <div>
    <label>Name</label>
    <input type="text" name="name" />
  </div>
  <div>
    <label>Email</label>
    <input type="text" name="email" />
  </div>
  <div>
    <label>Phone</label>
    <input type="text" name="phone" />
  </div>
</form>

Note that the form elements are self-closing HTML style tags (with space and slash before the final caret). This is not only good coding practice for modern HTML, it's also required for ZenTools to be able to target these form elements. So make sure you use 'em! This is worth repeating:

You must use HTML self-closing tags in ZenTools form templates in order for the controller to populate them correctly!

In the next section we'll look at how to use controllers to format our templates, work with forms and much more.


Next: 05 - Controllers