Now.js Framework Documentation
data-for
data-for
Overview
data-for renders a list of elements by iterating over an array. It requires a <template> element inside that defines the structure for each item.
When to use:
- Display lists or tables from data
- Render repeated components
- Show collections of items
Why use it:
- ✅ Efficient list rendering with diffing
- ✅ Provides
indexvariable in loop - ✅ Supports nested loops
- ✅ Works with all other directives
Basic Usage
Simple List
<ul data-for="item in items">
<template>
<li data-text="item.name"></li>
</template>
</ul>With data:
{
items: [
{ name: "Apple" },
{ name: "Banana" },
{ name: "Cherry" }
]
}Output:
<ul>
<li>Apple</li>
<li>Banana</li>
<li>Cherry</li>
</ul>Syntax
<container data-for="itemVar in arrayExpression">
<template>
<!-- Item template content -->
</template>
</container>| Part | Description |
|---|---|
itemVar |
Variable name for current item |
in or of |
Keyword separator (both work) |
arrayExpression |
Data path to the array |
<template> |
Required - defines item structure |
Features
1. Access Item Properties
<div data-for="user in users">
<template>
<div class="user-card">
<h3 data-text="user.name"></h3>
<p data-text="user.email"></p>
</div>
</template>
</div>2. Index Variable
The index variable is automatically available (0-based):
<ol data-for="item in items">
<template>
<li>
<span data-text="index + 1"></span>.
<span data-text="item.name"></span>
</li>
</template>
</ol>Output:
<ol>
<li>1. Apple</li>
<li>2. Banana</li>
<li>3. Cherry</li>
</ol>3. Using of Keyword
Both in and of keywords work:
<!-- Both are equivalent -->
<div data-for="item in items">...</div>
<div data-for="item of items">...</div>4. Nested Arrays
<div data-for="category in categories">
<template>
<h2 data-text="category.name"></h2>
<ul data-for="product in category.products">
<template>
<li data-text="product.name"></li>
</template>
</ul>
</template>
</div>5. With Other Directives
<ul data-for="item in items">
<template>
<li data-class="active:item.isActive"
data-attr="id:'item-' + index">
<span data-text="item.name"></span>
<span data-if="item.isNew" class="badge">New</span>
</li>
</template>
</ul>Advanced Examples
Product Grid
<div class="product-grid" data-for="product in products">
<template>
<div class="product-card" data-attr="id:'product-' + product.id">
<img data-attr="src:product.image, alt:product.name">
<h3 data-text="product.name"></h3>
<p class="price" data-text="product.price | currency:'THB'"></p>
<p class="stock" data-if="product.stock > 0">
In stock: <span data-text="product.stock"></span>
</p>
<p class="out-of-stock" data-if="product.stock === 0">
Out of stock
</p>
<button data-on="click:addToCart(product)"
data-attr="disabled:product.stock === 0">
Add to Cart
</button>
</div>
</template>
</div>Data Table
<table>
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Email</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody data-for="user in users">
<template>
<tr data-class="inactive:!user.isActive">
<td data-text="index + 1"></td>
<td data-text="user.name"></td>
<td data-text="user.email"></td>
<td>
<span data-class="user.isActive ? 'badge-success' : 'badge-secondary'"
data-text="user.isActive ? 'Active' : 'Inactive'">
</span>
</td>
<td>
<button data-on="click:editUser(user.id)">Edit</button>
<button data-on="click:deleteUser(user.id)">Delete</button>
</td>
</tr>
</template>
</tbody>
</table>Navigation Menu
<nav>
<ul class="menu" data-for="item in menuItems">
<template>
<li data-class="active:item.isActive, has-children:item.children.length > 0">
<a data-attr="href:item.url" data-text="item.label"></a>
<ul data-if="item.children.length > 0" class="submenu" data-for="child in item.children">
<template>
<li>
<a data-attr="href:child.url" data-text="child.label"></a>
</li>
</template>
</ul>
</li>
</template>
</ul>
</nav>Timeline
<div class="timeline" data-for="event in timeline">
<template>
<div class="timeline-item"
data-class="first:index === 0, last:index === timeline.length - 1">
<div class="timeline-marker"></div>
<div class="timeline-content">
<time data-text="event.date | date:'D MMM YYYY'"></time>
<h4 data-text="event.title"></h4>
<p data-text="event.description"></p>
</div>
</div>
</template>
</div>Comment Thread
<div class="comments" data-for="comment in comments">
<template>
<div class="comment">
<img data-attr="src:comment.author.avatar" class="avatar">
<div class="comment-body">
<strong data-text="comment.author.name"></strong>
<time data-text="comment.date | date:'relative'"></time>
<p data-text="comment.text"></p>
<!-- Nested replies -->
<div data-if="comment.replies.length > 0" class="replies" data-for="reply in comment.replies">
<template>
<div class="reply">
<strong data-text="reply.author.name"></strong>
<p data-text="reply.text"></p>
</div>
</template>
</div>
</div>
</div>
</template>
</div>API Reference
Available Variables
| Variable | Description |
|---|---|
itemVar |
Current item (user-defined name) |
index |
Current index (0-based) |
Expression Syntax
| Expression | Description |
|---|---|
item in items |
Simple array iteration |
item in data.items |
Nested array access |
item in computedItems |
Can use computed values |
Common Pitfalls
⚠️ 1. Missing Template Element
<!-- ❌ Wrong - no template -->
<ul data-for="item in items">
<li data-text="item.name"></li>
</ul>
<!-- ✅ Correct - with template -->
<ul data-for="item in items">
<template>
<li data-text="item.name"></li>
</template>
</ul>⚠️ 2. Template Must Have Single Root
<!-- ⚠️ Multiple roots will all be rendered -->
<div data-for="item in items">
<template>
<div data-text="item.title"></div>
<p data-text="item.description"></p>
</template>
</div>⚠️ 3. Item Variable Scope
<!-- ❌ item not accessible outside loop -->
<div data-for="item in items">
<template>
<span data-text="item.name"></span>
</template>
</div>
<p data-text="item.name"></p> <!-- Won't work -->⚠️ 4. Modifying Array During Iteration
// ❌ Avoid modifying array during render
for (let item of items) {
items.push(newItem); // Causes issues
}
// ✅ Create new array
const newItems = [...items, newItem];⚠️ 5. Non-Array Values
// ❌ data-for expects an array
{ items: "not an array" }
{ items: null }
// ✅ Always provide an array
{ items: [] }
{ items: [{ name: "Item" }] }Performance Tips
| Tip | Description |
|---|---|
| Avoid deeply nested loops | Flattens data when possible |
| Limit displayed items | Use pagination or virtual scrolling |
| Use simple templates | Complex templates increase render time |
| Avoid inline functions | Define functions in methods |