Dynamic Elements
Conditional Rendering

Conditional Rendering

Conditional rendering in Canvelete (opens in a new tab) allows you to show or hide template elements based on data conditions, user permissions, or dynamic states. This powerful feature enables you to create adaptive interfaces that respond intelligently to different scenarios.

Basic Conditional Syntax

If Statements

Show content when a condition is true:

// Simple if condition
"{{#if user.isLoggedIn}}
  <div class='welcome'>Welcome back, {{user.name}}!</div>
{{/if}}"
 
// If with else
"{{#if user.isActive}}
  <span class='status active'>Active</span>
{{else}}
  <span class='status inactive'>Inactive</span>
{{/if}}"
 
// Multiple conditions with else if
"{{#if user.role === 'admin'}}
  <div class='admin-panel'>Admin Controls</div>
{{else if user.role === 'moderator'}}
  <div class='mod-panel'>Moderator Tools</div>
{{else}}
  <div class='user-panel'>User Dashboard</div>
{{/if}}"

Unless Statements

Show content when a condition is false:

// Unless (opposite of if)
"{{#unless user.isLoggedIn}}
  <div class='login-prompt'>Please log in to continue</div>
{{/unless}}"
 
// Unless with else
"{{#unless product.inStock}}
  <div class='out-of-stock'>Out of Stock</div>
{{else}}
  <button class='add-to-cart'>Add to Cart</button>
{{/unless}}"

Inline Conditionals

Short conditional expressions:

// Ternary operator
"{{user.isActive ? 'Active' : 'Inactive'}}"
 
// Logical AND
"{{user.isAdmin && 'Administrator'}}"
 
// Logical OR (default values)
"{{user.displayName || user.username || 'Anonymous'}}"
 
// Nullish coalescing
"{{user.avatar ?? '/images/default-avatar.png'}}"

Complex Conditional Logic

Multiple Conditions

Combine multiple conditions with logical operators:

// AND conditions
"{{#if (user.isActive && user.isVerified)}}
  <div class='verified-user'>Verified Active User</div>
{{/if}}"
 
// OR conditions
"{{#if (user.role === 'admin' || user.role === 'moderator')}}
  <div class='staff-controls'>Staff Controls</div>
{{/if}}"
 
// Mixed logical operators
"{{#if ((user.isActive && user.isVerified) || user.role === 'admin')}}
  <div class='trusted-user'>Trusted User Content</div>
{{/if}}"
 
// Negation
"{{#if (!user.isBanned && !user.isSuspended)}}
  <div class='user-content'>User can post content</div>
{{/if}}"

Comparison Operators

Use various comparison operators:

// Equality
"{{#if user.age === 18}}
  <div class='just-adult'>Just turned 18!</div>
{{/if}}"
 
// Inequality
"{{#if user.loginCount !== 1}}
  <div class='returning-user'>Welcome back!</div>
{{/if}}"
 
// Greater than / Less than
"{{#if user.age >= 21}}
  <div class='adult-content'>Adult Content Available</div>
{{/if}}"
 
"{{#if product.price < 50}}
  <div class='budget-friendly'>Budget Friendly</div>
{{/if}}"
 
// String comparisons
"{{#if user.country === 'US'}}
  <div class='us-specific'>US-specific content</div>
{{/if}}"

Array and Object Conditions

Check array and object properties:

// Array length
"{{#if products.length > 0}}
  <div class='product-list'>
    {{#each products}}
      <div class='product'>{{name}}</div>
    {{/each}}
  </div>
{{else}}
  <div class='empty-state'>No products available</div>
{{/if}}"
 
// Array includes
"{{#if (includes user.permissions 'write')}}
  <button class='edit-button'>Edit</button>
{{/if}}"
 
// Object property existence
"{{#if user.profile}}
  <div class='profile-section'>
    {{#if user.profile.bio}}
      <p>{{user.profile.bio}}</p>
    {{/if}}
  </div>
{{/if}}"
 
// Nested property checks
"{{#if user.settings.notifications.email}}
  <div class='email-notifications'>Email notifications enabled</div>
{{/if}}"

Conditional Styling

Dynamic Classes

Apply CSS classes conditionally:

// Conditional class application
"<div class='user-card {{user.isActive ? 'active' : 'inactive'}} {{user.isPremium ? 'premium' : 'standard'}}'>
  <h3>{{user.name}}</h3>
</div>"
 
// Multiple conditional classes
"<button class='btn {{#if user.canEdit}}btn-primary{{else}}btn-secondary{{/if}} {{user.isLoading ? 'loading' : ''}}'>
  {{user.isLoading ? 'Loading...' : 'Save'}}
</button>"
 
// Class object syntax
{
  "classes": {
    "active": "{{user.isActive}}",
    "premium": "{{user.isPremium}}",
    "new-user": "{{user.loginCount <= 3}}"
  }
}

Dynamic Styles

Apply inline styles conditionally:

// Conditional inline styles
"<div style='color: {{user.isActive ? '#22c55e' : '#ef4444'}}; opacity: {{user.isVisible ? 1 : 0.5}}'>
  {{user.name}}
</div>"
 
// Complex style conditions
"<div style='
  background-color: {{#if user.role === 'admin'}}#3b82f6{{else if user.role === 'moderator'}}#8b5cf6{{else}}#6b7280{{/if}};
  border: {{user.isSelected ? '2px solid #3b82f6' : '1px solid #d1d5db'}};
'>
  User Content
</div>"

Conditional Content Sections

Feature Flags

Show features based on flags:

// Feature flag conditions
"{{#if features.newDashboard}}
  <div class='new-dashboard'>
    <!-- New dashboard content -->
  </div>
{{else}}
  <div class='legacy-dashboard'>
    <!-- Legacy dashboard content -->
  </div>
{{/if}}"
 
// Multiple feature flags
"{{#if (features.advancedSearch && user.isPremium)}}
  <div class='advanced-search'>
    <!-- Advanced search interface -->
  </div>
{{/if}}"

Permission-Based Rendering

Show content based on user permissions:

// Permission checks
"{{#if (hasPermission user.permissions 'admin')}}
  <div class='admin-section'>
    <h2>Admin Controls</h2>
    <!-- Admin-only content -->
  </div>
{{/if}}"
 
// Multiple permission levels
"{{#if (hasAnyPermission user.permissions ['read', 'write', 'admin'])}}
  <div class='content-area'>
    {{#if (hasPermission user.permissions 'write')}}
      <button class='edit-btn'>Edit</button>
    {{/if}}
    {{#if (hasPermission user.permissions 'admin')}}
      <button class='delete-btn'>Delete</button>
    {{/if}}
  </div>
{{else}}
  <div class='no-access'>You don't have permission to view this content</div>
{{/if}}"

Device and Context Conditions

Render based on device or context:

// Device-specific rendering
"{{#if device.isMobile}}
  <div class='mobile-layout'>
    <!-- Mobile-optimized content -->
  </div>
{{else}}
  <div class='desktop-layout'>
    <!-- Desktop layout -->
  </div>
{{/if}}"
 
// Screen size conditions
"{{#if viewport.width > 768}}
  <div class='large-screen-content'>
    <!-- Content for larger screens -->
  </div>
{{/if}}"
 
// Time-based conditions
"{{#if (isBusinessHours currentTime timezone)}}
  <div class='support-available'>Live support available</div>
{{else}}
  <div class='support-offline'>Support offline - leave a message</div>
{{/if}}"

Advanced Conditional Patterns

Nested Conditions

Complex nested conditional logic:

// Deeply nested conditions
"{{#if user.isLoggedIn}}
  {{#if user.hasProfile}}
    {{#if user.profile.isComplete}}
      <div class='complete-profile'>
        Welcome, {{user.profile.displayName}}!
      </div>
    {{else}}
      <div class='incomplete-profile'>
        <a href='/profile/complete'>Complete your profile</a>
      </div>
    {{/if}}
  {{else}}
    <div class='no-profile'>
      <a href='/profile/create'>Create your profile</a>
    </div>
  {{/if}}
{{else}}
  <div class='login-required'>
    <a href='/login'>Please log in</a>
  </div>
{{/if}}"

Switch-Like Conditions

Handle multiple discrete values:

// Switch-like pattern using else if
"{{#if status === 'pending'}}
  <span class='status pending'>⏳ Pending</span>
{{else if status === 'approved'}}
  <span class='status approved'>✅ Approved</span>
{{else if status === 'rejected'}}
  <span class='status rejected'>❌ Rejected</span>
{{else if status === 'cancelled'}}
  <span class='status cancelled'>🚫 Cancelled</span>
{{else}}
  <span class='status unknown'>❓ Unknown</span>
{{/if}}"
 
// Using lookup helper for switch-like behavior
{
  "statusConfig": {
    "pending": {"icon": "⏳", "text": "Pending", "class": "pending"},
    "approved": {"icon": "✅", "text": "Approved", "class": "approved"},
    "rejected": {"icon": "❌", "text": "Rejected", "class": "rejected"}
  }
}
 
"{{#with (lookup statusConfig status)}}
  <span class='status {{class}}'>{{icon}} {{text}}</span>
{{else}}
  <span class='status unknown'>❓ Unknown Status</span>
{{/with}}"

Conditional Loops

Combine conditions with iteration:

// Filter items in loops
"{{#each products}}
  {{#if (and this.inStock (gte this.price minPrice) (lte this.price maxPrice))}}
    <div class='product'>
      <h3>{{this.name}}</h3>
      <p>${{this.price}}</p>
    </div>
  {{/if}}
{{/each}}"
 
// Conditional loop rendering
"{{#if products.length > 0}}
  <div class='product-grid'>
    {{#each products}}
      <div class='product-card'>
        <h3>{{name}}</h3>
        {{#if salePrice}}
          <span class='sale'>${{salePrice}}</span>
          <span class='original'>${{originalPrice}}</span>
        {{else}}
          <span class='price'>${{originalPrice}}</span>
        {{/if}}
      </div>
    {{/each}}
  </div>
{{else}}
  <div class='empty-state'>
    <h3>No products found</h3>
    <p>Try adjusting your search criteria</p>
  </div>
{{/if}}"

Performance Considerations

Lazy Evaluation

Evaluate conditions only when necessary:

// Lazy condition evaluation
"{{#lazy}}
  {{#if (expensiveConditionCheck user)}}
    <div class='expensive-content'>
      {{expensiveContentGeneration}}
    </div>
  {{/if}}
{{/lazy}}"

Condition Caching

Cache expensive condition results:

// Cached condition results
{
  "computed": {
    "canEditPost": "{{user.id === post.authorId || user.role === 'admin'}}",
    "showPremiumFeatures": "{{user.isPremium && features.premiumEnabled}}"
  }
}
 
// Use cached conditions
"{{#if canEditPost}}
  <button class='edit-post'>Edit Post</button>
{{/if}}"
 
"{{#if showPremiumFeatures}}
  <div class='premium-section'>Premium Content</div>
{{/if}}"

Error Handling in Conditions

Safe Condition Evaluation

Handle errors in conditional expressions:

// Safe property access
"{{#if user?.profile?.settings?.darkMode}}
  <div class='dark-theme'>Dark mode content</div>
{{/if}}"
 
// Try-catch in conditions
"{{#if (try (gt user.age 18) catch false)}}
  <div class='adult-content'>Adult content</div>
{{/if}}"
 
// Default values for missing data
"{{#if (user.preferences.notifications || true)}}
  <div class='notifications-enabled'>Notifications on</div>
{{/if}}"

Testing Conditional Logic

Mock Different States

Test various conditional states:

// Test data for different states
{
  "testScenarios": {
    "loggedOutUser": {"user": null},
    "newUser": {"user": {"id": 1, "loginCount": 1}},
    "adminUser": {"user": {"id": 1, "role": "admin"}},
    "premiumUser": {"user": {"id": 1, "isPremium": true}},
    "emptyCart": {"cart": {"items": []}},
    "fullCart": {"cart": {"items": [{"id": 1, "name": "Product"}]}}
  }
}

Condition Documentation

Document complex conditional logic:

// Documented conditions
"{{!-- 
  Show edit button if:
  1. User owns the content (user.id === content.authorId)
  2. User is admin or moderator
  3. Content is not locked
  4. User has edit permissions
--}}
{{#if (and 
  (or (eq user.id content.authorId) (includes ['admin', 'moderator'] user.role))
  (not content.isLocked)
  (includes user.permissions 'edit')
)}}
  <button class='edit-button'>Edit</button>
{{/if}}"

Best Practices

  1. Keep conditions simple: Break complex logic into computed properties
  2. Use meaningful names: Make condition purposes clear
  3. Handle edge cases: Always consider null, undefined, and empty values
  4. Optimize performance: Cache expensive condition evaluations
  5. Test thoroughly: Verify all conditional branches work correctly
  6. Document complex logic: Explain non-obvious conditional requirements
  7. Use consistent patterns: Establish team conventions for conditional rendering
  8. Avoid deep nesting: Refactor deeply nested conditions into helper functions

Common Patterns

Loading States

"{{#if isLoading}}
  <div class='loading-spinner'>Loading...</div>
{{else if error}}
  <div class='error-message'>{{error.message}}</div>
{{else if data}}
  <div class='content'>{{data}}</div>
{{else}}
  <div class='empty-state'>No data available</div>
{{/if}}"

Form Validation

"{{#if form.submitted}}
  {{#if form.errors.email}}
    <div class='error'>{{form.errors.email}}</div>
  {{/if}}
  {{#if form.errors.password}}
    <div class='error'>{{form.errors.password}}</div>
  {{/if}}
{{/if}}"

Progressive Disclosure

"<div class='user-card'>
  <h3>{{user.name}}</h3>
  {{#if showDetails}}
    <p>{{user.bio}}</p>
    <p>Member since: {{user.joinDate | date}}</p>
    {{#if user.isActive}}
      <p>Last seen: {{user.lastSeen | fromNow}}</p>
    {{/if}}
  {{/if}}
  <button onclick='toggleDetails()'>
    {{showDetails ? 'Hide' : 'Show'}} Details
  </button>
</div>"

Next Steps