Lists & Repetition
Render arrays and collections with filtering, sorting, and pagination
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