![]() |
WebStringTemplates Previous ![]() ![]() ![]() |
For your second page, you will learn how to extract boilerplate code to
sub-templates and how to process a list of data. This page will cover:-
Sub-Templates
Processing a List
The Completed Second Page
Missing Data in Sub-Templates
For your next page you need to display a list of books from the catalog. Your Data Interface Definition file is bookcatalog.data.html. Copy this file from the manual/completedExamples sub-directory to the directory containing the RunWST jar file.
bookcatalog.data.html contains a list of books to be displayed under the path booksWithFmtPrices.
This catalog page will have the same header and footer as the previous page, so before laying out the new page, let's define two templates, one for the header and one for the footer, which we can call from any page. These included templates will be in the same directory as the main template and must end in .st. Only the main template for each page ends in .st.html. We will call these sub-templates, header.st and footer.st.
The file header.st has the following code in it.
<!-- the header -->
<center>
<img src="$[GifUrl]$">
<h1>$[Title]$</h1>
</center>
<hr>
While the file footer.st has the following code in it.
<!-- the footer -->
<hr>
<center>
$[Copyright]$
</center>
Then in the main page, include these templates with $[header()]$ and $[footer()]$, as if they were a function call. These sub-templates automatically have access to all the data the main template has access to. If you placed header.st and footer.st in a sub-directory you will need to add the relative path from the main template, e.g. $[utils/header()]$. Note: you must use Unix style path separaters, /, and you cannot use ./ or ../ in the path.
The first attempt at bookcatalog.st.html then contains the code
<HTML>
<HEAD>
<TITLE>$[Title]$</TITLE>
</HEAD>
<BODY>
$[header()]$
$[footer()]$
</BODY>
</HTML>
Now run RunWST using the command line
java -jar RunWST-1.5.jar bookcatalog
The list of books is shown as an ordered list. You cannot access the individual elements of the list using the index shown. This is by design. It prevents you from making any assumptions about how many books will be in the list. As you will see next, WebStringTemplates provides a straight forward means of looping through all the elements in a list. The initial output page, with just the header and footer is shown here.
To process a list you first get the list data using its path (in this example booksWithFmtPrices) and then you use the : (colon) syntax to pass each element, one at a time to a sub-template for individual processing. For example
$[booksWithFmtPrices:catalogRow()]$
This command passes each element of the booksWithFmtPrices list, one at a time, to the sub-template catalogRow.st for processing. In catalogRow.st, the element passed can be accessed using the data path attr. The index of the element is also passed to the sub-template in the data path list_i.
Let's start by defining a simple catalogRow.st which just outputs the book title on a new line. In a new file catalogRow.st put the following
<br>$[attr]$
Note that attr holds each list element, in order. Each list element has an overall string description, shown above under blank tab below each list item.
Adding $[booksWithFmtPrices:catalogRow()]$
between the header
and footer in bookcatalog.st.html gives
<HTML>
<HEAD>
<TITLE>$[Title]$</TITLE>
</HEAD>
<BODY>
$[header()]$
<!-- the main part -->
$[booksWithFmtPrices:catalogRow()]$
$[footer()]$
</BODY>
</HTML>
The output file is now updated to this.
If you wanted to display the row number as well, you could edit catalogRow.st to
<br>$[list_i]$. $[attr]$
which gives this output.
The attribute list_i is only defined if you are processing a list using the : syntax. Two other attributes that are only defined when you are processing a list are:- list_first and list_last. list_first is "true" if this is the first item in the list and "false" otherwise. list_last is "true" if this is the last item in the list and "false" otherwise. You can use these attributes in $[if( )]$ statements to add extra code, depending on whether this is the first or last or middle element in a list.
The list processing syntax :, can be used even if the data is not a list. In that case the single data item is converted to a one element list before being passed for processing.
Now that you know how to handle each item in a list, finish the catalog page to show the bookRow.title linked to the detailsUrl together with the author's name (bookRow.surname), the normal price (fmtPrice) and an "add to cart" link using the CartAdd text and addUrl for each book. You will need to copy the manual/completedExamples/images/forwardSmaller.gif to an images sub-directory, if you have not already done so.
Here is my simple bookcatalog.st.html template which uses a table. (In the manual/completedExamples sub-directory this template is called bookcatalogList.st.html.) It produces this output page
and this is the catalogRow.st file. I actually used two sub-templates, one called catalogTable.st, which has the start and end table tags and which calls the second one, catalogRow.st, for each book. (These files are called catalogRowList.st and catalogTableList.st in the manual/completedExamples sub-directory.)
One of the reasons I did this was because some html editors will throw
away empty tables like
<table>
$[booksWithFmtPrices:catalogRow()]$
</table>
Putting these tags in a sub-template protected them from being cleaned up before I added the final table's headings.
If you try and access data from a sub-template that does not exist, the data path in the error return string is updated to give you more information on what was passed to the sub-template and which sub-template the error occurred in.
In catalogRow.st, try changing the $[By]$ to $[Buy]$ and the $[attr.bookRow.surname]$ to $[attr.booksRow.surname]$, i.e.
<td><a
href="$[attr.detailsUrl]$">$[attr.bookRow.title]$</a>
$[Buy]$
$[attr.booksRow.surname]$</td>
Refresh the output and you will see an output like the following in your output.html web page.
Core Java Vol I - Fundamentals $[Buy]$
$[booksWithFmtPrices.1.catalogRow_st.attr.booksRow.surname]$
$[Buy]$ indicates WebStringTemplates is looking for the Buy data in the main template's data store and cannot find it.
To understand the error path $[booksWithFmtPrices.1.catalogRow_st.attr.booksRow.surname]$, start from the end.
WebStringTemplates is looking for surname in
booksRow. This is the error as booksRow
does not exist. It should be bookRow.
booksRow is being searched for in attr.
attr is the default name for a each element of the list as
it is processed by : and passed to the sub-template.
attr is in the catalogRow.st sub-template as indicated by
the catalogRow_st entry in the error path.
catalogRow.st was passed the first item in a list, as shown by the
1.
This list was from the data booksWithFmtPrices in the main
template's data store.
What is not shown here is that booksWithFmtPrices was passed from the sub-template catalogTable.st. That you have to work out for yourself.
Now in catalogTable.st try changing
$[booksWithFmtPrices:catalogRow()]$
to$[booksWithPrices:catalogRow()]$
You can leave the other error
in or not as you wish. Refresh the output and you will see a lot of error
paths. The first one looks like
$[booksWithPrices.catalogRow_st.attr.bookRow.title]$
Again starting from the end of the error path and working back you can see that catalogRow.st was passed the data from booksWithPrices. This data was not found and so there was no list to process, the missing reference was just passed on to catalogRow.st.
On the next page you will be introduced to the last few features necessary to use WebStringTemplates to design your web page templates.
![]() |
WebStringTemplates Previous ![]() ![]() ![]() |