Control Flow

Conditionals, loops, and pattern matching for dynamic template content.

Raw Blocks

Inside @#...#@ raw blocks (any matching number of #), content is output verbatim - no escaping needed. The @@ escape is only needed outside raw blocks to output a literal @.

Conditionals (@if)

Render content based on conditions:

@if user.is_admin {
    Admin
}

With else

@if user.is_logged_in {
    

Welcome back, @user.name!

} else {

Please sign in.

}

With else if

@if user.role == "admin" {
    Admin
} else if user.role == "moderator" {
    Moderator
} else {
    Member
}

Pattern Matching (if let)

@if let Some(email) = user.email {
    @email
}

@if let Ok(data) = fetch_result {
    
@data
} else {

Failed to load data

}

Conditionals in Attributes

Add attributes conditionally:

Real-world example:


@if let Some(err) = errors.get("email") {
    @err
}

Loops (@for)

Iterate over collections:

@for item in items {
    
  • @item.name
  • }

    With Index

    @for (index, item) in items.iter().enumerate() {
        
            @(index + 1)
            @item.name
        
    }

    With Tuple Destructuring

    @for (key, value) in settings {
        
    @key
    @value
    }

    Labeled Loops

    Use labels with @break and @continue:

    @for outer: row in grid.rows {
        
            @for cell in row.cells {
                @if cell.is_stop_marker {
                    @break :outer;
                }
                @if cell.is_hidden {
                    @continue;
                }
                @cell.value
            }
        
    }

    Dynamic Attributes in Loops

    Content

    Pattern Matching (@match)

    Match on enums and values:

    @match status {
        Status::Active => {
            Active
        }
        Status::Pending => {
            Pending
        }
        Status::Inactive => {
            Inactive
        }
    }

    With Destructuring

    @match result {
        Ok(user) => {
            

    Welcome, @user.name!

    } Err(e) => {

    Error: @e

    } }

    With Guards

    @match score {
        n if n >= 90 => { A }
        n if n >= 80 => { B }
        n if n >= 70 => { C }
        _ => { F }
    }

    Loop Control

    @break

    @for item in items {
        @if item.id == target_id {
            

    Found: @item.name

    @break; } }

    @continue

    @for item in items {
        @if item.hidden {
            @continue;
        }
        
  • @item.name
  • }

    Complete Example

    Combining control flow constructs:

    @fn apply(user: Option, items: Vec) {
        @if let Some(user) = user {
            

    Welcome, @user.name!

    @match user.subscription { Subscription::Free => {

    You're on the free plan. Upgrade

    } Subscription::Pro => {

    Pro Member

    } }
      @for (i, item) in items.iter().enumerate() { @if !item.archived {
    • @item.name @if let Some(desc) = item.description {

      @desc

      }
    • } }
    } else {

    Please sign in to continue.

    } }