Advanced Templating
String concatenation, inline pipes, and special variables
DBindly v2.3.0 introduces powerful templating features for more flexible data rendering.
Template Syntax
Basic Interpolation
Use double curly braces to insert field values:
<div dbind_repeat="users">
<p>Hello, {{name}}!</p>
</div>Nested Properties
Access nested data with dot notation:
<div dbind_repeat="orders">
<p>Customer: {{customer.name}}</p>
<p>Email: {{customer.contact.email}}</p>
<p>Address: {{shipping.address.city}}, {{shipping.address.country}}</p>
</div>String Concatenation
Combine multiple fields and literals using +:
<div dbind_repeat="users">
<!-- Combine first and last name -->
<h3>{{firstName + ' ' + lastName}}</h3>
<!-- Build a full address -->
<p>{{address.street + ', ' + address.city + ' ' + address.zip}}</p>
<!-- Mix fields with static text -->
<p>{{'Welcome, ' + displayName + '!'}}</p>
</div>Rules for Concatenation
- Use
+to join parts - String literals must be in single or double quotes
- Field names are unquoted
- Spaces around
+are optional
<!-- All valid -->
<span>{{first + ' ' + last}}</span>
<span>{{first+' '+last}}</span>
<span>{{"Hello, " + name}}</span>
<span>{{'Hello, ' + name}}</span>Inline Pipes (Filters)
Apply formatting filters directly in templates:
<div dbind_repeat="products">
<h3>{{name|uppercase}}</h3>
<p>{{price|currency:USD}}</p>
<p>{{description|truncate:100}}</p>
<time>{{createdAt|date:relative}}</time>
</div>Pipe Syntax
{{fieldName|filterName}}
{{fieldName|filterName:parameter}}
Available Filters
Text Filters
| Filter | Description | Example |
|---|---|---|
uppercase | Convert to uppercase | {{name|uppercase}} |
lowercase | Convert to lowercase | {{email|lowercase}} |
capitalize | Capitalize first letter | {{title|capitalize}} |
titlecase | Capitalize each word | {{name|titlecase}} |
trim | Remove whitespace | {{input|trim}} |
truncate:N | Limit to N characters | {{desc|truncate:50}} |
slug | URL-friendly string | {{title|slug}} |
nl2br | Newlines to <br> | {{bio|nl2br}} |
striphtml | Remove HTML tags | {{content|striphtml}} |
Number Filters
| Filter | Description | Example |
|---|---|---|
number | Format with locale | {{count|number}} |
currency:CODE | Format as currency | {{price|currency:USD}} |
percent | Format as percentage | {{rate|percent}} |
Date Filters
| Filter | Description | Example |
|---|---|---|
date | Format date | {{createdAt|date}} |
date:short | Short date format | {{date|date:short}} |
date:long | Long date format | {{date|date:long}} |
time | Format time | {{timestamp|time}} |
datetime | Date and time | {{updated|datetime}} |
relative | Relative time | {{posted|date:relative}} |
Other Filters
| Filter | Description | Example |
|---|---|---|
boolean | true/false string | {{active|boolean}} |
yesno | Yes/No string | {{subscribed|yesno}} |
default:value | Fallback value | {{nickname|default:Anonymous}} |
json | JSON stringify | {{data|json}} |
urlencode | URL encode | {{query|urlencode}} |
Chaining Filters
Apply multiple filters in sequence:
<!-- Trim, then truncate, then capitalize -->
<p>{{description|trim|truncate:100|capitalize}}</p>
<!-- Lowercase then URL encode -->
<a href="/search?q={{query|lowercase|urlencode}}">Search</a>Special Variables
Loop Index Variables
Within dbind_repeat loops, special variables are available:
| Variable | Description |
|---|---|
{{_index}} | Zero-based index (0, 1, 2...) |
{{_number}} | One-based number (1, 2, 3...) |
<ol dbind_repeat="items">
<li>
<span class="number">{{_number}}.</span>
<span>{{name}}</span>
</li>
</ol>Using Index for Styling
<div dbind_repeat="products">
<div class="product" style="animation-delay: calc({{_index}} * 0.1s)">
<span class="rank">#{{_number}}</span>
<h3>{{name}}</h3>
</div>
</div>Combining Features
Concatenation + Pipes
<div dbind_repeat="users">
<!-- Full name, uppercase -->
<h3>{{firstName + ' ' + lastName|uppercase}}</h3>
<!-- Note: Pipe applies to entire expression -->
</div>Complex Templates
<div dbind_repeat="orders">
<div class="order-card">
<header>
<span class="order-number">Order #{{_number}}</span>
<time>{{createdAt|date:relative}}</time>
</header>
<div class="customer">
<h4>{{customer.firstName + ' ' + customer.lastName}}</h4>
<p>{{customer.email|lowercase}}</p>
</div>
<div class="shipping">
<p>{{shipping.address.street}}</p>
<p>{{shipping.address.city + ', ' + shipping.address.state + ' ' + shipping.address.zip}}</p>
<p>{{shipping.address.country|uppercase}}</p>
</div>
<div class="total">
<span>Total: {{total|currency:USD}}</span>
</div>
<footer>
<span class="status {{status|lowercase}}">{{status|capitalize}}</span>
</footer>
</div>
</div>Template in Attributes
Use templates in data attribute values:
<div dbind_repeat="products">
<!-- Dynamic classes -->
<div class="product {{category|lowercase}}">
<img
dbind_src="image"
dbind_alt="name"
loading="lazy"
>
<h3 dbind_data="name"></h3>
<!-- Dynamic href with template -->
<a href="/products/{{slug}}">View Details</a>
</div>
</div>Default Values
Provide fallback values for missing data:
<div dbind_repeat="users">
<img src="{{avatar|default:/images/default-avatar.png}}">
<h3>{{displayName|default:Anonymous User}}</h3>
<p>{{bio|default:No bio provided}}</p>
</div>Escaping
Templates are automatically HTML-escaped to prevent XSS:
<!-- Safe: HTML entities are escaped -->
<p>{{userInput}}</p>
<!-- If userInput is "<script>alert('xss')</script>" -->
<!-- Output: <script>alert('xss')</script> -->For trusted HTML content, use dbind_html:
<!-- Only use with trusted content! -->
<div dbind_html="richContent"></div>Complete Example
<section class="team">
<h2>Our Team</h2>
<div class="team-grid" dbind_repeat="team">
<article class="team-member" dbind_transition="fade">
<div class="member-rank">#{{_number}}</div>
<img
src="{{avatar|default:/images/placeholder.jpg}}"
alt="{{firstName + ' ' + lastName}}"
loading="lazy"
>
<div class="member-info">
<h3>{{firstName + ' ' + lastName}}</h3>
<p class="role">{{role|titlecase}}</p>
<p class="department">{{department|uppercase}}</p>
<p class="bio">{{bio|truncate:120|default:No bio available}}</p>
<div class="meta">
<span>Joined {{joinDate|date:relative}}</span>
</div>
<div class="social">
<a href="mailto:{{email|lowercase}}">Email</a>
<a href="{{linkedin|default:#}}">LinkedIn</a>
<a href="{{twitter|default:#}}">Twitter</a>
</div>
</div>
</article>
</div>
</section>
<style>
.team-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 24px;
}
.team-member {
position: relative;
padding: 20px;
border-radius: 12px;
background: #fff;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.member-rank {
position: absolute;
top: 12px;
right: 12px;
font-weight: bold;
color: #666;
}
</style>Next Steps
- TypeScript - Type definitions
- JavaScript API - API reference
- Lists - List rendering with dbind_repeat