Template code Chunk output
{#example_1}
<ul>

{.loop in $list as $item}
 <li>{$item}</li>
{/loop}

</ul>
{#}
Theme theme = new Theme("examples");

// Fetch template from this file: themes/examples/loop.chtml
// Inside that file there is a template "snippet" named #example_1
Chunk html = theme.makeChunk("loop#example_1");

html.set("list", new String[]{"apples","bananas","carrots","durian"} );

html.render( out );
<ul>

 <li>apples</li>
 <li>bananas</li>
 <li>carrots</li>
 <li>durian</li>

</ul>

  • apples
  • bananas
  • carrots
  • durian
Template code Chunk output
{#example_2}
<div id="widget-list">

<h2>Widgets</h2>

{.loop in $widgets}
 <div>
  {$widget_id}
  {$widget_name}
 </div>
{.onEmpty}
{!-- Always provide an onEmpty block in case $widgets is empty/null --}
 <div><i>No widgets found!</i></div>
{/loop}

</div>



<div id="wodget-list">

<h2>Wodgets</h2>

{.loop in $wodgets}
 <div>
  {$wodget_id}
  {$wodget_name}
 </div>
{.onEmpty}
 <div><i>No wodgets found!</i></div>
{/loop}

</div>
{#}
Theme theme = new Theme("examples");

// Fetch template from this file: themes/examples/loop.chtml
// Inside that file there is a template "snippet" named #example_2
Chunk html = theme.makeChunk("loop#example_2");

// getWidgets() might return an array/list of Map objects
// or an array/list of objects that implement com.x5.util.DataCapsule
// or an object that implements com.x5.util.TableData
//
html.set("widgets", getWidgets() );

// Templates are *not* allowed to invoke object methods directly!
// So for example, you can't just place objects directly into the
// chunk with .set() and expect to have access to the public methods
// of the Widget class from the template:
//
//    Widget w = new Widget();
//    html.set("widget", w);
//
//    Widget[] widgetsForSale = getWidgetsForSale();
//    html.set("widgets", widgetsForSale);
//
// Why? It violate separation-of-concerns. Your code would get ugly, fast.
//
// Not to worry, gluing your custom object into the template doesn't have
// to be busy work. If your class implements com.x5.util.DataCapsule,
// then you will be able to define a short list of "getter" methods
// that are safe for exposing to the template, and the code above will
// work fine.
//
// See the "Data Capsules (easy MVC)" example or the docs for more info.

html.render( out );
<div id="widget-list">

<h2>Widgets</h2>

 <div>
  1001
  Hoositwhatsit
 </div>
 <div>
  1002
  Thingamajig
 </div>
 <div>
  1003
  Gadget
 </div>
 <div>
  1004
  Bauble
 </div>
 <div>
  1005
  Bangle
 </div>

</div>



<div id="wodget-list">

<h2>Wodgets</h2>

 <div><i>No wodgets found!</i></div>

</div>

Widgets

1001 Hoositwhatsit
1002 Thingamajig
1003 Gadget
1004 Bauble
1005 Bangle

Wodgets

No wodgets found!
Template code Chunk output
{#example_3}
{!-- The {.loop in $list as $x} form is the pinnacle of readability,
  -- especially when looping over a list of objects (aka maps or
  -- associative arrays).
  --
  -- This syntax opens the door for nested loops of the same data type.
  --}
<div id="widget-list">

{.loop in $widgets as $w}
 <div id="widg_{$w.widget_id}">
  {$w.widget_id}
  {$w.widget_name}
 </div>
{/loop}

</div>
{#}
Theme theme = new Theme("examples");

// Fetch template from this file: themes/examples/loop.chtml
// Inside that file there is a template "snippet" named #example_3
Chunk html = theme.makeChunk("loop#example_3");

// {.loop} is pretty smart.
// It knows how to iterate over several different kinds of input.
//
// getWidgets() might return an array/list of Map objects (think JSON)
// or an array/list of objects that implement com.x5.util.DataCapsule
// or an object that implements com.x5.util.TableData
// or a String with tabular data in InlineTable format:
//
//    String inlineTable = "[[heading_1,heading_2,heading_3],"
//       + "[data_1,data_2,data_3],"
//       + "[data_1,data_2,data_3]]";
//
DataCapsule[] widgets = getWidgets();
html.set("widgets", widgets );

html.render( out );
<div id="widget-list">

 <div id="widg_1001">
  1001
  Hoositwhatsit
 </div>
 <div id="widg_1002">
  1002
  Thingamajig
 </div>
 <div id="widg_1003">
  1003
  Gadget
 </div>
 <div id="widg_1004">
  1004
  Bauble
 </div>
 <div id="widg_1005">
  1005
  Bangle
 </div>

</div>

1001 Hoositwhatsit
1002 Thingamajig
1003 Gadget
1004 Bauble
1005 Bangle
Template code Chunk output
{#example_4}
{!-- Sometimes you need some special css for the first and last
  -- items in a list.   Set first_last="true" in your .loop options
  -- to get {$is_first} and {$is_last} tags defined on the first and
  -- last iterations.
  --
  -- If you prefer other tag names for those flags, set the first_last
  -- argument to your preferred tag names: first_last="primero,ultimo"
  --}
<style>
#widgets .first { border-top: 1px solid blue; }
#widgets .last { border-bottom: 2px solid green; }
</style>  

<div id="widgets">

{.loop in $widgets  first_last="true"}
 <div class="{.if ($is_first)}first{/if}{.if ($is_last)}last{/if}">
  {$widget_id}
  {$widget_name}
 </div>
{/loop}

</div>
{#}
import net.minidev.json.JSONValue;

//...

Theme theme = new Theme("examples");

// Fetch template from this file: themes/examples/loop.chtml
// Inside that file there is a template "snippet" named #example_4
Chunk html = theme.makeChunk("loop#example_4");

// Sometimes a chtml snippet is a cool place to store some data.
String jsonWidgets = theme.fetch("loop#example_5");

html.set("widgets", JSONValue.parse(jsonWidgets).get("widgets") );

html.render( out );
<style>
#widgets .first { border-top: 1px solid blue; }
#widgets .last { border-bottom: 2px solid green; }
</style>  

<div id="widgets">

 <div class="">
  1001
  Hoositwhatsit
 </div>
 <div class="">
  1002
  Thingamajig
 </div>
 <div class="">
  1003
  Gadget
 </div>
 <div class="">
  1004
  Bauble
 </div>
 <div class="">
  1005
  Bangle
 </div>

</div>

1001 Hoositwhatsit
1002 Thingamajig
1003 Gadget
1004 Bauble
1005 Bangle
Template code Chunk output
{#example_5}
{ "widgets" : [ { "widget_id" : "1001", "widget_name" : "Hoositwhatsit" },
                { "widget_id" : "1002", "widget_name" : "Thingamajig" },
                { "widget_id" : "1003", "widget_name" : "Gadget" },
                { "widget_id" : "1004", "widget_name" : "Bauble" },
                { "widget_id" : "1005", "widget_name" : "Bangle" }
              ]
}
{#}
//...
{ "widgets" : [ { "widget_id" : "1001", "widget_name" : "Hoositwhatsit" },
                { "widget_id" : "1002", "widget_name" : "Thingamajig" },
                { "widget_id" : "1003", "widget_name" : "Gadget" },
                { "widget_id" : "1004", "widget_name" : "Bauble" },
                { "widget_id" : "1005", "widget_name" : "Bangle" }
              ]
}

{ "widgets" : [ { "widget_id" : "1001", "widget_name" : "Hoositwhatsit" }, { "widget_id" : "1002", "widget_name" : "Thingamajig" }, { "widget_id" : "1003", "widget_name" : "Gadget" }, { "widget_id" : "1004", "widget_name" : "Bauble" }, { "widget_id" : "1005", "widget_name" : "Bangle" } ] }