<?xml version='1.0' ?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
               "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
<!ENTITY % myvars SYSTEM "../variables.ent">
%myvars;
]>
<sect1 id="templates" xreflabel="Using Templates in OpenACS">
<title>Using Templates in OpenACS</title>

 
<authorblurb>
<para>By Pete Su</para>
</authorblurb>

<sect2 id="templates-overview">
<title>Overview</title>


<para>
The OpenACS Template System (ATS) is designed to allow developers to
cleanly separate <emphasis>application logic</emphasis> from <emphasis>display
logic</emphasis>. The intent is to have all of the logic related to
manipulating the database and other application state data in one
place, and all the logic related to displaying the state of the
application in another place.  This gives developer's quicker
customization and easier upgrades, and also allows developers and
graphic designers to work more independently.
</para>

<para>
In ATS, you write two files for every user-visible page in the
system. One is a plain <computeroutput>.tcl</computeroutput> file and the other is a
special <computeroutput>.adp</computeroutput> file. The <computeroutput>.tcl</computeroutput> file runs a
script that sets up a set of name/value bindings that we call <emphasis>data
sources</emphasis>. These <ulink url="/doc/acs-templating/guide/data.html">data sources</ulink> are generally the results of Tcl and/or database queries
or some combination thereof. The template system automatically makes
them available to the <computeroutput>.adp</computeroutput> file, or the display part of
the template, which is written in a combination of HTML, special
template related tags, and data source substitutions.
</para>

<para>
In the overall context of our example OpenACS Notes application, this
document will show you how to set up a simple templated page that
displays a form to the user for entering new notes into the system. In
later sections of the DG, we'll discuss how to develop the pages that
actually add notes to the database, how to provide a separate instance
of the Notes application to every user and how to design appropriate
access control policies for the system.
</para>


</sect2>

<sect2 id="templates-entering-notes">
<title>Entering Notes</title>


<para>
In order for the Notes application to be useful, we have to allow
users to enter data into the database. Typically, this takes two
pages: one that displays a form for data entry, and another page that
runs the code to update the database and tells the user whether the
operation failed. In this document, we will use the template system to
build the first of these pages. This isn't a very interesting use of
the system since we won't be displaying much data, but we'll cover
more on that end later.
</para>

<para>
The <computeroutput>.tcl</computeroutput> file for the form entry template is pretty
simple. Here, the only thing we need from the database is a new ID for
the note object to be inserted. Open up a file called
<computeroutput>note-add.tcl</computeroutput> in the <computeroutput>ROOT/packages/notes/www</computeroutput>
directory, and put the following code in it:
</para>

 

<programlisting>

ad_page_contract {

    Form to add a note in OpenACS Notes.

    @author Jane Coder 
    @creation-date 11 Oct 2000

} -properties {
    note_id:onevalue
    submit_label:onevalue
    target:onevalue
    page_title:onevalue
} -query {
}

set user_id [ad_verify_and_get_user_id]

db_1row user_name {
    select first_names || ' ' || last_name as user_name 
    from users
    where forum_id = :user_id
}

set page_title "Add a note for $user_name"
set submit_label "Add"
set target "note-add-2"
set note_id [db_nextval acs_object_id_seq]

ad_return_template "note-add"

</programlisting>


<para>
Some things to note about this code:
</para>

<itemizedlist>
<listitem><para>
The procedure <link linkend="tcl-doc-ad-page-contract">ad_page_contract</link> is
always the first thing a <computeroutput>.tcl</computeroutput> file calls, if it's under
the www/ directory (i.e. not a Tcl library file). It does validation
of input values from the HTTP request (i.e. form variables) and in
this case, the <computeroutput>-properties</computeroutput> clause is used to set up the
data sources that we will ship over to the <computeroutput>.adp</computeroutput> part of
the page. In this case, we only use the simplest possible kind of data
source, called a <computeroutput>onevalue</computeroutput>, which hold just a single
string value.  Later on, we'll see how to use more powerful kinds of
data sources for representing multiple rows from an SQL query.  You
also include overall documentation for the page in the contract, and
OpenACS has automatic tools that extract this documentation and make it
browsable.
</para></listitem>
<listitem><para>
After being declared in the <computeroutput>ad_page_contract</computeroutput>, each
property is just a simple Tcl variable. The template system passes the
final value of the variable to the <computeroutput>.adp</computeroutput> template when the
<computeroutput>.tcl</computeroutput> file is processed.
</para></listitem>
<listitem><para>
The call <computeroutput>ad_return_template</computeroutput> tells the template system
what <computeroutput>.adp</computeroutput> template page to fetch to display the
properties that have been processed. By default, the template system
will look for a file by the same name as the <computeroutput>.tcl</computeroutput> file
that just ran, but with an <computeroutput>.adp</computeroutput> extension.
</para></listitem>
</itemizedlist>

<para>
Next we write the corresponding <computeroutput>.adp</computeroutput> page. This page
outputs HTML for the form, and also contains placeholders whose values
are substituted in from the properties set up by the <computeroutput>.tcl</computeroutput>
file.  Create a file called <computeroutput>note-add.adp</computeroutput> in your editor,
and insert this text:
</para>

 

<programlisting>

&lt;master src="master"&gt;
&lt;property name="title"&gt;@page_title@&lt;/property&gt;
&lt;property name="context_bar"&gt;@context_bar@&lt;/property&gt;

&lt;form action=@target@&gt;
&lt;p&gt;Title: 
&lt;input type="text" name="title" value=""&gt;
&lt;/p&gt;
&lt;p&gt;Body: 
&lt;input type="text" name="title" value=""&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;center&gt;
&lt;input type=submit value="@submit_label@"&gt;
&lt;/center&gt;
&lt;/p&gt;
&lt;/form&gt;

</programlisting>


<para>
The main point to note here is: when you want to substitute a value
into a page, you put the name of the data source between two "@"
characters. Another point to note is the use of a master template:
Master templates allow you do centralize display code that is used
throughout an application in a single file. In this case, we intend to
have a master template that does the standard page headers and footers
for us - create the <computeroutput>master.adp</computeroutput> file, which looks like
this:
</para>

 

<programlisting>

&lt;%= [ad_header $title] %&gt; 
&lt;h2&gt;@title@&lt;/h2&gt; 
&lt;%= [eval ad_context_bar $context_bar] %&gt; 
&lt;hr&gt; 
&lt;slave&gt; 
&lt;br clear="all"&gt; 
&lt;%= [ad_footer] %&gt;

</programlisting>


<para>
The main subtlety in this code is the inline Tcl code for running
procs to build the header, footer, context bar, etc.  Also, note the
property substitutions that happen here, the values of which are set
up in the <computeroutput>&lt;property&gt;</computeroutput> tags in the slave page.  
</para>

<para>
After putting all these files into
<computeroutput>ROOT/packages/notes/www</computeroutput>, you should be able to go to
<computeroutput>/notes/</computeroutput> URL for your server and see the input form.
</para>


</sect2>

<sect2 id="templates-summary">
<title>Summary</title>


<para>
Templates separate application logic from display logic by requiring
the developer to write pages in two stages, one file for database
queries and application logic, and another for display. In OpenACS, the
logic part of the page is just a <computeroutput>.tcl</computeroutput> that sets up
<emphasis>data sources</emphasis> that are used by the display part of the page. The
display part of the page is an <computeroutput>.adp</computeroutput> file with some
special tags and notations for dealing with display logic and
inserting properties into the text of the page. Later on we'll get
into templates more deeply, and show how to use database queries as
data sources.
</para>

</sect2>

<sect2 id="templates-documentation">
<title>Documentation</title>
<para>
<ulink url="/doc/acs-templating/">Templating system documentation</ulink>
</para>
<para><phrase role="cvstag">($Id: templates.xml,v 1.10 2006/07/17 05:38:37 torbenb Exp $)</phrase></para>

</sect2>

</sect1>
