@variable@
construct.
The code goes into a Tcl script. In other words, a templated page
consists of two files, a Tcl part that puts its results in data
sources, and an ADP page (the template), into which these data
sources will be interpolated to yield a complete HTML page.
As usual, the Tcl page should start with a call to
ad_page_contract
. In its -properties
block you promise the data sources that your script will provide;
they were earlier called page properties, hence the
name of the option. Then your script performs all the
computations and queries needed to define these data sources. There
are special mechanisms for handling multirow data sources;
see below.
At the end of the Tcl script, you should call
ad_return_template
. The template runs after the
Tcl script, and can use these data sources.
Make sure that the fancy adp parser is enabled in your AOL ini file.
[ns/server/myserver/adp] DefaultParser=fancy
A few more hints
ns_puts
, ns_write
etc., which don't
wait till the headers are written or the page is completed; they
may act differently than you expect.
<%
%>
in the adp page.
<include>
d from
several pages. Prefer this to writing a Tcl proc that returns
HTML.
Nuts \$2.70 \[<a href="\"shoppe\">buy</a>\]
<form>
tag as always. All HTML tags can be
used in the ADP file (template).
First I take a page from the news package as an example. For
simplicity, I pick item-view
, which does not use a
<form>
. I reformatted it a bit to make three
panes fit next to each other and to line up corresponding code.
old Tcl code | new | |
---|---|---|
packages/news/www/item-view.tcl |
packages/news/www/item-view.adp |
|
# /packages/news/admin/index.tcl ad_page_contract { View a news item. @author Jon Salz (jsalz@arsdigita.com) @creation-date 11 Aug 2000 @cvs-id $Id$ } { news_item_id:integer,notnull } db_1row news_item_select { select * from news_items where news_item_id = :news_item_id } set body " [ad_header $title] <h2>$title</h2> [ad_context_bar [list "" "News"] $title] <hr> <p>Released $release_date: <blockquote> $body </blockquote> [ad_footer] " doc_return 200 text/html $body return |
ad_page_contract { View a news item. @author Jon Salz (jsalz@arsdigita.com) @creation-date 11 Aug 2000 @cvs-id $Id$ } { news_item_id:integer,notnull } -properties { body:onevalue release_date:onevalue title:onevalue header:onevalue context_bar:onevalue footer:onevalue } db_1row news_item_select { select * from news_items where news_item_id = :news_item_id } set context_bar [ad_context_bar \ [list "" "News"] $title] ad_return_template |
<master> <property name="doc(title)">@title@</property> <property name="context">@context;noquote@</property> <hr> <p>Released @release_date@: <blockquote> @body@ </blockquote> |
db_multirow
, and the repeating part of the HTML
output is produced by the <multiple>
tag. The
following example shows the part of the index
page of
the News module that uses the mechanism, not a whole page.
old Tcl code | new | |
---|---|---|
packages/news/www/index.tcl |
packages/news/www/index.adp |
|
ad_page_contract { Displays a list of available news items. @param archive_p show archived news items? @author Jon Salz (jsalz@mit.edu) @creation-date 11 Aug 2000 @cvs-id $Id$ } { } |
ad_page_contract { Displays a list of available news items. @param archive_p show archived news items? @author Jon Salz (jsalz@mit.edu) @creation-date 11 Aug 2000 @cvs-id $Id$ } { } -properties { header:onevalue context_bar:onevalue subsite_id:onevalue subsite:multirow item:multirow footer:onevalue } |
|
... | ... | ... |
append body " <ul> " db_foreach news_items_select { select news_item_id, title from news_items_obj where context_id = :subsite_id and sysdate >= release_date and ( expiration_date is null or expiration_date > sysdate) } { append body "<li><a href=" \"item-view?news_item_id="\ "$news_item_id\" >$title</a>\n" } if_no_rows { append body "<li>There are currently no news items available.\n" } append body " <p><li>You can use the <a href= \"admin/\">administration interface</a> to post a new item (there's currently no security in place). </ul> " |
db_multirow item news_items_select { select news_item_id, title from news_items_obj where context_id = :subsite_id and sysdate >= release_date and ( expiration_date is null or expiration_date > sysdate) } |
<ul> <multiple name=item> <li><a href= "item-view?news_item_id=<% %>@item.news_item_id@" >@item.title@</a> </multiple> <if @item:rowcount@ eq 0> <li>There are currently no news items available. </if> <p><li>You can use the <a href= "admin/">administration interface</a> to post a new item (there's currently no security in place). </ul> |
<if>
construct to handle
the case when no lines are returned. (The
<multiple>
loop just executes zero times.)
db_multirow
does have a code block and
an optional if_no_rows
block, just like
db_foreach
. They aren't used in the example,
though.
If you have a more complicated db_foreach, where logic is performed inside the body, then it might be helpful to build your own multirow variable. In the excert below, taken from /pvt/alerts.tcl and /pvt/alerts.adp, the foreach logic made it hard to use the db_multirow because it needed a combination of the output from sql and also the output of Tcl procedures using that value.
old Tcl code | new | |
---|---|---|
packages/acs-core-ui/www/pvt/alerts.tcl |
packages/acs-core-ui/www/pvt/alerts.adp |
|
ad_page_contract { @cvs-id $Id: migration.html,v 1.4 2017/08/07 23:48:02 gustafn Exp $ } { } |
ad_page_contract { @cvs-id $Id: migration.html,v 1.4 2017/08/07 23:48:02 gustafn Exp $ } { } -properties { header:onevalue decorate_top:onevalue ad_footer:onevalue discussion_forum_alert_p:onevalue bboard_keyword_p:onevalue bboard_rows:multirow classified_email_alert_p:onevalue classified_rows:multirow gc_system_name:onevalue } |
|
... | ... | ... |
if { [db_table_exists "bboard_email_alerts"] } { set counter 0 db_foreach alerts_list " select bea.valid_p, bea.frequency, bea.keywords, bt.topic, bea.rowid from bboard_email_alerts bea, bboard_topics bt where bea.user_id = :user_id and bea.topic_id = bt.topic_id order by bea.frequency" { incr counter if { $valid_p == "f" } { # alert has been disabled set status "Disabled" set action " <a href="\"/bboard/alert-reenable\"> " Re-enable</a>" } else { # alert is enabled set status " <font color=red>Enabled</font>" set action " <a href="\"/bboard/alert-disable\"> " Disable</a>" } append existing_alert_rows "<tr> <td>$status</td> <td>$action</td> <td>$topic</td> <td>$frequency</td>" if { [bboard_pls_blade_installed_p] == 1 } { append existing_alert_rows " <td>\"$keywords\"</td>" } append existing_alert_rows "</tr>\n" } if { $counter > 0 } { set wrote_something_p 1 set keyword_header "" if { [bboard_pls_blade_installed_p] == 1 } { set keyword_header "<th>Keywords</th>" } append page_content " <h3>Your discussion forum alerts</h3> <blockquote> <table> <tr> <th>Status</th> <th>Action</th> <th>Topic</th> <th>Frequency</th> $keyword_header </tr> $existing_alert_rows </table> </blockquote> " } } |
set discussion_forum_alert_p 0 if { [db_table_exists "bboard_email_alerts"] } { set discussion_forum_alert_p 1 set rownum 0 if { [bboard_pls_blade_installed_p] == 1 } { set bboard_keyword_p 1 } else { set bboard_keyword_p 0 } db_foreach alerts_list " select bea.valid_p, bea.frequency, bea.keywords, bt.topic, bea.rowid from bboard_email_alerts bea, bboard_topics bt where bea.user_id = :user_id and bea.topic_id = bt.topic_id order by bea.frequency" { incr rownum if { $valid_p == "f" } { # alert has been disabled for some reason set bboard_rows:[set rownum](status) "disable" set bboard_rows:[set rownum](action_url) " /bboard/alert-reenable" } else { # alert is enabled set bboard_rows:[set rownum](status) "enable" set bboard_rows:[set rownum](action_url) " /bboard/alert-disable" } set bboard_rows:[set rownum](topic) $topic set bboard_rows:[set rownum](frequency) $frequency set bboard_rows:[set rownum](keywords) $keywords } if_no_rows { set discussion_forum_alert_p 0 } set bboard_rows:rowcount $rownum } |
<if @discussion_forum_alert_p@ eq 1> <h3>Your discussion forum alerts</h3> <blockquote> <table> <tr><th>Status</th> <th>Action</th> <th>Topic</th> <th>Frequency</th> <if @bboard_keyword_p@ eq 1> <th>Keyword</th> </if> </tr> <multiple name=bboard_rows> <tr> <if @bboard_rows.status@ eq "enabled"> <td><font color=red>Enabled</font></td> <td><a href="@bboard_rows.action_url@"> Disable</a></td> </if> <else> <td>Disabled</td> <td><a href="@bboard_rows.action_url@"> Re-enable</a></td> </else> <td>@bboard_rows.topic@</td> <td>@bboard_rows.frequency@</td> <if @bboard_rows.bboard_keyword_p@ eq 1> <td>@keyword</td> </if> </tr> </multiple> </table> </blockquote> </if> |