Collections & Pagination

Load server-side data with search, filtering, and pagination

Collection attributes connect your HTML to server-side data collections. They enable features like pagination, search, and server-side filtering.

dbind_collection

Purpose: Load data from a named DBindly collection. This connects your HTML to server-side data.

Syntax:

<element dbind_collection="collectionName">
  <!-- Child elements can access collection data -->
</element>

Finding Your Collection Slug

The collectionName is the slug of your collection from the DBIndly dashboard:

  1. Open DashboardCollections
  2. Click on your collection
  3. Find the Slug in collection settings

Examples:

  • Collection named "Products" → slug: products
  • Collection named "Blog Posts" → slug: blog-posts
  • Collection named "Team Members" → slug: team-members
<!-- Use the slug, not the display name -->
<div dbind_collection="team-members">
  ...
</div>

How It Works

  1. DBindly fetches data from the collection via your API
  2. Data is loaded into the element's scope
  3. Child elements can use dbind_repeat and other bindings
  4. Real-time updates are pushed automatically (if enabled)

Basic Usage

<!-- Load products collection -->
<div dbind_collection="products">
  <div dbind_repeat="data">
    <h3 dbind_data="name"></h3>
    <p dbind_data="description"></p>
    <span dbind_data="price" dbind_format="currency:USD"></span>
  </div>
</div>

This fetches data from your "products" collection and renders each item.

Collection Response Format

DBindly expects collections to return data in this format:

{
  "data": [...],           // Array of items
  "total": 100,            // Total item count
  "page": 1,               // Current page
  "pageSize": 20,          // Items per page
  "totalPages": 5          // Total number of pages
}

Use Cases

1. Product Catalog

<section class="catalog" dbind_collection="products">
  <h2>Our Products</h2>
  <div class="product-grid" dbind_repeat="data">
    <article class="product-card">
      <img dbind_src="image" dbind_alt="name">
      <h3 dbind_data="name"></h3>
      <p dbind_data="price" dbind_format="currency:USD"></p>
    </article>
  </div>
</section>

2. Blog Posts

<main class="blog" dbind_collection="posts">
  <article dbind_repeat="data" class="post">
    <img dbind_src="featuredImage" dbind_alt="title" class="post-image">
    <h2 dbind_data="title"></h2>
    <div class="meta">
      <span dbind_data="author.name"></span>
      <time dbind_data="publishedAt" dbind_format="date:medium"></time>
    </div>
    <p dbind_data="excerpt"></p>
    <a dbind_href="url">Read More</a>
  </article>
</main>

3. Team Directory

<div class="team-directory" dbind_collection="team">
  <div dbind_repeat="data" class="team-member">
    <img dbind_src="photo" dbind_alt="name" class="avatar">
    <h4 dbind_data="name"></h4>
    <span class="title" dbind_data="jobTitle"></span>
    <span class="department" dbind_data="department"></span>
  </div>
</div>

Loading States

Use dbind_loading and dbind_skeleton for loading feedback:

<div dbind_collection="products">
  <!-- Loading skeleton -->
  <div dbind_loading="show" class="skeleton-grid">
    <div class="skeleton-card"></div>
    <div class="skeleton-card"></div>
    <div class="skeleton-card"></div>
  </div>
 
  <!-- Actual content (hidden while loading) -->
  <div dbind_loading="hide" class="product-grid" dbind_repeat="data">
    <div class="product-card" dbind_data="name"></div>
  </div>
</div>

dbind_search

Purpose: Create a search input that filters collection data based on user input.

Syntax:

<input type="text" dbind_search="collectionName" placeholder="Search...">

How It Works

  1. User types in the search input
  2. DBindly debounces the input (waits for typing to stop)
  3. A new request is made to the collection with the search query
  4. Results are updated in the DOM

Basic Usage

<div dbind_collection="products">
  <!-- Search input -->
  <input type="search" dbind_search="products" placeholder="Search products...">
 
  <!-- Results -->
  <div class="product-grid" dbind_repeat="data">
    <div class="product-card">
      <h3 dbind_data="name"></h3>
    </div>
  </div>
 
  <!-- No results -->
  <div dbind_empty="data">
    <p>No products match your search.</p>
  </div>
</div>

Search Input Attributes

You can use standard HTML input attributes:

<input
  type="search"
  dbind_search="products"
  placeholder="Search by name, description..."
  minlength="2"
  aria-label="Search products"
>

Use Cases

1. Product Search with Filters

<div dbind_collection="products">
  <div class="search-section">
    <input type="search" dbind_search="products" placeholder="Search products...">
 
    <select dbind_filter="products" data-field="category">
      <option value="">All Categories</option>
      <option value="electronics">Electronics</option>
      <option value="clothing">Clothing</option>
    </select>
  </div>
 
  <div class="results" dbind_repeat="data">
    <div class="product" dbind_data="name"></div>
  </div>
 
  <div dbind_empty="data">
    <p>No products found. Try different search terms.</p>
  </div>
</div>

2. User Directory Search

<div dbind_collection="users">
  <div class="directory-header">
    <h2>Team Directory</h2>
    <input
      type="search"
      dbind_search="users"
      placeholder="Search by name or department..."
    >
  </div>
 
  <table class="user-table">
    <thead>
      <tr>
        <th>Name</th>
        <th>Email</th>
        <th>Department</th>
      </tr>
    </thead>
    <tbody dbind_repeat="data">
      <tr>
        <td dbind_data="name"></td>
        <td dbind_data="email"></td>
        <td dbind_data="department"></td>
      </tr>
    </tbody>
  </table>
</div>

3. Instant Search with Highlight

<div dbind_collection="articles">
  <input type="search" dbind_search="articles" placeholder="Search articles...">
 
  <div dbind_repeat="data" class="search-result">
    <h3 dbind_data="title"></h3>
    <p dbind_html="highlightedSnippet"></p>
    <a dbind_href="url">Read More</a>
  </div>
</div>

Debounce Behavior

DBindly automatically debounces search input to prevent excessive API calls:

  • Default debounce: 300ms
  • Minimum characters: 1 (configurable)

Server-Side Search

Your collection endpoint should handle the search query parameter:

GET /api/collections/products?search=headphones

The server filters data and returns matching results.


dbind_paginate

Purpose: Add automatic pagination controls to a collection.

Syntax:

<element dbind_paginate="pageSize"></element>

How It Works

  1. Collection is loaded with the specified page size
  2. DBindly generates pagination controls
  3. Clicking a page number fetches that page of data
  4. The DOM updates with new results

Basic Usage

<div dbind_collection="products" dbind_paginate="12">
  <!-- Products grid -->
  <div class="product-grid" dbind_repeat="data">
    <div class="product-card">
      <h3 dbind_data="name"></h3>
    </div>
  </div>
 
  <!-- Pagination controls are auto-generated -->
</div>

Custom Pagination Controls

If you need custom styling, create your own pagination structure:

<div dbind_collection="products">
  <div class="product-grid" dbind_repeat="data">
    <div class="product-card" dbind_data="name"></div>
  </div>
 
  <!-- Custom pagination -->
  <nav class="pagination" aria-label="Product pages">
    <button dbind_page="prev" dbind_hide="isFirstPage">
      ← Previous
    </button>
 
    <span class="page-numbers" dbind_repeat="pageNumbers">
      <button
        dbind_page="{{number}}"
        dbind_class="activeClass"
        dbind_data="number"
      ></button>
    </span>
 
    <button dbind_page="next" dbind_hide="isLastPage">
      Next →
    </button>
  </nav>
</div>

Use Cases

1. Product Catalog with Pagination

<section class="catalog" dbind_collection="products" dbind_paginate="24">
  <header class="catalog-header">
    <h1>All Products</h1>
    <input type="search" dbind_search="products" placeholder="Search...">
  </header>
 
  <div class="product-grid" dbind_repeat="data">
    <article class="product-card">
      <img dbind_src="image" dbind_alt="name">
      <h3 dbind_data="name"></h3>
      <p dbind_data="price" dbind_format="currency:USD"></p>
    </article>
  </div>
 
  <div class="empty-state" dbind_empty="data">
    <p>No products found.</p>
  </div>
</section>

2. Blog Archive

<div class="blog-archive" dbind_collection="posts" dbind_paginate="10">
  <article dbind_repeat="data" class="post-preview">
    <time dbind_data="publishedAt" dbind_format="date:long"></time>
    <h2 dbind_data="title"></h2>
    <p dbind_data="excerpt"></p>
    <a dbind_href="url">Continue Reading →</a>
  </article>
</div>

dbind_loadmore

Purpose: Add a "Load More" button for infinite scroll-style pagination.

Syntax:

<button dbind_loadmore="collectionName">Load More</button>

How It Works

  1. Initial page of data is loaded
  2. User clicks "Load More"
  3. Next page is fetched and appended to existing data
  4. Button hides when all data is loaded

Basic Usage

<div dbind_collection="products">
  <!-- Products append here -->
  <div class="product-grid" dbind_repeat="data">
    <div class="product-card">
      <h3 dbind_data="name"></h3>
    </div>
  </div>
 
  <!-- Load more button -->
  <button dbind_loadmore="products" class="btn-load-more">
    Load More Products
  </button>
</div>

Custom Loading States

<div dbind_collection="posts">
  <div dbind_repeat="data" class="post">
    <h2 dbind_data="title"></h2>
  </div>
 
  <!-- Load more with states -->
  <div class="load-more-container">
    <button dbind_loadmore="posts" dbind_hide="isLoading">
      Load More Posts
    </button>
    <span dbind_show="isLoading" class="loading-spinner">
      Loading...
    </span>
    <span dbind_show="isComplete" class="all-loaded">
      You've reached the end!
    </span>
  </div>
</div>

Use Cases

1. Social Feed

<div class="social-feed" dbind_collection="posts">
  <article dbind_repeat="data" class="feed-post">
    <header class="post-header">
      <img dbind_src="author.avatar" dbind_alt="author.name">
      <span dbind_data="author.name"></span>
      <time dbind_data="createdAt" dbind_format="date:relative"></time>
    </header>
    <p dbind_data="content"></p>
    <footer class="post-actions">
      <button>Like</button>
      <button>Comment</button>
      <button>Share</button>
    </footer>
  </article>
 
  <button dbind_loadmore="posts" class="load-more">
    Show More Posts
  </button>
</div>

2. Image Gallery

<div class="gallery" dbind_collection="images">
  <div class="gallery-grid" dbind_repeat="data">
    <figure class="gallery-item">
      <img dbind_src="thumbnail" dbind_alt="title" loading="lazy">
      <figcaption dbind_data="title"></figcaption>
    </figure>
  </div>
 
  <button dbind_loadmore="images" class="btn-load-more">
    Load More Images
  </button>
</div>

Load More vs Pagination

Featuredbind_paginatedbind_loadmore
UI PatternPage numbers"Load More" button
Data DisplayReplace contentAppend content
Best ForTables, directoriesFeeds, galleries
URL UpdatesYes (page parameter)No
Browser BackWorks as expectedMay lose position

dbind_page-info

Purpose: Display pagination information like current page, total pages, and total items.

Syntax:

<element dbind_page-info="field"></element>

Available Fields

FieldDescriptionExample
pageCurrent page number1
totalPagesTotal number of pages10
totalTotal number of items237
pageSizeItems per page20
fromFirst item number on page21
toLast item number on page40

Basic Usage

<div dbind_collection="products" dbind_paginate="20">
  <!-- Page info -->
  <div class="page-info">
    Showing <span dbind_page-info="from"></span>-<span dbind_page-info="to"></span>
    of <span dbind_page-info="total"></span> products
  </div>
 
  <!-- Products -->
  <div dbind_repeat="data">
    <div class="product" dbind_data="name"></div>
  </div>
 
  <!-- Pagination -->
  <div class="pagination-footer">
    Page <span dbind_page-info="page"></span>
    of <span dbind_page-info="totalPages"></span>
  </div>
</div>

Use Cases

1. Results Summary

<div class="search-results-header">
  <h2>
    Found <span dbind_page-info="total"></span> results
  </h2>
  <p class="results-range">
    Showing <span dbind_page-info="from"></span> - <span dbind_page-info="to"></span>
  </p>
</div>

2. Table Footer

<table class="data-table">
  <thead>
    <tr>
      <th>Name</th>
      <th>Email</th>
      <th>Status</th>
    </tr>
  </thead>
  <tbody dbind_repeat="data">
    <tr>
      <td dbind_data="name"></td>
      <td dbind_data="email"></td>
      <td dbind_data="status"></td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <td colspan="3">
        Page <span dbind_page-info="page"></span>/<span dbind_page-info="totalPages"></span>
        (<span dbind_page-info="total"></span> total records)
      </td>
    </tr>
  </tfoot>
</table>

Collection Filtering

dbind_collection-filter

Purpose: Add filter controls that update the collection query.

Syntax:

<select dbind_collection-filter="collectionName" data-field="fieldName">
  <option value="">All</option>
  <option value="value1">Option 1</option>
</select>

Basic Usage

<div dbind_collection="products">
  <!-- Category filter -->
  <select dbind_collection-filter="products" data-field="category">
    <option value="">All Categories</option>
    <option value="electronics">Electronics</option>
    <option value="clothing">Clothing</option>
    <option value="home">Home & Garden</option>
  </select>
 
  <!-- Status filter -->
  <select dbind_collection-filter="products" data-field="status">
    <option value="">All Status</option>
    <option value="active">In Stock</option>
    <option value="low">Low Stock</option>
    <option value="out">Out of Stock</option>
  </select>
 
  <!-- Products -->
  <div dbind_repeat="data" class="product-card">
    <h3 dbind_data="name"></h3>
  </div>
</div>

Multiple Filters

Filters work together - selecting multiple narrows results:

<div dbind_collection="users">
  <div class="filter-bar">
    <select dbind_collection-filter="users" data-field="department">
      <option value="">All Departments</option>
      <option value="engineering">Engineering</option>
      <option value="marketing">Marketing</option>
      <option value="sales">Sales</option>
    </select>
 
    <select dbind_collection-filter="users" data-field="role">
      <option value="">All Roles</option>
      <option value="manager">Managers</option>
      <option value="senior">Senior</option>
      <option value="junior">Junior</option>
    </select>
 
    <select dbind_collection-filter="users" data-field="location">
      <option value="">All Locations</option>
      <option value="nyc">New York</option>
      <option value="sf">San Francisco</option>
      <option value="remote">Remote</option>
    </select>
  </div>
 
  <div dbind_repeat="data" class="user-card">
    <span dbind_data="name"></span>
  </div>
</div>

Collection Sorting

dbind_collection-sort

Purpose: Add sort controls that change the collection order.

Syntax:

<select dbind_collection-sort="collectionName">
  <option value="field:asc">Field (A-Z)</option>
  <option value="field:desc">Field (Z-A)</option>
</select>

Basic Usage

<div dbind_collection="products">
  <!-- Sort control -->
  <select dbind_collection-sort="products">
    <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>
    <option value="createdAt:desc">Newest First</option>
  </select>
 
  <div dbind_repeat="data" class="product">
    <h3 dbind_data="name"></h3>
    <span dbind_data="price" dbind_format="currency:USD"></span>
  </div>
</div>

Complete Example: E-commerce Catalog

<div class="product-catalog" dbind_collection="products" dbind_paginate="24">
  <!-- Header with search and filters -->
  <header class="catalog-header">
    <h1>Our Products</h1>
 
    <div class="search-box">
      <input
        type="search"
        dbind_search="products"
        placeholder="Search products..."
        aria-label="Search products"
      >
    </div>
  </header>
 
  <!-- Filter and Sort Bar -->
  <div class="filter-bar">
    <div class="filters">
      <select dbind_collection-filter="products" data-field="category" aria-label="Category">
        <option value="">All Categories</option>
        <option value="electronics">Electronics</option>
        <option value="clothing">Clothing</option>
        <option value="home">Home & Living</option>
        <option value="sports">Sports</option>
      </select>
 
      <select dbind_collection-filter="products" data-field="brand" aria-label="Brand">
        <option value="">All Brands</option>
        <option value="apple">Apple</option>
        <option value="samsung">Samsung</option>
        <option value="sony">Sony</option>
      </select>
 
      <select dbind_collection-filter="products" data-field="priceRange" aria-label="Price Range">
        <option value="">Any Price</option>
        <option value="0-50">Under $50</option>
        <option value="50-100">$50 - $100</option>
        <option value="100-500">$100 - $500</option>
        <option value="500+">$500+</option>
      </select>
    </div>
 
    <div class="sort">
      <label for="sort-select">Sort by:</label>
      <select id="sort-select" dbind_collection-sort="products">
        <option value="relevance:desc">Relevance</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>
        <option value="sales:desc">Best Selling</option>
        <option value="createdAt:desc">Newest</option>
      </select>
    </div>
  </div>
 
  <!-- Results Info -->
  <div class="results-info">
    <span>
      Showing <span dbind_page-info="from"></span>-<span dbind_page-info="to"></span>
      of <span dbind_page-info="total"></span> products
    </span>
  </div>
 
  <!-- Loading State -->
  <div dbind_loading="show" class="loading-grid">
    <div class="skeleton-card"></div>
    <div class="skeleton-card"></div>
    <div class="skeleton-card"></div>
    <div class="skeleton-card"></div>
  </div>
 
  <!-- Product Grid -->
  <div dbind_loading="hide" class="product-grid">
    <article dbind_repeat="data" class="product-card">
      <!-- Sale Badge -->
      <span class="sale-badge" dbind_show="onSale">SALE</span>
 
      <!-- Product Image -->
      <a dbind_href="url" class="product-image">
        <img dbind_src="image" dbind_alt="name" loading="lazy">
      </a>
 
      <!-- Product Info -->
      <div class="product-info">
        <span class="category" dbind_data="category"></span>
        <h3><a dbind_href="url" dbind_data="name"></a></h3>
 
        <!-- Rating -->
        <div class="rating">
          <span class="stars" dbind_data="ratingStars"></span>
          <span class="count">(<span dbind_data="reviewCount"></span>)</span>
        </div>
 
        <!-- Price -->
        <div class="price-container">
          <span class="current-price" dbind_data="price" dbind_format="currency:USD"></span>
          <span class="original-price" dbind_show="onSale" dbind_data="originalPrice" dbind_format="currency:USD"></span>
        </div>
 
        <!-- Stock Status -->
        <span class="in-stock" dbind_if="stock>10">In Stock</span>
        <span class="low-stock" dbind_if="stock<=10">Only <span dbind_data="stock"></span> left</span>
        <span class="out-of-stock" dbind_if="stock==0">Out of Stock</span>
      </div>
 
      <!-- Add to Cart -->
      <button class="btn-add-cart" dbind_unless="stock==0">Add to Cart</button>
      <button class="btn-notify" dbind_if="stock==0">Notify Me</button>
    </article>
  </div>
 
  <!-- Empty State -->
  <div class="empty-state" dbind_empty="data">
    <img src="/images/no-products.svg" alt="">
    <h2>No products found</h2>
    <p>Try adjusting your search or filter criteria.</p>
    <button onclick="clearFilters()">Clear All Filters</button>
  </div>
 
  <!-- Pagination -->
  <nav class="pagination" aria-label="Product pages">
    <div class="page-info">
      Page <span dbind_page-info="page"></span> of <span dbind_page-info="totalPages"></span>
    </div>
  </nav>
</div>

CSS (excerpt):

.product-catalog {
  max-width: 1200px;
  margin: 0 auto;
}
 
.filter-bar {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem 0;
  border-bottom: 1px solid #e5e7eb;
}
 
.product-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 1.5rem;
  padding: 2rem 0;
}
 
.product-card {
  border: 1px solid #e5e7eb;
  border-radius: 12px;
  overflow: hidden;
  transition: box-shadow 0.2s;
}
 
.product-card:hover {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
 
.loading-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.5rem;
}
 
.skeleton-card {
  height: 350px;
  background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
  background-size: 200% 100%;
  animation: skeleton 1.5s ease-in-out infinite;
  border-radius: 12px;
}
 
@keyframes skeleton {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

Real-Time Updates

Collections can receive real-time updates when data changes on the server:

<div dbind_collection="notifications" dbind_live="true">
  <div dbind_repeat="data" class="notification">
    <span dbind_data="message"></span>
    <time dbind_data="createdAt" dbind_format="date:relative"></time>
  </div>
</div>

When new data is added to the collection, it automatically appears in the DOM.


Next Steps

  • Lists - Client-side list rendering
  • Loading - Loading states and skeletons
  • Formatting - Format collection data