{tree}

Renders a tree of rows: its body for every row, and {recurse} renders it again for the row's children.

Loops and trees Tag pairs

Syntax

{tree 'rows'} ... {recurse} ... {/tree}
{tree data='rows', children='items'} ... {branch} ... {recurse} ... {/branch} ... {/tree}
{tree 'rows'} ... @else@ ... {/tree}

Parameters

rows
The name of the rows: a {data} block, a stored sequence, an array of the page or of an enclosing row, or a _data/ file. data= names them as well.

Options

children
The field of a row that holds its children, at every depth. Default children.

Description

{tree 'menu'} renders its content - the body - once for every top row, like any data tag. The difference is inside the body: {recurse} renders that same body again for the children of the current row, each child a row of its own, and so on down to any depth. Menus, category trees, folder listings and threaded comments are all one body written once.

The children of a row are the array in its children field; the children='items' option names another field, used at every depth. A row without children - the field missing or empty - renders nothing at its {recurse}. {branch} ... {/branch} renders only for a row that has children, so the <ul> around a {recurse} is left out for a leaf, and its @else@ part renders for a leaf instead.

Every list of the tree is a level named as the tree is: depth@tree is 1 for the top rows and one more per level down, and first@tree, current@tree, count@tree speak of the list being rendered. The handling options sort, where and reverse written on the tree apply to every list, the children included. The @else@ part of the tree itself shows when there are no rows at all.

Under the strict syntax check a tree without rows named, a name nothing holds, or a tree without its closing tag is an error.

Examples

A nested menu

One body renders every level; branch leaves the inner list out for a leaf.

Templateexamples/tree/1-menu.pad
{data 'treeMenu'}
[
  { "title": "Home" },
  { "title": "Shop", "children": [
      { "title": "Books" },
      { "title": "Music", "children": [ { "title": "Jazz" }, { "title": "Folk" } ] } ] },
  { "title": "Contact" }
]
{/data}
<ul>
{tree 'treeMenu'}
  <li>{$title}{branch}<ul>{recurse}</ul>{/branch}</li>
{/tree}
</ul>
Resultopen alone
  • Home
  • Shop
    • Books
    • Music
      • Jazz
      • Folk
  • Contact

Another children field, sorted, with depth

children= names the field; sort applies at every level; depth@tree counts the levels.

Templateexamples/tree/2-options.pad
<ul>
{tree data='folders', children='sub', sort='name'}
  <li>{$name} <small>(depth {depth@tree}, {current@tree} of {count@tree})</small>{branch}<ul>{recurse}</ul>{/branch}</li>
{/tree}
</ul>
PHPexamples/tree/2-options.php
<?php

  $folders = [
    [ 'name' => 'src', 'sub' => [
        [ 'name' => 'views' ],
        [ 'name' => 'models', 'sub' => [ [ 'name' => 'user' ], [ 'name' => 'order' ] ] ] ] ],
    [ 'name' => 'docs' ] ];

?>
Resultopen alone
  • docs (depth 1, 1 of 2)
  • src (depth 1, 2 of 2)
    • models (depth 2, 1 of 2)
      • order (depth 3, 1 of 2)
      • user (depth 3, 2 of 2)
    • views (depth 2, 2 of 2)

See also

  • {branch} Inside a {tree}: renders its content only when the current row has children, its @else@ part for a leaf.
  • {recurse} Inside a {tree}: renders the tree's body once more for the children of the current row.
  • {data} Turns its content - JSON, XML, YAML, CSV, a list or a range - into a named data set for a later tag to iterate.