[stringtemplate-interest] alternating row colows

John Snyders jjsnyders at rcn.com
Fri Mar 2 06:56:39 PST 2007


comments inline

> -----Original Message-----
> From: Nate [mailto:misc at n4te.com]
> Sent: Thursday, March 01, 2007 9:54 PM
> To: John Snyders
> Cc: stringtemplate-interest at antlr.org
> Subject: Re: [stringtemplate-interest] alternating row colows
>
>
> Interesting solution, though I don't like that the controller has to
> step in for the presentation to perform "presentation only" logic.

I have found that sometimes a little presentation only logic has to go
in the controller when working with ST. I prefer this to having business
logic bleed into the presentation.

> IMO, named templates should go in a group file when multiple template
> files can use them. But if only a single template will use the named
> template, why should it be in a different file? It just makes following
> the template markup harder.

I agree in principal but would rephrase as: Common text should go in a named
template when it is used from multiple templates or multiple places in a
single template.

I put all my templates in group files so that I can have "local" templates.
Templates that are used only by the main template in the group file.

Here is a sketch of my template organization:

File WebAppBase.stg:
group WebAppBase;
page(title, content, ...) ::= <<
...
>>

table(id, data, rowTemplate) ::= <<
    ...
    $data : {
    <tr class="even">
      $(rowTemplate)(row=it)$
    </tr>
    },
    {
    <tr class="odd">
      $(rowTemplate)(row=it)$
    </tr>
    }$
    ...
>>

File SomePage.stg:
group SomePage : WebAppBase;

mypage(data, ...) ::= <<
  $page(
    title="My Page",
    content={
      ...
      $table(id="foo", data=data, rowTemplate="thisrow",...)$
      ...
    },...
  }$
>>

thisrow(row) ::= <<
  ...
>>

Notice that group SomePage extends WebAppBase as do all my pages. I put
named templates that are used by many pages in the base group and templates
that are only needed by a single page go in that page group like thisrow.

> It would be great it I could do this...
>
> $columns = {
>     <td>$it.firstName$</td>
>     <td>$it.firstName$</td>
>     <td>$it.address$</td>
> }$
> $stuff:
>     {<tr>$it:columns()$</tr>},
>     {<tr class="odd">$it:columns()$</tr>}
> $

You can achieve the same intent using a group file as shown above.
To create a template with the name columns do this
columns(it) ::= <<
    <td>$it.firstName$</td>
    <td>$it.firstName$</td>
    <td>$it.address$</td>
>>

It is just different syntax and you have to move to a group file format.

> Another use for declaring inline templates is that then you could pass a
> template to another. Eg, I recently tried this...
>
> $outputTable(
>     headers=["Name", "Address"],
>     data=stuff,
>     columnsTemplate={
>         <td>$it.firstName$</td>
>         <td>$it.firstName$</td>
>         <td>$it.address$</td>
>     }
> )$
>
> I believe this fails because the inline template is evaluated
> immediately and the result is passed as a value. Maybe this could be
> written like this...
>
> $columnsTemplate={
>     <td>$it.firstName$</td>
>     <td>$it.firstName$</td>
>     <td>$it.address$</td>
> }$
> $outputTable(
>     headers=["Name", "Address"],
>     data=stuff,
>     columnsTemplate=columnsTemplate
> )$

I did it above by passing the name of the template and using the
$(templatename)()$ syntax.

Does anyone know if there is a better way?
Should there be a better way?

> On a separate note, I tried this...
>
> simpleTemplate (stuff) ::= <<
>     first: $stuff:{$it$}$
>     second: $stuff:{$it$}$
>  >>
>
> ...
>
> $simpleTemplate(stuff=[1,2,3,4])$
>
> The output is...
>
> first: 1234
> second:
>
> The reason seems to be that the inline list is turned into an iterator,
> so naturally the second time it is accessed hasNext() will be false. :(

I reported this bug previously
http://www.antlr.org:8080/pipermail/stringtemplate-interest/2006-September/0
00688.html

The ST implementation needs to stop passing iterators around. For the same
reason Java 1.5 added interface Iterable to support the new for each syntax
ST needs something similar.

> -Nate
>
>
> John Snyders wrote:
> > I'm not sure I agree with the desire to keep everything in one
> file and not
> > use group files.
> >
> > In my own HTML generation with ST I quickly found that group
> files were the
> > best option. Fine grained templates provide consistency. For
> example to make
> > sure that label elements are always used with text input
> elements you would
> > create a template that includes both label and input and wires
> them together
> > with the for attribute on label. Then call that template
> everywhere you need
> > to prompt for a text string. The named templates in a group
> file serve the
> > same purpose as tag libraries in JSP.
> >
> > Anyway, here is a thought of how to do it with parallel list iteration.
> > The controler would create a collection that contains an
> alternating list of
> > red, green that is the same size as the stuff collection. Call
> the attribute
> > tableclass.
> >
> > $stuff, tableclass : { it, c |
> >      <tr class="$c$">
> >         <td>$it.firstName$</td>
> >         <td>$it.lastName$</td>
> >         <td>$it.address$</td>
> >      </tr> }$
> >
> > It is not necessary to actually store in memory the full tableclass as a
> > collection. Don't use ArrayList for example, create your own
> implementation
> > that just stores the things to alternate between and the number
> of items in
> > the virtual collection. Then provide a custom iterator.
> >
> > I got this idea from your smarty example. I never heard of
> smarty before.
> > I'll go check it out.
> >
> > Thanks,
> > -John
> >
> >
> >> -----Original Message-----
> >> From: stringtemplate-interest-bounces at antlr.org
> >> [mailto:stringtemplate-interest-bounces at antlr.org]On Behalf Of Nate
> >> Sent: Thursday, March 01, 2007 7:31 PM
> >> To: stringtemplate-interest at antlr.org
> >> Subject: [stringtemplate-interest] alternating row colows
> >>
> >>
> >> I know ST supports alternating templates, eg...
> >>
> >> $stuff:redRow(),greenRow()$
> >>
> >> However, I don't see this as being useful for rendering an HTML table
> >> with alternating row colors. Am I expected to do the following?
> >>
> >> $stuff:{
> >>     <tr class="red">
> >>        <td>$it.firstName$</td>
> >>        <td>$it.lastName$</td>
> >>        <td>$it.address$</td>
> >>     </tr>
> >> },{
> >>     <tr class="green">
> >>        <td>$it.firstName$</td>
> >>        <td>$it.lastName$</td>
> >>        <td>$it.address$</td>
> >>     </tr>
> >> }$
> >>
> >> I don't want to duplicate my template just to change the row color. I
> >> don't want to put my template in another file so it can be reused. I
> >> just want to know if the current row is even or odd. This is purely
> >> presentation logic, so it should be easy. Is there an easier way to
> >> accomplish this in ST?
> >>
> >> In Smarty it is done with something like this...
> >>
> >> <tr class="{cycle values="green,red"}">
> >>    <td>$it.firstName$</td>
> >>    <td>$it.lastName$</td>
> >>    <td>$it.address$</td>
> >> </tr>
> >>
> >> -Nate


More information about the stringtemplate-interest mailing list