Template code Chunk output
{#example_1}
<ul>

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

</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>
{% endloop %}

</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>
{% endloop %}

</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 %} syntax is the preferred form.
  -- The "as" makes your loop template more readable, especially 
  -- when looping over a list of objects (aka maps, dictionaries,
  -- associative arrays, parameter bags, etc).
  --
  -- Without the "as" clause, it is not even possible to nest loops
  -- over similar data types, since the unprefixed attribute tags
  -- from the inner and outer loops would collide. Inner loop
  -- scope always takes precedence.
  --}
<div id="widget-list">

{% loop in $widgets as $w %}
  <div class="widget widg_{$w.widget_id}">
    {$w.widget_id}
    {$w.widget_name}
    {% if ($w.related_widgets|len != 0) %}
      <div class="related">
        <h2>Related Widgets:</h2>
      {% loop in $w.related_widgets as $r %}
        <div class="related_widget related_widg_{$r.widget_id}">
          {$r.widget_id}
          {$r.widget_name}
        </div>
      {% onEmpty %}
      {% endloop %}
      </div>
    {% endif %}
  </div>
{% endloop %}

</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 class="widget widg_1001">
    1001
    Hoositwhatsit
      <div class="related">
        <h2>Related Widgets:</h2>
        <div class="related_widget related_widg_1002">
          1002
          Thingamajig
        </div>
        <div class="related_widget related_widg_1003">
          1003
          Gadget
        </div>
      </div>
  </div>
  <div class="widget widg_1002">
    1002
    Thingamajig
  </div>
  <div class="widget widg_1003">
    1003
    Gadget
  </div>
  <div class="widget widg_1004">
    1004
    Bauble
  </div>
  <div class="widget 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 three special tags:
  --
  --   {$first} is defined on the first iteration.
  --   {$last} is defined on the final iteration.
  --   {$place} is "first" or "" or "last" as appropriate.
  --
  -- If you prefer other tag names for those flags, set the first_last
  -- argument to your preferred tag names:
  --   first_last="primero,ultimo,puesto"
  --
  -- Note the use of the rpad filter (new in 2.6.4) to append
  -- a space only when the tag value is non-empty.
  --}
<style>
.widgets .first { border-top: 1px solid blue; }
.widgets .last { border-bottom: 2px solid green; }
</style>  

<div class="widgets">

{% loop in $widgets  first_last="true" %}
 <div class="{$place|rpad}widget">
  {$widget_id}
  {$widget_name}
 </div>
{% endloop %}

</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_7");

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 class="widgets">

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

</div>

1001 Hoositwhatsit
1002 Thingamajig
1003 Gadget
1004 Bauble
1005 Bangle
Template code Chunk output
{#example_5}
{!-- Customized tags example --}
<style>
.widgets .primero { border-top: 1px solid blue; }
.widgets .ultimo { border-bottom: 2px solid green; }
</style>

<div class="widgets">

{% loop in $widgets  first_last="primero,ultimo,puesto" %}
 <div class="{$puesto|rpad}widget">
  {$widget_id}
  {$widget_name}
 </div>
{% endloop %}

</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_7");

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

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

<div class="widgets">

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

</div>

1001 Hoositwhatsit
1002 Thingamajig
1003 Gadget
1004 Bauble
1005 Bangle