@data-bind : The Template Iteration Attribute
The data-bind attribute enables template-based iteration over collections in Scryber PDF documents. When applied to <template> elements, it dynamically generates repeating content for each item in an array, list, or any enumerable data source.
Summary
The data-bind attribute is the primary mechanism for creating dynamic, data-driven repeating content in Scryber templates. It binds a template element to a collection and generates the template’s content once for each item in that collection. Each iteration creates a new data context scoped to the current item, allowing you to reference item properties using the dot notation (.propertyName).
This attribute is essential for:
- Generating table rows from database results
- Creating lists of items from arrays
- Building master-detail reports
- Iterating over JSON or XML data
- Dynamically generating any repeating content structure
Usage
The data-bind attribute is applied to <template> elements and accepts binding expressions that evaluate to enumerable collections:
<template data-bind="">
<!-- Content repeated for each item -->
<div></div>
</template>
Basic Syntax
<!-- Bind to a collection -->
<template data-bind="">
<!-- Template content -->
</template>
<!-- With nested property access -->
<template data-bind="">
<!-- Template content -->
</template>
<!-- Using XPath-style expressions -->
<template data-bind="{@:Model.Data}">
<!-- Template content -->
</template>
Supported Elements
The data-bind attribute is only supported on the following element:
<template>- The template element for repeating content
Note: While data-bind is technically part of the ForEach component infrastructure, it is specifically designed and intended for use with the <template> HTML element in Scryber templates.
Binding Values
Expression Syntax
The data-bind attribute accepts binding expressions in two formats:
1. Modern Expression Syntax (Recommended)
<template data-bind="">
- Uses double curly braces: ``
- Supports JavaScript-like expressions
- Allows method calls: ``
- Enables calculations: ``
2. Legacy XPath Syntax
<template data-bind="{@:expression}">
- Uses
{@:...}notation - Simple property path access
- Compatible with older Scryber templates
Supported Data Types
The expression must evaluate to one of the following enumerable types:
| Data Type | Example | Description |
|---|---|---|
.NET Array |
new[] { "a", "b", "c" } |
Standard C# arrays |
.NET List |
List<Customer> |
Generic list collections |
IEnumerable<T> |
IQueryable<Order> |
Any enumerable interface |
DataTable.Rows |
dataTable.Rows |
Database query results |
JSON Array |
[{...}, {...}] |
Arrays from JSON sources |
XML NodeList |
XPath results | XML document nodes |
Data Context Scoping
Within a template, a new data context is created for each iteration:
<template data-bind="">
<!-- Current item reference -->
<!-- The entire current item -->
<!-- Property of current item -->
<!-- Expression using current item -->
<!-- Parent context still accessible -->
<!-- Access parent model -->
<!-- Use parent data -->
</template>
Special Context Variables
Within data-bind templates, special variables are available (syntax may vary):
| Variable | Description | Example |
|---|---|---|
. |
Current item | `` |
$index or index() |
Zero-based index | `` |
$count or count() |
Total item count | 9 |
Notes
Template Element Behavior
- The
<template>element itself is not rendered in the output - Only the template’s content is generated for each item
- Multiple
<template>elements can be nested for hierarchical data
Empty Collections
- If the bound collection is
nullor empty, no content is generated - No error is thrown for empty collections
- Use conditional rendering to show “no items” messages
Performance Considerations
For large collections (100+ items):
- Enable style caching: Add
data-cache-styles="true" - Use style identifiers: Set
data-style-identifier="unique-id" - Limit items per page: Use
data-bind-maxto paginate - Simplify expressions: Avoid complex calculations in binding expressions
- Pre-process data: Filter and transform data before binding when possible
Iteration Control Attributes
The data-bind attribute works in conjunction with:
data-bind-start- Start index for iteration (default: 0)data-bind-step- Step increment (default: 1)data-bind-max- Maximum items to process (default: unlimited)
See individual documentation for these attributes for details.
Common Binding Patterns
Nested Collections
<template data-bind="">
<h2></h2>
<template data-bind="">
<div></div>
</template>
</template>
Accessing Parent Context
<template data-bind="">
<div>
Order for
</div>
</template>
Filtered Collections
<template data-bind="">
<div></div>
</template>
Examples
1. Simple List Iteration
Generate a simple list from an array:
<!-- Model: { fruits: ["Apple", "Banana", "Orange", "Grape"] } -->
<ul>
<template data-bind="">
<li></li>
</template>
</ul>
<!-- Output: -->
<!-- • Apple -->
<!-- • Banana -->
<!-- • Orange -->
<!-- • Grape -->
2. Object Collection with Properties
Iterate over objects and access their properties:
<!-- Model: { users: [{name: "John", email: "john@example.com"}, ...] } -->
<template data-bind="">
<div style="margin-bottom: 10pt;">
<strong></strong><br/>
Email:
</div>
</template>
3. Table Row Generation
Create table rows dynamically:
<table style="width: 100%;">
<thead>
<tr>
<th>#</th>
<th>Product</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<template data-bind="">
<tr>
<td></td>
<td></td>
<td>$</td>
</tr>
</template>
</tbody>
</table>
4. Nested Template for Hierarchical Data
Handle multi-level data structures:
<!-- Model: { departments: [{name: "Sales", employees: [...]}] } -->
<template data-bind="">
<div style="page-break-inside: avoid; margin-bottom: 20pt;">
<h2 style="background-color: #336699; color: white; padding: 10pt;">
Department
</h2>
<table style="width: 100%;">
<template data-bind="">
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</template>
</table>
</div>
</template>
5. Complex Expression Binding
Use expressions to transform data:
<template data-bind="">
<div>
<!-- Calculated values -->
<strong></strong><br/>
Subtotal: $<br/>
Tax: $<br/>
Total: $
</div>
</template>
6. Accessing Parent Model in Nested Template
Reference parent context from within nested templates:
<!-- Model: { companyName: "Acme Corp", orders: [...] } -->
<template data-bind="">
<div>
<h3>Order #</h3>
<p>Company: </p>
<template data-bind="">
<div>
- units
(Order: )
</div>
</template>
</div>
</template>
7. Conditional Item Display
Use expressions to conditionally render items:
<template data-bind="">
<div hidden="">
- $
</div>
</template>
8. Invoice Line Items with Totals
Generate invoice sections with calculations:
<h1>Invoice #</h1>
<table style="width: 100%; margin: 20pt 0;">
<thead>
<tr style="background-color: #f0f0f0; font-weight: bold;">
<th style="text-align: left;">Description</th>
<th style="text-align: right;">Qty</th>
<th style="text-align: right;">Unit Price</th>
<th style="text-align: right;">Total</th>
</tr>
</thead>
<tbody>
<template data-bind="">
<tr>
<td></td>
<td style="text-align: right;"></td>
<td style="text-align: right;">$</td>
<td style="text-align: right;">$</td>
</tr>
</template>
</tbody>
<tfoot>
<tr style="font-weight: bold; border-top: 2pt solid black;">
<td colspan="3" style="text-align: right;">Subtotal:</td>
<td style="text-align: right;">$</td>
</tr>
<tr style="font-weight: bold;">
<td colspan="3" style="text-align: right;">Tax (%):</td>
<td style="text-align: right;">$</td>
</tr>
<tr style="font-weight: bold; font-size: 14pt;">
<td colspan="3" style="text-align: right;">Total:</td>
<td style="text-align: right;">$</td>
</tr>
</tfoot>
</table>
9. Multi-Page Customer Report
Generate one page per customer with order details:
<template data-bind="">
<div style="page-break-before: always;">
<!-- Customer header -->
<div style="background-color: #336699; color: white; padding: 15pt; margin-bottom: 20pt;">
<h1 style="margin: 0;"></h1>
<div style="margin-top: 5pt;">
Contact: | Phone: | Email:
</div>
</div>
<!-- Customer summary -->
<div style="margin-bottom: 20pt; padding: 10pt; background-color: #f0f0f0;">
<strong>Account Summary</strong><br/>
Total Orders: <br/>
Total Revenue: $<br/>
Average Order: $
</div>
<!-- Order history -->
<h2>Order History</h2>
<table style="width: 100%;">
<thead>
<tr style="background-color: #e0e0e0;">
<th>Date</th>
<th>Order #</th>
<th style="text-align: right;">Amount</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<template data-bind="">
<tr>
<td></td>
<td></td>
<td style="text-align: right;">$</td>
<td></td>
</tr>
</template>
</tbody>
</table>
</div>
</template>
10. Catalog with Categories and Products
Three-level nested template structure:
<template data-bind="">
<div style="margin-bottom: 40pt;">
<h1 style="color: #336699; border-bottom: 3pt solid #336699; padding-bottom: 5pt;">
</h1>
<p style="font-style: italic; color: #666;"></p>
<template data-bind="">
<div style="margin: 20pt 0 20pt 20pt;">
<h2 style="color: #666; border-bottom: 1pt solid #ccc;">
</h2>
<div style="column-count: 2; column-gap: 20pt;">
<template data-bind="">
<div style="break-inside: avoid; margin-bottom: 15pt; padding: 10pt; border: 1pt solid #ddd;">
<h3 style="margin: 0 0 5pt 0; color: #336699;">
</h3>
<div style="color: #666; font-size: 9pt; margin-bottom: 5pt;">
SKU:
</div>
<p style="margin: 5pt 0;"></p>
<div style="font-weight: bold; font-size: 12pt; color: #336699;">
$
</div>
</div>
</template>
</div>
</div>
</template>
</div>
</template>
11. Data Grid with Alternating Row Colors
Apply styling based on position:
<style>
.data-row { padding: 8pt; border-bottom: 1pt solid #ddd; }
.data-row:nth-child(even) { background-color: #f9f9f9; }
.data-row:nth-child(odd) { background-color: #ffffff; }
</style>
<template data-bind="">
<div class="data-row">
<div style="display: inline-block; width: 30%;"></div>
<div style="display: inline-block; width: 40%;"></div>
<div style="display: inline-block; width: 30%;"></div>
</div>
</template>
12. Timeline with Event Grouping
Group events by date with nested iterations:
<template data-bind="">
<div style="margin-bottom: 25pt; padding-left: 25pt; border-left: 3pt solid #336699;">
<h2 style="color: #336699; margin: 0 0 10pt 0;">
</h2>
<template data-bind="">
<div style="margin-bottom: 12pt; padding: 10pt; background-color: #f9f9f9;">
<div style="font-weight: bold; color: #336699;">
-
</div>
<div style="margin-top: 5pt; color: #666;">
</div>
<div style="margin-top: 5pt; font-size: 9pt; color: #999;">
Location: | Duration:
</div>
</div>
</template>
</div>
</template>
13. Product Comparison Table
Generate comparison columns dynamically:
<table style="width: 100%; border-collapse: collapse;">
<thead>
<tr style="background-color: #336699; color: white;">
<th style="text-align: left; padding: 10pt;">Feature</th>
<template data-bind="">
<th style="padding: 10pt;"></th>
</template>
</tr>
</thead>
<tbody>
<template data-bind="">
<tr style="border-bottom: 1pt solid #ddd;">
<td style="padding: 8pt; font-weight: bold;"></td>
<template data-bind="">
<td style="padding: 8pt; text-align: center;">
</td>
</template>
</tr>
</template>
</tbody>
</table>
14. File Directory Listing with Icons
Display files with type-specific icons:
<h2>Directory Contents</h2>
<template data-bind="">
<div style="padding: 10pt; border-bottom: 1pt solid #eee;">
<div style="display: inline-block; width: 50%; vertical-align: middle;">
<img src="" style="width: 16pt; height: 16pt; vertical-align: middle;"/>
<span style="margin-left: 8pt;"></span>
</div>
<div style="display: inline-block; width: 20%; vertical-align: middle; text-align: center;">
</div>
<div style="display: inline-block; width: 15%; vertical-align: middle; text-align: center;">
</div>
<div style="display: inline-block; width: 15%; vertical-align: middle; text-align: right;">
</div>
</div>
</template>
15. Performance-Optimized Large Dataset
Efficient rendering with style caching:
<!-- Efficiently render 1000+ items -->
<style>
.large-list-item {
padding: 5pt;
border-bottom: 1pt solid #eee;
font-size: 10pt;
}
</style>
<template data-bind=""
data-cache-styles="true"
data-style-identifier="large-list-cache">
<div class="large-list-item">
<strong></strong> - |
</div>
</template>
16. Conditional Empty State
Show message when collection is empty:
<div style="border: 1pt solid #ccc; padding: 15pt;">
<h3>Products</h3>
<template data-bind="">
<div class="product-item">
- $
</div>
</template>
<!-- Show this when no products -->
<div hidden=""
style="color: #999; font-style: italic; text-align: center; padding: 20pt;">
No products available at this time.
</div>
</div>
See Also
- template element - The template HTML element
- data-bind-start attribute - Control iteration start index
- data-bind-step attribute - Control iteration step
- data-bind-max attribute - Limit iteration count
- data-content attribute - Inline template content
- Data Binding - Complete data binding guide
- Expressions - Expression syntax reference
- ForEach Component - Base component class