Template Variables
Template variables are the building blocks of dynamic content in Canvelete (opens in a new tab). They allow you to create flexible, reusable templates by defining placeholders that can be populated with different data for each render.
Variable Syntax
Basic Variables
Template variables use double curly braces {{}} syntax:
// Simple variable
"{{variableName}}"
// Nested object properties
"{{user.profile.firstName}}"
// Array access
"{{products[0].name}}"
"{{items[index].price}}"Variable Types
String Variables
// Text content
"{{user.name}}" // "John Doe"
"{{product.description}}" // "High-quality wireless headphones"
// With string concatenation
"{{user.firstName + ' ' + user.lastName}}"
// Template literals (ES6 style)
"`Hello, ${user.name}! Welcome back.`"Number Variables
// Numeric values
"{{product.price}}" // 29.99
"{{user.age}}" // 25
"{{order.quantity}}" // 3
// Mathematical operations
"{{price * quantity}}" // Calculate total
"{{(originalPrice - salePrice) / originalPrice * 100}}" // Discount percentageBoolean Variables
// Boolean values
"{{user.isActive}}" // true/false
"{{product.inStock}}" // true/false
// Boolean expressions
"{{user.age >= 18}}" // Age check
"{{price > 0 && inStock}}" // Availability checkArray Variables
// Array properties
"{{products.length}}" // Number of products
"{{users[0].name}}" // First user's name
// Array methods
"{{products.join(', ')}}" // Comma-separated list
"{{tags.slice(0, 3)}}" // First 3 tagsObject Variables
// Object properties
"{{user.profile.bio}}"
"{{settings.theme.primaryColor}}"
// Dynamic property access
"{{user[propertyName]}}"
"{{config[environment].apiUrl}}"Variable Scoping
Global Variables
Available throughout the entire template:
// Global configuration
{
"globals": {
"siteName": "My Website",
"currentYear": 2024,
"theme": {
"primaryColor": "#007bff",
"secondaryColor": "#6c757d"
}
}
}
// Usage in template
"© {{currentYear}} {{siteName}}"
"<div style='color: {{theme.primaryColor}}'>"Local Variables
Scoped to specific template sections:
// Local variable definition
"{{#with user.profile}}
<h1>{{firstName}} {{lastName}}</h1>
<p>{{bio}}</p>
<img src='{{avatar}}' alt='Profile picture'>
{{/with}}"
// Loop variables
"{{#each products as |product index|}}
{{index + 1}}. {{product.name}} - ${{product.price}}
{{/each}}"Context Variables
Special variables providing context information:
// Built-in context variables
"{{@index}}" // Current loop index
"{{@key}}" // Current object key
"{{@first}}" // True if first item in loop
"{{@last}}" // True if last item in loop
"{{@root}}" // Reference to root data context
// Usage example
"{{#each items}}
<div class='{{@first ? 'first' : ''}} {{@last ? 'last' : ''}}'>
Item {{@index + 1}}: {{name}}
</div>
{{/each}}"Variable Modifiers and Filters
Text Modifiers
// Case transformations
"{{user.name | uppercase}}" // JOHN DOE
"{{user.name | lowercase}}" // john doe
"{{user.name | capitalize}}" // John doe
"{{user.name | titlecase}}" // John Doe
// Text formatting
"{{description | truncate:100}}" // Limit to 100 characters
"{{content | stripTags}}" // Remove HTML tags
"{{text | escape}}" // HTML escape
"{{url | slugify}}" // URL-friendly formatNumber Modifiers
// Number formatting
"{{price | currency}}" // $29.99
"{{price | currency:'EUR'}}" // €29.99
"{{percentage | percent}}" // 15%
"{{percentage | percent:2}}" // 15.25%
// Mathematical operations
"{{value | round}}" // Round to nearest integer
"{{value | round:2}}" // Round to 2 decimal places
"{{value | floor}}" // Round down
"{{value | ceil}}" // Round up
"{{value | abs}}" // Absolute valueDate Modifiers
// Date formatting
"{{createdAt | date}}" // Default format
"{{createdAt | date:'YYYY-MM-DD'}}" // 2024-01-15
"{{createdAt | date:'MMM DD, YYYY'}}" // Jan 15, 2024
"{{createdAt | date:'dddd, MMMM Do YYYY'}}" // Monday, January 15th 2024
// Relative dates
"{{createdAt | fromNow}}" // 2 hours ago
"{{dueDate | toNow}}" // in 3 days
"{{startDate | calendar}}" // Today at 2:30 PMArray Modifiers
// Array operations
"{{items | length}}" // Number of items
"{{items | first}}" // First item
"{{items | last}}" // Last item
"{{items | join:', '}}" // Join with comma
// Array filtering and sorting
"{{products | where:'category','Electronics'}}"
"{{products | sortBy:'price'}}"
"{{products | reverse}}"
"{{products | unique:'id'}}"Advanced Variable Techniques
Computed Variables
Define calculated values based on other variables:
// Computed variable definitions
{
"computed": {
"fullName": "{{firstName}} {{lastName}}",
"displayPrice": "{{salePrice || regularPrice}}",
"discountPercent": "{{Math.round((regularPrice - salePrice) / regularPrice * 100)}}",
"isOnSale": "{{salePrice && salePrice < regularPrice}}",
"stockStatus": "{{stock > 10 ? 'In Stock' : stock > 0 ? 'Low Stock' : 'Out of Stock'}}"
}
}
// Usage in templates
"<h1>{{fullName}}</h1>"
"<span class='price'>{{displayPrice | currency}}</span>"
"{{#if isOnSale}}<span class='sale'>{{discountPercent}}% OFF</span>{{/if}}"Variable Inheritance
Pass variables down through template hierarchy:
// Parent template
{
"template": "product-card",
"data": {
"product": "{{currentProduct}}",
"theme": "{{globalTheme}}",
"currency": "{{userCurrency}}"
}
}
// Child template can access inherited variables
"<div class='product-card' style='--primary-color: {{theme.primaryColor}}'>
<h3>{{product.name}}</h3>
<span>{{product.price | currency:currency}}</span>
</div>"Dynamic Variable Names
Use variables to determine other variable names:
// Dynamic property access
"{{user[fieldName]}}" // fieldName determines which property to access
// Dynamic method calls
"{{product[methodName]()}}" // Call method based on variable
// Conditional variable selection
"{{condition ? variableA : variableB}}"Variable Validation
Ensure variables meet expected criteria:
// Validation rules
{
"validation": {
"user.email": {
"type": "email",
"required": true
},
"product.price": {
"type": "number",
"min": 0,
"required": true
},
"user.age": {
"type": "integer",
"min": 0,
"max": 150
}
}
}
// Validation in templates
"{{#if (validate user.email 'email')}}
Valid email: {{user.email}}
{{else}}
Invalid email format
{{/if}}"Variable Security
Input Sanitization
Protect against malicious input:
// Automatic HTML escaping
"{{userInput}}" // Automatically escaped
// Manual escaping control
"{{userInput | escape}}" // Force escape
"{{{trustedHtml}}}" // Triple braces for unescaped HTML
// Safe property access
"{{user?.profile?.bio | escape}}"Access Control
Restrict variable access based on permissions:
// Permission-based access
"{{#if (hasPermission 'view-sensitive-data')}}
SSN: {{user.ssn}}
{{else}}
SSN: ***-**-****
{{/if}}"
// Role-based variables
"{{#if user.role === 'admin'}}
Admin Panel: {{adminData}}
{{/if}}"Performance Optimization
Variable Caching
Cache expensive variable calculations:
// Caching configuration
{
"cache": {
"computed": {
"expensiveCalculation": {
"ttl": 300000, // 5 minutes
"dependencies": ["inputA", "inputB"]
}
}
}
}Lazy Evaluation
Evaluate variables only when needed:
// Lazy evaluation
"{{#lazy}}
{{expensiveOperation()}}
{{/lazy}}"
// Conditional evaluation
"{{#if showDetails}}
{{calculateComplexMetrics()}}
{{/if}}"Debugging Variables
Variable Inspector
Debug variable values during development:
// Debug output
"{{debug user}}" // Outputs variable structure
"{{log 'User name:' user.name}}" // Console logging
// Type checking
"{{typeof user.age}}" // "number"
"{{isArray products}}" // true/falseError Handling
Handle variable errors gracefully:
// Try-catch for variables
"{{try user.profile.bio catch 'Bio not available'}}"
// Default values
"{{user.name || 'Anonymous User'}}"
"{{product.image || '/images/placeholder.jpg'}}"
// Safe navigation
"{{user?.profile?.settings?.theme || 'default'}}"Common Patterns
User Profile Display
{
"user": {
"firstName": "John",
"lastName": "Doe",
"avatar": "https://example.com/avatar.jpg",
"role": "admin",
"lastLogin": "2024-01-15T10:30:00Z"
}
}
// Template usage
"<div class='user-profile'>
<img src='{{user.avatar}}' alt='{{user.firstName}} {{user.lastName}}'>
<h2>{{user.firstName}} {{user.lastName}}</h2>
<span class='role'>{{user.role | titlecase}}</span>
<p>Last login: {{user.lastLogin | fromNow}}</p>
</div>"Product Listing
{
"products": [
{
"id": 1,
"name": "Wireless Headphones",
"price": 199.99,
"salePrice": 149.99,
"rating": 4.5,
"reviews": 1247
}
]
}
// Template usage
"{{#each products}}
<div class='product'>
<h3>{{name}}</h3>
<div class='pricing'>
{{#if salePrice}}
<span class='sale-price'>{{salePrice | currency}}</span>
<span class='original-price'>{{price | currency}}</span>
{{else}}
<span class='price'>{{price | currency}}</span>
{{/if}}
</div>
<div class='rating'>
{{rating}} stars ({{reviews}} reviews)
</div>
</div>
{{/each}}"Best Practices
- Use descriptive names: Make variable purposes clear
- Validate input: Always check variable types and values
- Provide defaults: Handle missing or null values gracefully
- Escape output: Prevent XSS attacks with proper escaping
- Cache expensive operations: Use computed variables for complex calculations
- Document variables: Maintain clear documentation of expected data structure
- Test edge cases: Verify behavior with empty, null, and invalid data
Next Steps
- Learn about Conditional Rendering for advanced template logic
- Explore Data Binding for connecting data sources
- Check the API Reference for complete variable syntax