This guide provides comprehensive documentation for creating Handlebars templates for Resource Cards displayed in the Resource Explorer component.
What is the Resource Explorer?
The Resource Explorer is a searchable, filterable interface for browsing and selecting resources within the Velrada Rostering application. Resources are displayed as cards, with the visual presentation of each card determined by a customisable Handlebars template.
What is Handlebars?
Handlebars is a simple templating language that allows you to create HTML markup with dynamic data. Templates use double curly braces {{ }} to insert values and helpers.
Example:
<div>{{name}}</div>If the resource has name: "John Smith", this renders as:
<div>John Smith</div>AppSettings for Templates
App Setting - Roster/RosterPCF/ResourceCardTemplate
Default Value -
<div style="display:flex;align-items:center;gap:12px;padding:8px;position:relative;">
<div style="width:40px;height:40px;border-radius:50%;background-color:{{colorFromIndex index}};display:flex;align-items:center;justify-content:center;flex-shrink:0;">
<span style="color:white;font-weight:600;font-size:14px;">{{initials name}}</span>
</div>
<div style="display:flex;flex-direction:column;overflow:hidden;">
<div style="display:flex;">
<div style="font-weight:600;font-size:14px;color:rgb(50,49,48);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">
{{name}}
</div>
{{#if isPreferred}}
<div>{{{icon "star"}}}</div>
{{/if}}
</div>
{{#if resourcetype}}
<div style="font-size:12px;color:rgb(96,94,92);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">{{resourcetype}}</div>
{{/if}}
</div>
{{#if isDoubleBooked}}
<div style="position:absolute;top:-3px;right:-5px;" title="Double Booked">
{{{icon "warning"}}}
</div>
{{/if}}
</div>Getting Started
Basic Template Structure
A minimal template looks like this:
<div style='padding:8px;'>
<div style='font-weight:600;'>{{name}}</div>
</div>This displays the resource's name in bold with padding.
Editing Templates
A Resource Card template can be edited by editing the App Setting.
Template Data Context
Every resource card has access to a context object containing resource information. The available fields depend on your system configuration.
Core Fields (Always Available)
Field Name | Type | Description | Example Value |
|---|---|---|---|
|
| Unique identifier for the resource |
|
|
| Display name of the resource |
|
|
| Whether resource is booked in conflicting time |
|
|
| Type/category of resource |
|
|
| Position in the results list (0-based) |
|
|
| Whether resource is marked as preferred |
|
|
| Whether booked to the current shift |
|
|
| Whether booked to the current segment |
|
Custom/Dynamic Fields
Users can use the App Setting below to configure custom fields when they use a custom API to fetch or search for resources.
App Setting - Roster/RosterPCF/ResourceExplorerApiResourceFields
Example Values - resourcetype, customField1, etc (use comma separated values if providing multiple values)
Accessing Fields in Templates
Use the field name directly in double curly braces:
<div>{{name}}</div>
<div>{{vel_email}}</div>
<div>Skill: {{vel_skillrating}}/5</div>Available Handlebars Helpers
Helpers are special functions you can use within templates to transform or conditionally display data.
Built-in Handlebars Helpers
{{#if condition}}...{{/if}}
Conditionally display content based on truthiness.
{{#if isPreferred}}
<div style='color:green;'>★ Preferred Resource</div>
{{/if}}{{#unless condition}}...{{/unless}}
Opposite of if - displays content when condition is false.
{{#unless isDoubleBod
oked}}
<div style='color:green;'>Available</div>
{{/unless}}{{#each array}}...{{/each}}
Loop through arrays.
{{#each skills}}
<span>{{this}}</span>
{{/each}}{{#with object}}...{{/with}}
Change the context to a nested object.
{{#with location}}
<div>{{city}}, {{state}}</div>
{{/with}}Custom Helpers
{{#ifEquals arg1 arg2}}...{{/ifEquals}}
Purpose: Compare two values for equality
Parameters:
arg1- First valuearg2- Second value
Example:
{{#ifEquals resourceType 'Registered Nurse'}}
<div style='color:blue;'>
{{else}}
<div>Other Role</div>
{{/ifEquals}}Use Cases:
Show different badges based on status
Conditional formatting by resource type
Display role-specific icons
{{formatNumber value}}
Purpose: Format numbers with locale-specific thousand separators
Parameters:
value- Number to format
Example:
<div>Total Hours: {{formatNumber 1234.56}}</div>
<!-- Renders: Total Hours: 1,234.56 -->Use Cases:
Display salary/pay rates
Show hours worked
Format any numeric values
{{uppercase text}}
Purpose: Convert text to uppercase
Parameters:
text- String to convert
Example:
<div>{{uppercase name}}</div>
<!-- "john smith" becomes "JOHN SMITH" -->Use Cases:
Standardise name formatting
Emphasise important text
Display codes/IDs in uppercase
{{lowercase text}}
Purpose: Convert text to lowercase
Parameters:
text- String to convert
Example:
<div>Email: {{lowercase vel_email}}</div>
<!-- "John.Smith@Example.COM" becomes "john.smith@example.com" -->Use Cases:
Normalise email addresses
Format usernames
{{truncate text length}}
Purpose: Truncate text with ellipsis if it exceeds a specified length
Parameters:
text- String to truncatelength- Maximum character count
Example:
<div>{{truncate description 50}}</div>
<!-- "This is a very long description that exceeds the limit"
becomes "This is a very long description that exceeds th..." -->Use Cases:
Prevent card text overflow
Display summaries
Limit long field values
{{initials name}}
Purpose: Extract initials from a full name
Parameters:
name- Full name string
Rules:
Single word: Returns first 2 characters uppercase
Multiple words: Returns first letter of first word + first letter of last word, uppercase
Examples:
{{initials 'John Smith'}}
{{initials 'Mary Jane Watson'}}
{{initials 'Madonna'}}
Use Cases:
Display initials in avatar circles
Compact name representations
Visual identification
Full Example:
<div style='display:flex;align-items:center;gap:8px;'>
<div
style='
width: 32px;
height: 32px;
border-radius: 50%;
background-color: {{colorFromIndex index}};
color: white;
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
font-size: 12px;
'
>
{{initials name}}
</div>
<div>{{name}}</div>
</div>{{colorFromIndex index}}
Purpose: Generate a consistent color based on an index number
Parameters:
index- Numeric index (typically 0-23 for best distribution)
Returns: HSL color string (e.g., hsl(180, 65%, 45%))
Color Palette:
Uses 24 evenly distributed hues on the color wheel
65% saturation, 45% lightness
Consistent colors for the same index
Example:
<div style='background-color:{{colorFromIndex index}};'>
{{name}}
</div>Use Cases:
Color-code resources by position in list
Create visually distinct avatar backgrounds
Group visual identification
Color Examples:
index: 0 → hsl(0, 65%, 45%)(red)index: 4 → hsl(60, 65%, 45%)(yellow)index: 8 → hsl(120, 65%, 45%)(green)index: 16 → hsl(240, 65%, 45%)(blue)
{{icon iconName}}
Purpose: Insert an inline SVG icon
Parameters:
iconName- Name of the icon (see Icon Library section)
Returns: Safe HTML string containing SVG markup
Example:
<div>
{{icon 'calendar'}}
Scheduled
</div>Use Cases:
Add visual indicators (warnings, status icons)
Display symbols next to text
Enhance visual communication
Common Icons:
{{icon "warning"}}- Alert symbol{{icon "person"}}- Person silhouette{{icon "calendar"}}- Calendar icon{{icon "star"}}- Star (favorites){{icon "clock"}}- Time/clock
See full list in Icon Library section.
Icon Library
The system includes 40+ pre-built SVG icons you can use via the {{icon "name"}} helper.
Status & Alerts
Icon Name | Visual | Use Case |
|---|---|---|
| ⚠️ Yellow triangle | Warnings, conflicts |
| ✖️ Red circle X | Errors, unavailable |
| ℹ️ Blue circle | Information, notes |
| ✅ Green checkmark | Success, confirmed |
| 🚫 Red circle crossed out | Compliance breach |
Example:
{{#if isDoubleBooked}}
<div style='color:#A42626;'>
{{icon 'warning'}}
Double Booked
</div>
{{/if}}Favorites & Ratings
Icon Name | Visual | Use Case |
|---|---|---|
| Preferred/favorite | |
| ☆ Empty star | Not preferred |
Example:
<div>
{{name}}
{{#if isPreferred}}{{{icon 'star'}}}{{/if}}
</div>Actions
Icon Name | Visual | Use Case |
|---|---|---|
| Edit indicator | |
| Delete/remove | |
| Duplicate | |
| Paste operation | |
| Save action | |
| Add/create | |
| Remove/subtract | |
| Refresh/reload |
Navigation
Icon Name | Visual | Use Case |
|---|---|---|
| | Next/forward |
| Previous/back | |
| Expand/show more | |
| Collapse/show less |
Rostering Specific
Icon Name | Visual | Use Case |
|---|---|---|
| Dates, schedules | |
| Time, duration | |
| Individual resource | |
| Teams, groups | |
| Location, territory | |
| Day shifts | |
| Night shifts | |
| Swap/exchange | |
| Locked, unavailable | |
| Unlocked, available |
Example:
<div style='font-size:12px;color:#605E5C;'>
{{icon 'location'}}
{{vel_territory}}
</div>
<div style='font-size:12px;color:#605E5C;'>
{{icon 'clock'}}
{{vel_shifthours}}
hours
</div>Settings & Utility
Icon Name | Visual | Use Case |
|---|---|---|
| Configuration, settings | |
| Filter options | |
| Search |
Complete Icon List
Status: warning, error, info, success, breach
Favorites: star, star-outline
Actions: edit, delete, copy, paste, save, add, remove, refresh
Navigation: chevron-right, chevron-left, chevron-down, chevron-up
Rostering: calendar, clock, person, person-group, location,
day-shift, night-shift, swap, lock, unlock
Settings: settings, filter, search
Template Examples
Example 1: Basic Card with Name and Type
<div style='padding:8px;display:flex;flex-direction:column;gap:4px;'>
<div style='font-weight:600;font-size:14px;color:rgb(50,49,48);'>
{{name}}
</div>
{{#if resourceType}}
<div style='font-size:12px;color:rgb(96,94,92);'>
{{resourceType}}
</div>
{{/if}}
</div>Renders:
John Smith
Registered NurseExample 2: Card with Avatar Initials
<div style='display:flex;align-items:center;gap:8px;padding:8px;'>
<div
style='
width: 36px;
height: 36px;
border-radius: 50%;
background-color: {{colorFromIndex index}};
color: white;
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
font-size: 14px;
'
>
{{initials name}}
</div>
<div style='flex:1;'>
<div style='font-weight:600;'>{{name}}</div>
<div style='font-size:12px;color:#605E5C;'>{{resourceType}}</div>
</div>
</div>Renders:
[JS] John Smith
Registered Nurse(Where [JS] is a colored circle with initials)
Example 3: Card with Status Indicators
<div style='padding:8px;'>
<div style='font-weight:600;display:flex;align-items:center;gap:4px;'>
{{name}}
{{#if isPreferred}}{{{icon 'star'}}}{{/if}}
</div>
{{#if resourceType}}
<div style='font-size:12px;color:#605E5C;margin-top:4px;'>
{{icon 'person'}}
{{resourceType}}
</div>
{{/if}}
{{#if isDoubleBooked}}
<div
style='font-size:11px;color:#A42626;font-weight:500;margin-top:4px;'
>
{{icon 'warning'}}
Double Booked
</div>
{{/if}}
</div>Renders:
John Smith ★
👤 Registered Nurse
⚠ Double Booked
Example 4: Detailed Card with Custom Fields
<div style='padding:10px;border-left:3px solid {{colorFromIndex index}};'>
<!-- Header -->
<div
style='display:flex;align-items:center;gap:6px;margin-bottom:8px;'
>
<div
style='
width: 32px;
height: 32px;
border-radius: 50%;
background-color: {{colorFromIndex index}};
color: white;
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
font-size: 12px;
'
>
{{initials name}}
</div>
<div style='flex:1;'>
<div style='font-weight:600;font-size:14px;'>
{{name}}
{{#if isPreferred}}{{{icon 'star'}}}{{/if}}
</div>
</div>
</div>
<!-- Details -->
<div
style='display:flex;flex-direction:column;gap:4px;font-size:12px;color:#605E5C;'
>
{{#if resourceType}}
<div>{{{icon 'person'}}} {{resourceType}}</div>
{{/if}}
{{#if vel_territory}}
<div>{{{icon 'location'}}} {{vel_territory}}</div>
{{/if}}
{{#if vel_email}}
<div>✉ {{lowercase vel_email}}</div>
{{/if}}
{{#if vel_skillrating}}
<div>★ Skill: {{vel_skillrating}}/5</div>
{{/if}}
</div>
<!-- Status -->
{{#if isDoubleBooked}}
<div
style='
margin-top: 8px;
padding: 4px 8px;
background-color: #FDE7E9;
color: #A42626;
border-radius: 4px;
font-size: 11px;
font-weight: 500;
'
>
{{icon 'warning'}}
Double Booked
</div>
{{/if}}
</div>Renders: A detailed card with avatar, multiple fields, and status indicator.
Example 5: Compact Horizontal Layout
<div
style='display: flex; align-items: center; justify-content: space-between;
padding: 6px 10px;'
>
<div style='display:flex;align-items:center;gap:8px;'>
<div
style='
width: 28px;
height: 28px;
border-radius: 50%;
background-color: {{colorFromIndex index}};
color: white;
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
font-size: 11px;
'
>
{{initials name}}
</div>
<div>
<div style='font-weight:600;font-size:13px;'>{{name}}</div>
<div style='font-size:11px;color:#605E5C;'>{{truncate
resourceType
20
}}</div>
</div>
</div>
<div style='display:flex;gap:4px;'>
{{#if isPreferred}}{{icon 'star'}}{{/if}}
{{#if isDoubleBooked}}{{icon 'warning'}}{{/if}}
</div>
</div>Example 6: Role-Based Styling
<div style='padding:10px;'>hand
{{#ifEquals resourceType 'Registered Nurse'}}
<div style='background-color:#E3F2FD;padding:8px;border-radius:4px;'>
<div style='font-weight:600;color:#1976D2;'>
{{icon 'person'}}
{{name}}
</div>
<div style='font-size:12px;color:#1565C0;'>RN - Registered Nurse</div>
</div>
{{else}}
{{#ifEquals resourceType 'Licensed Practical Nurse'}}
<div style='background-color:#F3E5F5;padding:8px;border-radius:4px;'>
<div style='font-weight:600;color:#7B1FA2;'>
{{icon 'person'}}
{{name}}
</div>
<div style='font-size:12px;color:#6A1B9A;'>LPN - Licensed Practical Nurse</div>
</div>
{{else}}
<div style='padding:8px;'>
<div style='font-weight:600;'>{{name}}</div>
<div style='font-size:12px;color:#605E5C;'>{{resourceType}}</div>
</div>
{{/ifEquals}}
{{/ifEquals}}
</div>This template applies different background colors and styling based on the resource type.
Styling Guidelines
Recommended Inline Styles
Templates support inline CSS styles only (no external CSS classes). Use the style attribute.
Typography
<!-- Primary text -->
<div style='font-weight:600;font-size:14px;color:rgb(50,49,48);'>
{{name}}
</div>
<!-- Secondary text -->
<div style='font-size:12px;color:rgb(96,94,92);'>
{{resourceType}}
</div>
<!-- Small text -->
<div style='font-size:11px;color:rgb(96,94,92);'>
Additional info
</div>Colors
Use Fluent UI color palette for consistency:
Use Case | Color | RGB Value |
|---|---|---|
Primary text | Near-black |
|
Secondary text | Gray |
|
Error/Warning | Red |
|
Success | Green |
|
Info/Link | Blue |
|
Background (error) | Light red |
|
Background (info) | Light blue |
|
Border | Light gray |
|
Layout
<!-- Flexbox container -->
<div style='display:flex;flex-direction:column;gap:4px;'>
<!-- Content -->
</div>
<!-- Horizontal flex -->
<div style='display:flex;align-items:center;gap:8px;'>
<!-- Content -->
</div>
<!-- Padding -->
<div style='padding:8px;'>
<!-- Content -->
</div>
<!-- Margins -->
<div style='margin-top:4px;margin-bottom:8px;'>
<!-- Content -->
</div>Borders & Radius
<!-- Rounded corners -->
<div style='border-radius:4px;'>
<!-- Content -->
</div>
<!-- Circle (for avatars) -->
<div style='border-radius:50%;'>
<!-- Content -->
</div>
<!-- Border -->
<div style='border:1px solid rgb(237,235,233);'>
<!-- Content -->
</div>
<!-- Left accent border -->
<div style='border-left:3px solid {{colorFromIndex index}};'>
<!-- Content -->
</div>Accessibility Considerations
Color Contrast: Ensure sufficient contrast between text and background
Minimum 4.5:1 ratio for normal text
Minimum 3:1 for large text (18pt+)
Icon Meanings: Don't rely solely on color to convey meaning
Use icons with color
Include text labels
Font Size: Keep text readable
Minimum 11px for small text
12-14px for body text
16px+ for headers
Best Practices
Keep Cards Compact
Resource cards should fit comfortably in a vertical list. Aim for heights between 60-120px.
<div style='padding:30px;font-size:18px;'>
<!-- Too much padding andnd large font -->
</div><div style='padding:8px;font-size:14px;'>
<!-- Compact and readable -->
</div>Use Conditional Rendering
Only show fields when they have values.
❌ Don't:
<div>Email: {{vel_email}}</div>
<!-- Shows "Email: " even if empty -->✅ Do:
{{#if vel_email}}
<div>Email: {{vel_email}}</div>
{{/if}}Handle Missing Data Gracefully
Always provide fallbacks for optional fields.
<div>
{{#if resourceType}}
{{resourceType}}
{{else}}
<span style='color:#A0A0A0;'>No Type Specified</span>
{{/if}}
</div>Maintain Visual Hierarchy
Use font weight, size, and color to establish importance.
<!-- Primary info (largest, boldest) -->
<div style='font-weight:600;font-size:14px;color:rgb(50,49,48);'>
{{name}}
</div>
<!-- Secondary info (medium) -->
<div style='font-size:12px;color:rgb(96,94,92);'>
{{resourceType}}
</div>
<!-- Tertiary info (smallest) -->
<div style='font-size:11px;color:rgb(96,94,92);'>
{{vel_employeeid}}
</div>Consistent Spacing
Use consistent gap values throughout your template.
Recommended spacing scale:
gap: 4px- Tight spacing (within a section)gap: 8px- Medium spacing (between sections)gap: 12px- Loose spacing (major separators)
<div style='display:flex;flex-direction:column;gap:4px;'>
<!-- Items close together -->
</div>Optimise for Scanning
Users often scan lists quickly. Put the most important information first and make it visually distinct.
Good hierarchy:
Name (largest, bold)
Role/Type (medium, secondary color)
Status indicators (icons, colored badges)
Additional details (smallest, tertiary color)
Test with Real Data
Test your templates in a development environment with realistic data that matches your production environment. Test edge cases:
Very long names
Missing fields
Multiple status flags active
Resources with all custom fields populated
Tip: Use browser developer tools to inspect the rendered HTML and verify your template output.
Performance Considerations
Avoid complex nested loops - Each card renders many times
Use helpers efficiently - Helpers like
colorFromIndexare optimisedKeep HTML minimal - More DOM nodes = slower rendering
Troubleshooting
Problem: Template shows blank cards
Possible Causes:
Syntax error in Handlebars
Missing closing tags (
{{/if}},{{/each}})Field name typo
Solution:
Check browser console for Handlebars compilation errors
Verify all
{{#if}}blocks have matching{{/if}}closingsVerify field names match your data exactly (case-sensitive)
Problem: Icons not appearing
Possible Causes:
Icon name typo
Using quotes incorrectly
Solution:
<!-- ✖ Wrong -->
{{icon 'warning'}}
<!-- ✅ Correct -->
{{icon "warning"}}Problem: Data not showing
Possible Causes:
Field not included in
resourceExplorerApiResourceFieldsapp settingField name mismatch
Data not available for that resource
Solution:
Check browser console to see the actual resource data being passed to the template
Verify
resourceExplorerApiResourceFieldsapp setting includes your custom fieldUse
{{#if fieldName}}to handle missing data
Problem: Styling not working
Possible Causes:
Invalid CSS syntax
Using external CSS classes (not supported)
Missing semicolons in style attribute
Solution:
<!-- ✖ Wrong - missing semicolon -->
<div style="color:red font-size:14px">
<!-- ✅ Correct -->
<div style="color:red;font-size:14px;">Problem: Cards different heights
Cause: Conditional content creates variable-height cards
Solution: Use fixed height or min-height if consistency is important
<div style='min-height:80px;padding:8px;'>
<!-- Content -->
</div>Advanced Techniques
Creating Status Badges
{{#if isDoubleBooked}}
<div
style='
display: inline-block;
padding: 2px 8px;
background-color: #FDE7E9;
color: #A42626;
border-radius: 12px;
font-size: 11px;
font-weight: 500;
'
>
{{icon 'warning'}}
Double Booked
</div>
{{/if}}Multi-Column Layouts
<div style='display:grid;grid-template-columns:1fr 1fr;gap:8px;padding:8px;'>
<div>
<div style='font-size:11px;color:#605E5C;'>Name</div>
<div style='font-weight:600;'>{{name}}</div>
</div>
<div>
<div style='font-size:11px;color:#605E5C;'>Type</div>
<div style='font-weight:600;'>{{resourceType}}</div>
</div>
<div>
<div style='font-size:11px;color:#605E5C;'>Territory</div>
<div style='font-weight:600;'>{{vel_territory}}</div>
</div>
<div>
<div style='font-size:11px;color:#605E5C;'>Rating</div>
<div style='font-weight:600;'>{{vel_skillrating}}/5</div>
</div>
</div>Custom Skill Rating Display
{{#if vel_skillrating}}
<div style='display:flex;align-items:center;gap:4px;'>
<span style='font-size:11px;color:#605E5C;'>Skill:</span>
{{#ifEquals vel_skillrating 5}}
<span style='color:#107C10;'>★ ★ ★ ★ ★</span>
{{else}}
{{#ifEquals vel_skillrating 4}}
<span style='color:#107C10;'>★ ★ ★ ★ ☆</span>
{{else}}
{{#ifEquals vel_skillrating 3}}
<span style='color:#FDB900;'>★ ★ ★ ☆ ☆</span>
{{else}}
<span style='color:#FDB900;'>{{vel_skillrating}}/5</span>
{{/ifEquals}}
{{/ifEquals}}
{{/ifEquals}}
</div>
{{/if}}Dynamic Background Colors
<div
style='
padding: 10px;
background: linear-gradient(
to right,
{{colorFromIndex index}}15,
{{colorFromIndex index}}05
);
border-left: 3px solid {{colorFromIndex index}};
'>
<div style='font-weight:600;'>{{name}}</div>
<div style='font-size:12px;color:#605E5C;'>{{resourceType}}</div>
</div>Note: The 15 and 05 are hex opacity values (15% and 5% opacity).
Combining Multiple Conditions
{{#if isPreferred}}
{{#unless isDoubleBooked}}
<div
style='
background-color: #E8F5E9;
color: #2E7D32;
padding: 4px 8px;
border-radius: 4px;
font-size: 11px;
font-weight: 500;
'
>
{{icon 'star'}}
{{icon 'success'}}
Available & Preferred
</div>
{{/unless}}
{/if}}Responsive Text Sizing
<div style='padding:8px;'>
<!-- Name takes available space, truncates if too long -->
<div
style='
font-weight: 600;
font-size: 14px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 200px;
'
>
{{name}}
</div>
<!-- Or use truncate helper -->
<div style='font-weight:600;font-size:14px;'>
{{truncate name 25}}
</div>
</div>Field Labels with Icons
<div style='display:flex;flex-direction:column;gap:6px;font-size:12px;'>
<div style='display:flex;align-items:center;gap:6px;'>
{{icon 'person'}}
<span style='color:#605E5C;'>{{resourceType}}</span>
</div>
{{#if vel_territory}}
<div style='display:flex;align-items:center;gap:6px;'>
{{icon 'location'}}
<span style='color:#605E5C;'>{{vel_territory}}</span>
</div>
{{/if}}
{{#if vel_email}}
<div style='display:flex;align-items:center;gap:6px;'>
<span style='font-size:14px;'>✉</span>
<span style='color:#0078D4;'>{{lowercase vel_email}}</span>
</div>
{{/if}}
</div>Nested Conditions for Complex Logic
<div style='padding:8px;'>
<div style='font-weight:600;font-size:14px;'>{{name}}</div>
<!-- Status badge with priority logic -->
{{#if isDoubleBooked}}
<!-- High priority: show double booked -->
<div style='color:#A42626;font-size:11px;margin-top:4px;'>
{{icon 'warning'}}
Unavailable - Double Booked
</div>
{{else}}
{{#if isPreferred}}
<!-- Medium priority: show preferred if not double booked -->
<div style='color:#107C10;font-size:11px;margin-top:4px;'>
{{icon 'star'}}
Preferred Resource
</div>
{{else}}
<!-- Low priority: show available -->
<div style='color:#605E5C;font-size:11px;margin-top:4px;'>
Available
</div>
{{/if}}
{{/if}}
</div>Summary Checklist
When creating a new template, ensure you:
✅ Use valid Handlebars syntax✅ Include conditional checks for optional fields ({{#if field}})✅ Keep card height reasonable (60-120px)✅ Use inline styles only (no external CSS classes)✅ Test in a development environment before deploying to production✅ Verify field names match your Dataverse configuration✅ Include visual indicators for important states (preferred, double booked)✅ Use helpers to transform data (uppercase,truncate,formatNumber)✅ Maintain consistent spacing and typography✅ Ensure good color contrast for accessibility✅ Handle edge cases (long names, missing data)✅ Save template tovel_appsettingwith keyRoster/RosterPCF/ResourceCardTemplate
Additional Resources
Handlebars Documentation: https://handlebarsjs.com/guide/
Getting Help
If you encounter issues:
Check browser console - Look for Handlebars compilation errors and JavaScript errors
Review sample data - Use browser dev tools to inspect resource data
Test incrementally - Build complex templates step by step, testing after each change
Refer to examples - Copy/modify examples from this guide
Use a development environment - Always test templates before deploying to production