Lists & Repetition
List attributes allow you to render arrays of data by repeating HTML elements. Combined with filtering and sorting, you can create powerful dynamic lists.
dbind_repeat
Purpose: Repeat an element for each item in an array. This is essential for rendering lists, grids, and tables from your data.
Syntax:
<element dbind_repeat="arrayField">
<!-- This entire element is repeated for each item -->
</element>
How It Works
- DBindly finds the element with
dbind_repeat - The element becomes a template
- For each item in the array, a copy of the template is created
- Inside each copy, data bindings refer to the current item
Basic Usage
<!-- Simple list -->
<ul>
<li dbind_repeat="items" dbind_data="name"></li>
</ul>
Data:
{
"items": [
{ "name": "Apple" },
{ "name": "Banana" },
{ "name": "Cherry" }
]
}
Result:
<ul>
<li>Apple</li>
<li>Banana</li>
<li>Cherry</li>
</ul>
Accessing Item Properties
Inside a repeated element, use field names directly (no array notation):
<div dbind_repeat="products">
<h3 dbind_data="name"></h3>
<p dbind_data="description"></p>
<span dbind_data="price" dbind_format="currency:USD"></span>
<img dbind_src="image" dbind_alt="name">
</div>
Data:
{
"products": [
{
"name": "Headphones",
"description": "Premium wireless audio",
"price": 149.99,
"image": "/images/headphones.jpg"
},
{
"name": "Keyboard",
"description": "Mechanical RGB keyboard",
"price": 89.99,
"image": "/images/keyboard.jpg"
}
]
}
Nested Properties
Access nested data within each item:
<div dbind_repeat="users">
<h3 dbind_data="name"></h3>
<span dbind_data="address.city"></span>
<span dbind_data="address.country"></span>
<img dbind_src="profile.avatar" dbind_alt="name">
</div>
Data:
{
"users": [
{
"name": "John Doe",
"address": {
"city": "New York",
"country": "USA"
},
"profile": {
"avatar": "/avatars/john.jpg"
}
}
]
}
Special Loop Variables
Inside dbind_repeat, you can access special variables:
| Variable | Description | Example |
|---|---|---|
_index | Zero-based index (0, 1, 2, ...) | {{_index}} |
_number | One-based number (1, 2, 3, ...) | {{_number}} |
_first | Boolean, true for first item | dbind_show="_first" |
_last | Boolean, true for last item | dbind_show="_last" |
_even | Boolean, true for even indexes | dbind_class="evenClass" |
_odd | Boolean, true for odd indexes | dbind_class="oddClass" |
<div dbind_repeat="items">
<span class="number">{{_number}}.</span>
<span dbind_data="name"></span>
<span dbind_show="_first" class="badge">First!</span>
<span dbind_show="_last" class="badge">Last!</span>
</div>
Result:
<div>
<span class="number">1.</span>
<span>Apple</span>
<span class="badge">First!</span>
</div>
<div>
<span class="number">2.</span>
<span>Banana</span>
</div>
<div>
<span class="number">3.</span>
<span>Cherry</span>
<span class="badge">Last!</span>
</div>
Use Cases
1. Product Grid
<div class="product-grid" dbind_repeat="products">
<article class="product-card">
<img dbind_src="image" dbind_alt="name" loading="lazy">
<h3 dbind_data="name"></h3>
<p dbind_data="description"></p>
<div class="price-rating">
<span dbind_data="price" dbind_format="currency:USD"></span>
<span dbind_data="rating">★</span>
</div>
<a dbind_href="url" class="btn-view">View Details</a>
</article>
</div>
2. Navigation Menu
<nav class="main-nav">
<a dbind_repeat="menuItems" dbind_href="url" dbind_data="label" class="nav-link"></a>
</nav>
3. Feature List
<ul class="feature-list">
<li dbind_repeat="features">
<span class="icon" dbind_data="icon"></span>
<strong dbind_data="title"></strong>
<p dbind_data="description"></p>
</li>
</ul>
4. Team Members
<div class="team-grid">
<div dbind_repeat="team" class="team-member">
<img dbind_src="photo" dbind_alt="name" class="avatar">
<h4 dbind_data="name"></h4>
<span class="title" dbind_data="jobTitle"></span>
<div class="social-links">
<a dbind_href="twitter" dbind_show="twitter">Twitter</a>
<a dbind_href="linkedin" dbind_show="linkedin">LinkedIn</a>
</div>
</div>
</div>
5. Blog Post List
<div class="blog-posts">
<article dbind_repeat="posts" class="post-card">
<img dbind_src="featuredImage" dbind_alt="title" class="post-image">
<div class="post-meta">
<span class="category" dbind_data="category"></span>
<time dbind_data="publishedAt" dbind_format="date:medium"></time>
</div>
<h2 dbind_data="title"></h2>
<p dbind_data="excerpt"></p>
<div class="post-footer">
<span class="author" dbind_data="author.name"></span>
<a dbind_href="url">Read More →</a>
</div>
</article>
</div>
6. Data Table
<table class="data-table">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Email</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr dbind_repeat="users">
<td>{{_number}}</td>
<td dbind_data="name"></td>
<td dbind_data="email"></td>
<td>
<span class="status-badge" dbind_class="statusClass" dbind_data="status"></span>
</td>
</tr>
</tbody>
</table>
7. Alternating Row Colors
<div dbind_repeat="items" class="row" dbind_class="rowClass">
<span dbind_data="name"></span>
</div>
Data:
{
"items": [
{ "name": "Row 1", "rowClass": "row-odd" },
{ "name": "Row 2", "rowClass": "row-even" },
{ "name": "Row 3", "rowClass": "row-odd" }
]
}
Or use _even / _odd:
<div dbind_repeat="items" class="row">
<span dbind_show="_odd" class="odd-indicator">●</span>
<span dbind_data="name"></span>
</div>
dbind_repeat-empty
Purpose: Provide fallback content when the repeated array is empty. This is an alias for dbind_empty that's more semantically clear when used with lists.
Syntax:
<element dbind_repeat-empty="arrayField">
<!-- Shown when arrayField is empty or missing -->
</element>
Basic Usage
<!-- Product list -->
<div class="products">
<div dbind_repeat="products" class="product-card">
<h3 dbind_data="name"></h3>
</div>
</div>
<!-- Empty state -->
<div class="empty-state" dbind_repeat-empty="products">
<img src="/images/no-products.svg" alt="No products">
<h3>No products found</h3>
<p>Try adjusting your search or filters.</p>
</div>
Use Cases
1. Search Results Empty State
<div class="search-container">
<input type="text" dbind_search="results" placeholder="Search...">
<div class="results-list">
<div dbind_repeat="results" class="result-item">
<h4 dbind_data="title"></h4>
<p dbind_data="snippet"></p>
</div>
</div>
<div class="no-results" dbind_repeat-empty="results">
<img src="/images/no-results.svg" alt="">
<h3>No results found</h3>
<p>We couldn't find anything matching your search.</p>
<button onclick="clearSearch()">Clear Search</button>
</div>
</div>
2. Empty Shopping Cart
<div class="cart-items">
<div dbind_repeat="cartItems" class="cart-item">
<img dbind_src="image" dbind_alt="name">
<span dbind_data="name"></span>
<span dbind_data="price" dbind_format="currency:USD"></span>
</div>
</div>
<div class="empty-cart" dbind_repeat-empty="cartItems">
<span class="cart-icon">🛒</span>
<h2>Your cart is empty</h2>
<p>Looks like you haven't added anything yet.</p>
<a href="/products" class="btn-primary">Start Shopping</a>
</div>
3. Empty Dashboard
<div class="dashboard-grid">
<div dbind_repeat="projects" class="project-card">
<h3 dbind_data="name"></h3>
<p dbind_data="description"></p>
</div>
</div>
<div class="getting-started" dbind_repeat-empty="projects">
<h2>Welcome! Let's create your first project.</h2>
<div class="steps">
<div class="step">
<span class="step-number">1</span>
<p>Click "New Project" to get started</p>
</div>
<div class="step">
<span class="step-number">2</span>
<p>Give your project a name and description</p>
</div>
<div class="step">
<span class="step-number">3</span>
<p>Invite your team members</p>
</div>
</div>
<button class="btn-primary">+ Create Project</button>
</div>
dbind_filter
Purpose: Filter the repeated items to show only those matching a condition.
Syntax:
<!-- Filter by exact field value -->
<element dbind_repeat="items" dbind_filter="field:value"></element>
<!-- Filter by multiple values -->
<element dbind_repeat="items" dbind_filter="field:value1,value2"></element>
Basic Usage
<!-- Show only active products -->
<div dbind_repeat="products" dbind_filter="status:active">
<h3 dbind_data="name"></h3>
</div>
<!-- Show only electronics category -->
<div dbind_repeat="products" dbind_filter="category:electronics">
<h3 dbind_data="name"></h3>
</div>
Data:
{
"products": [
{ "name": "Laptop", "category": "electronics", "status": "active" },
{ "name": "Shirt", "category": "clothing", "status": "active" },
{ "name": "Phone", "category": "electronics", "status": "inactive" }
]
}
Result (electronics filter):
<div><h3>Laptop</h3></div>
<div><h3>Phone</h3></div>
Multiple Value Matching
<!-- Show electronics OR clothing -->
<div dbind_repeat="products" dbind_filter="category:electronics,clothing">
<h3 dbind_data="name"></h3>
</div>
Use Cases
1. Category Tabs
<div class="category-tabs">
<button data-category="all">All</button>
<button data-category="electronics">Electronics</button>
<button data-category="clothing">Clothing</button>
</div>
<!-- Show all products (no filter) -->
<div id="all-products" dbind_repeat="products">
<div class="product" dbind_data="name"></div>
</div>
<!-- Show only electronics -->
<div id="electronics" dbind_repeat="products" dbind_filter="category:electronics" style="display:none;">
<div class="product" dbind_data="name"></div>
</div>
<!-- Show only clothing -->
<div id="clothing" dbind_repeat="products" dbind_filter="category:clothing" style="display:none;">
<div class="product" dbind_data="name"></div>
</div>
2. Status Sections
<!-- Active tasks -->
<section class="active-tasks">
<h2>Active Tasks</h2>
<div dbind_repeat="tasks" dbind_filter="status:active">
<div class="task" dbind_data="title"></div>
</div>
</section>
<!-- Completed tasks -->
<section class="completed-tasks">
<h2>Completed</h2>
<div dbind_repeat="tasks" dbind_filter="status:completed">
<div class="task completed" dbind_data="title"></div>
</div>
</section>
3. Featured Products
<!-- Featured products section -->
<section class="featured">
<h2>Featured Products</h2>
<div dbind_repeat="products" dbind_filter="featured:true">
<div class="product-card featured">
<h3 dbind_data="name"></h3>
</div>
</div>
</section>
<!-- Regular products -->
<section class="all-products">
<h2>All Products</h2>
<div dbind_repeat="products">
<div class="product-card">
<h3 dbind_data="name"></h3>
</div>
</div>
</section>
dbind_sort
Purpose: Sort the repeated items by a field value.
Syntax:
<!-- Sort ascending (default) -->
<element dbind_repeat="items" dbind_sort="field"></element>
<!-- Sort descending -->
<element dbind_repeat="items" dbind_sort="field:desc"></element>
<!-- Sort ascending explicitly -->
<element dbind_repeat="items" dbind_sort="field:asc"></element>
Basic Usage
<!-- Sort by name alphabetically -->
<div dbind_repeat="products" dbind_sort="name">
<h3 dbind_data="name"></h3>
</div>
<!-- Sort by price (highest first) -->
<div dbind_repeat="products" dbind_sort="price:desc">
<h3 dbind_data="name"></h3>
<span dbind_data="price" dbind_format="currency:USD"></span>
</div>
<!-- Sort by date (newest first) -->
<div dbind_repeat="posts" dbind_sort="publishedAt:desc">
<h2 dbind_data="title"></h2>
<time dbind_data="publishedAt" dbind_format="date:medium"></time>
</div>
Use Cases
1. Leaderboard
<div class="leaderboard">
<h2>Top Players</h2>
<div dbind_repeat="players" dbind_sort="score:desc">
<div class="player-row">
<span class="rank">{{_number}}</span>
<span class="name" dbind_data="name"></span>
<span class="score" dbind_data="score"></span>
</div>
</div>
</div>
2. Product List with Sort Options
<select id="sort-select" onchange="updateSort()">
<option value="name:asc">Name (A-Z)</option>
<option value="name:desc">Name (Z-A)</option>
<option value="price:asc">Price (Low to High)</option>
<option value="price:desc">Price (High to Low)</option>
<option value="rating:desc">Best Rated</option>
</select>
<!-- Default: Sort by name -->
<div id="products-by-name" dbind_repeat="products" dbind_sort="name">
<div class="product" dbind_data="name"></div>
</div>
3. Blog Posts by Date
<div class="blog-posts" dbind_repeat="posts" dbind_sort="createdAt:desc">
<article class="post">
<time dbind_data="createdAt" dbind_format="date:long"></time>
<h2 dbind_data="title"></h2>
</article>
</div>
Combining Sort with Filter
<!-- Featured products, sorted by price -->
<div dbind_repeat="products" dbind_filter="featured:true" dbind_sort="price:asc">
<div class="product-card">
<h3 dbind_data="name"></h3>
<span dbind_data="price" dbind_format="currency:USD"></span>
</div>
</div>
dbind_limit
Purpose: Limit the number of items displayed from the repeated array.
Syntax:
<element dbind_repeat="items" dbind_limit="number"></element>
Basic Usage
<!-- Show only first 3 products -->
<div dbind_repeat="products" dbind_limit="3">
<div class="product" dbind_data="name"></div>
</div>
Use Cases
1. Featured Section (Top N Items)
<section class="featured-products">
<h2>Top 4 Products</h2>
<div class="product-grid" dbind_repeat="products" dbind_sort="sales:desc" dbind_limit="4">
<div class="product-card">
<h3 dbind_data="name"></h3>
</div>
</div>
<a href="/products">View All Products →</a>
</section>
2. Recent Posts Widget
<aside class="recent-posts">
<h3>Recent Posts</h3>
<ul dbind_repeat="posts" dbind_sort="publishedAt:desc" dbind_limit="5">
<li>
<a dbind_href="url" dbind_data="title"></a>
<time dbind_data="publishedAt" dbind_format="date:relative"></time>
</li>
</ul>
</aside>
3. Preview with "Show More"
<div class="comments-section">
<!-- Initial 3 comments -->
<div id="comments-preview" dbind_repeat="comments" dbind_limit="3">
<div class="comment">
<strong dbind_data="author"></strong>
<p dbind_data="text"></p>
</div>
</div>
<button id="show-all-comments" onclick="showAllComments()">
Show all <span dbind_data="comments.length"></span> comments
</button>
</div>
4. Top Contributors
<div class="top-contributors">
<h3>Top 5 Contributors</h3>
<div dbind_repeat="contributors" dbind_sort="contributions:desc" dbind_limit="5">
<div class="contributor">
<img dbind_src="avatar" dbind_alt="name" class="avatar">
<span dbind_data="name"></span>
<span class="contributions" dbind_data="contributions"></span>
</div>
</div>
</div>
Combining Limit with Filter and Sort
<!-- Top 3 active products by rating -->
<div dbind_repeat="products" dbind_filter="status:active" dbind_sort="rating:desc" dbind_limit="3">
<div class="product">
<h3 dbind_data="name"></h3>
<span class="rating" dbind_data="rating">⭐</span>
</div>
</div>
Nested Lists
You can nest dbind_repeat to render hierarchical data:
Basic Nested Example
<div dbind_repeat="categories">
<h2 dbind_data="name"></h2>
<div class="products" dbind_repeat="products">
<div class="product" dbind_data="name"></div>
</div>
</div>
Data:
{
"categories": [
{
"name": "Electronics",
"products": [
{ "name": "Laptop" },
{ "name": "Phone" }
]
},
{
"name": "Clothing",
"products": [
{ "name": "T-Shirt" },
{ "name": "Jeans" }
]
}
]
}
Use Cases for Nested Lists
1. Accordion Menu
<div class="accordion-menu">
<div dbind_repeat="sections" class="accordion-section">
<h3 class="section-header" dbind_data="title"></h3>
<ul class="section-content">
<li dbind_repeat="items">
<a dbind_href="url" dbind_data="label"></a>
</li>
</ul>
</div>
</div>
2. Order with Line Items
<div dbind_repeat="orders" class="order-card">
<div class="order-header">
<span>Order #<span dbind_data="orderNumber"></span></span>
<span dbind_data="date" dbind_format="date:medium"></span>
</div>
<div class="order-items">
<div dbind_repeat="items" class="order-item">
<span dbind_data="name"></span>
<span>x<span dbind_data="quantity"></span></span>
<span dbind_data="price" dbind_format="currency:USD"></span>
</div>
</div>
<div class="order-total">
Total: <span dbind_data="total" dbind_format="currency:USD"></span>
</div>
</div>
3. Comments with Replies
<div class="comments">
<div dbind_repeat="comments" class="comment">
<div class="comment-header">
<img dbind_src="author.avatar" dbind_alt="author.name">
<span dbind_data="author.name"></span>
</div>
<p dbind_data="text"></p>
<!-- Nested replies -->
<div class="replies" dbind_show="replies">
<div dbind_repeat="replies" class="reply">
<span dbind_data="author.name"></span>
<p dbind_data="text"></p>
</div>
</div>
</div>
</div>
Complete Example: Filterable Product Grid
<div class="product-page">
<!-- Filter Controls -->
<aside class="filters">
<h3>Category</h3>
<select id="category-filter">
<option value="">All Categories</option>
<option value="electronics">Electronics</option>
<option value="clothing">Clothing</option>
<option value="home">Home & Garden</option>
</select>
<h3>Sort By</h3>
<select id="sort-by">
<option value="name:asc">Name (A-Z)</option>
<option value="price:asc">Price: Low to High</option>
<option value="price:desc">Price: High to Low</option>
<option value="rating:desc">Top Rated</option>
</select>
</aside>
<!-- Products Grid -->
<main class="products-container">
<!-- All products (default view) -->
<div id="all-products" class="product-grid">
<div dbind_repeat="products" dbind_sort="name:asc" class="product-card">
<img dbind_src="image" dbind_alt="name" loading="lazy">
<div class="product-info">
<span class="category-badge" dbind_data="category"></span>
<h3 dbind_data="name"></h3>
<div class="rating">
<span dbind_data="rating"></span>⭐
<span>(<span dbind_data="reviewCount"></span> reviews)</span>
</div>
<p class="price" dbind_data="price" dbind_format="currency:USD"></p>
<span class="stock" dbind_if="stock<=5">Only <span dbind_data="stock"></span> left!</span>
</div>
<button class="btn-add-cart" dbind_unless="stock==0">Add to Cart</button>
<button class="btn-notify" dbind_if="stock==0">Notify Me</button>
</div>
</div>
<!-- Empty state -->
<div class="no-products" dbind_repeat-empty="products">
<img src="/images/no-products.svg" alt="">
<h2>No products found</h2>
<p>Try adjusting your filters or search terms.</p>
<button onclick="clearFilters()">Clear All Filters</button>
</div>
</main>
</div>
<!-- Pagination -->
<nav class="pagination">
<a href="#" class="prev" dbind_show="hasPrevPage">← Previous</a>
<span class="page-info">
Page <span dbind_data="currentPage"></span> of <span dbind_data="totalPages"></span>
</span>
<a href="#" class="next" dbind_show="hasNextPage">Next →</a>
</nav>
Data:
{
"products": [
{
"name": "Wireless Headphones",
"category": "electronics",
"price": 149.99,
"rating": 4.5,
"reviewCount": 234,
"stock": 15,
"image": "/images/headphones.jpg"
},
{
"name": "Cotton T-Shirt",
"category": "clothing",
"price": 29.99,
"rating": 4.2,
"reviewCount": 89,
"stock": 3,
"image": "/images/tshirt.jpg"
},
{
"name": "Smart Watch",
"category": "electronics",
"price": 299.99,
"rating": 4.8,
"reviewCount": 567,
"stock": 0,
"image": "/images/watch.jpg"
}
],
"currentPage": 1,
"totalPages": 5,
"hasPrevPage": false,
"hasNextPage": true
}
Performance Considerations
Large Lists
For lists with many items:
- Use Pagination: Break large lists into pages
- Use Limits: Show initial subset with "Load More"
- Virtual Scrolling: For very long lists, consider client-side virtual scrolling
<!-- Initial load with limit -->
<div id="items-container" dbind_repeat="items" dbind_limit="20">
<div class="item" dbind_data="name"></div>
</div>
<button id="load-more" onclick="loadMoreItems()">
Load More
</button>
Lazy Loading Images
Always add loading="lazy" to images in lists:
<div dbind_repeat="products">
<img dbind_src="image" dbind_alt="name" loading="lazy">
</div>
Next Steps
- Collections - Server-side data loading with pagination
- Visibility - Conditional display
- Formatting - Format values in lists