Now.js Framework Documentation

Now.js Framework Documentation

data-for

EN 11 Dec 2025 11:58

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 index variable 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>
<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