ht-each directive reference
Overview
The ht-each directive repeats the target HTML element once per occurrence of some template data.
When combined with template variables and other templating directives such as ht-include, ht-if, and ht-attrs, the ht-each directive is a powerful building block for defining dynamic layouts that adapt to the contents of template data.
Example
This example shows the ht-each directive being used to template navigation links in a <header> element.
1<html lang='en-US'>
2 <head>
3 <meta charset='utf-8'>
4 <title>Hello, world</title>
5 <meta name='description' content='ht-each directive reference'>
6 </head>
7 <body>
8 <header>
9 <nav>
10 <menu>
11 <a ht-each='link in ${ data.nav }' href='${ link.href }'>
12 ${ link.title, link.label, "Placeholder" }
13 </a>
14 </menu>
15 </nav>
16 <h1>ht-each</h1>
17 </header>
18 <main>
19 <h2><code>ht-each</code> directive reference</h2>
20 <p>...</p>
21 </main>
22 </body>
23</html>
Example output index.html
Let's see what happens when we process this template with the following template data.
1{
2 data: {
3 nav: [
4 { label: "Home", href: "/" },
5 { label: "Features", href: "/features/" },
6 { label: "Docs", href: "/docs/" },
7 { label: "Blog", href: "/blog/" },
8 ]
9 }
10}
The placeholder template <a> element will be cloned once for each item in the data.nav template data property (an object array).
The end result should be four (4) <a> elements dynamically generated by HyperTemplates.
1<html lang='en-US'>
2 <head>
3 <meta charset='utf-8'>
4 <title>Hello, world</title>
5 <meta name='description' content='ht-each directive reference'>
6 </head>
7 <body>
8 <header>
9 <nav>
10 <menu>
11 <a href='/'>Home</a>
12 <a href='/features/'>Features</a>
13 <a href='/docs/'>Docs</a>
14 <a href='/blog/'>Blog</a>
15 </menu>
16 </nav>
17 <h1>ht-each</h1>
18 </header>
19 <main>
20 <h2><code>ht-each</code> directive reference</h2>
21 <p>...</p>
22 </main>
23 </body>
24</html>
Specification
Supported elements
The ht-each directive can be used with any HTML element, including void elements.
1<meta ht-each='property in ${ page.metadata }' name='${ property.name }' content='${ property.value }' />
Directive syntax
The ht-each directive defines iteration expressions using the binding in ${ variable } syntax.
The binding is a name assigned to a template data property that will be passed into the nested template.
The variable is a template variable that returns a template data property.
1<a ht-each='link in ${ data.nav }' href='${ link.href }'>
In this example, the link variable will be added to the template data that gets passed in to the nested <a> template.
Template data
Three auto-generated template data properties are available during ht-each iteration:
each.indexa one-indexed integer representing the position in the loopeach.countthe count of items in the iteration window (afterht-offsetandht-limitare applied)each.totalthe total count of items in the collection
Placeholder template
An HTML element with an ht-each directive is called an "placeholder template".
Placeholder and their child elements (if any) are cloned once per iteration of the referenced template data value.
1<nav>
2 <a ht-each='link in ${ data.nav }' href='${ link.href }'>
3 ${ link.label, "Placeholder" }
4 </a>
5</nav>
In this example, the <a> element together with its child ${ link.label, "Placeholder" } text node make up an iterator template.
Limit and offset
The ht-limit and ht-offset directives can be used to configure partial iterators.
Use ht-limit to limit the number of elements generated by an ht-each iterator.
Use ht-offset to skip the first n items in the ht-each template data.
The following example shows how to configure a feed page with three "featured posts", followed by any remaining posts. Both blocks are using the same
page.feed.pagestemplate data.1<!-- Blog posts fragment --> 2<section id='blog'> 3 <style> 4 featured-posts { 5 display: grid; 6 grid-auto-flow: column; 7 grid-template-columns: 1fr 1fr 1fr; 8 } 9 recent-posts { 10 display: grid; 11 grid-auto-flow: row; 12 grid-template-columns: 1fr; 13 } 14 </style> 15 <featured-posts> 16 <a ht-each='post in ${ page.feed.pages }' ht-limit='3' href='${ post.href }'> 17 <!-- Featured Post Layout --> 18 </a> 19 </featured-posts> 20 <recent-posts> 21 <a ht-each='post in ${ page.feed.pages }' ht-offset='3' href='${ post.href }'> 22 <!-- Recent Post Layout --> 23 </a> 24 </recent-posts> 25</section>If the recent posts block should be further constrained to show a limited number of items, the
ht-limitdirective could be used alongsideht-offset.1<recent-posts> 2 <a ht-each='post in ${ page.feed.pages }' ht-offset='3' ht-limit='6' href='${ post.href }'> 3 <!-- Recent Post Layout --> 4 </a> 5</recent-posts>NOTE:
ht-limitis always applied as a count, not a range. The equivalent Javascript is anArray.slice()expression ofarr.slice(offset, offset+limit). In the example above that would bearr.slice(3, 3+6)(up to 6 items), notarr.slice(3, 6)(up to 3 items).