Skip to main content Link Search Menu Expand Document (external link)

@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 null or 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):

  1. Enable style caching: Add data-cache-styles="true"
  2. Use style identifiers: Set data-style-identifier="unique-id"
  3. Limit items per page: Use data-bind-max to paginate
  4. Simplify expressions: Avoid complex calculations in binding expressions
  5. 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