Telerik blogs

The powerful template syntax in Angular allows us to easily manipulate the DOM, bind data and control the flow of our application's user interface. In this article, we’ll be zoning in on three powerful control flow blocks—@if, @for and @switch.

When diving into the world of Angular, one of the first things you’ll encounter is the powerful template syntax. This syntax allows you to easily manipulate the DOM, bind data and control the flow of your application’s user interface.

In this article, we’ll be zoning in on three control flow blocks—@if, @for and @switch.

Exploring the @if Block

Imagine you’re tasked with displaying content conditionally; you want certain elements to appear only if specific criteria are met. Enter @if, a control block that dynamically includes or excludes template content based on a given condition’s truthiness.

Consider you’re creating a feature that welcomes users by name if they’re logged in. Using @if, your code snippet could look like this:

@Component({
  template: `
    @if (user.isLoggedIn) {
      <div>Hello, {{ user.name }}! Great to see you again.</div>
    }
  `,
})
class WelcomeComponent {
  user = {
    isLoggedIn: true,
    name: 'John Doe',
  };
}

In the above example, the @if block is used within an Angular component to conditionally render a welcome message for a user if they are logged in. The @if directive checks the truthiness of the user.isLoggedIn property. If true, Angular dynamically includes the specified HTML content.

The brilliance of @if lies in its straightforward approach: If the condition evaluates to true, the element is part of the DOM; if not, it’s as if it never existed. But what about situations where you want to offer an alternative for when the condition fails? @if gracefully handles this with an @else condition:

@Component({
  template: `
    @if (user.isLoggedIn) {
      <div>Hello, {{ user.name }}! Great to see you again.</div>
    } @else {
      <div>Welcome, guest. Please sign in.</div>
    }
  `,
})
class WelcomeComponent {
  user = {
    isLoggedIn: true,
    name: 'John Doe',
  };
}

In this above example, an @else block is introduced to provide an alternative UI piece in cases where the initial @if condition fails. Here, if the user.isLoggedIn evaluates to false, the template renders a different piece of content inviting the user to sign in.

There also exists an @else if block that allows for additional conditional checks within the same sequence, enabling more complex logic flows by providing intermediate conditions before reaching the final @else.

@Component({
  template: `
    @if (user.status === 'loggedIn') {
      <div>Hello, {{ user.name }}! Great to see you again.</div>
    } @else if (user.status === 'loggedOut') {
      <div>Welcome, guest. Please sign in.</div>
    } @else {
      <div>Could not determine user status. Please try reloading the page.</div>
    }
  `,
})
class UserStatusComponent {
  user = {
    status: 'loggedIn', // Can be 'loggedIn', 'loggedOut', or any other status
    name: 'John Doe',
  };
}

The use of @if, @else if and @else within the above component enables more nuanced conditional rendering based on the user.status property. This scenario exemplifies handling multiple conditions within a single template block, offering a tailored UI response for each possible state of the user.status.

By utilizing @if, @else if and @else, developers can create more engaging and responsive user interfaces that cater to a variety of user states or conditions, making the application more intuitive and user-friendly.

Exploring the @for Block

The @for block in Angular introduces a powerful way to iterate over collections and render lists of elements dynamically within templates. This helps simplify the process of creating repetitive structures based on an array or an object’s properties, significantly reducing the amount of boilerplate code and enhancing readability.

Imagine we have an array of items representing tasks that users need to complete, and we want to render a list showing each task.

class TaskListComponent {
  tasks = [
    { name: 'Task 1', status: 'Pending' },
    { name: 'Task 2', status: 'Completed' },
    { name: 'Task 3', status: 'In Progress' },
  ];
}

With @for, we can easily map over this array and generate the corresponding HTML elements for each item in the collection.

@Component({
  template: `
    <ul>
      @for (task of tasks; track task.id) {
        <li>{{ task.name }} - {{ task.status }}</li>
      }
    </ul>
  `,
})
class TaskListComponent {
  tasks = [
    { id: 1, name: 'Task 1', status: 'Pending' },
    { id: 2, name: 'Task 2', status: 'Completed' },
    { id: 3, name: 'Task 3', status: 'In Progress' },
  ];
}

In the above snippet, the @for block iterates over the tasks array, creating a list item (<li>) for each task. Each task’s name and status are dynamically inserted into the template which keeps the template clean and focused while the underlying framework takes care of the rendering logic.

The track task.id statement in the @for directive is Angular’s way of optimizing the rendering process by tracking each item in the list by its unique identifier. This technique is particularly beneficial when dealing with dynamic lists where items may be added, removed or reordered.

The @for directive can be enhanced with an @empty block, showcasing Angular’s capability to handle scenarios where the collection to be iterated over is empty.

@Component({
  template: `
    <ul>
      @for (task of tasks; track task.id) {
        <li>{{ task.name }} - {{ task.status }}</li>
      } @empty {
        <li>No tasks available</li>
      }
    </ul>
  `,
})
class TaskListComponent {
  tasks = []; // Initially, the tasks array is empty.
}

In the above snippet, when the tasks array is empty, rather than rendering an empty <ul> element or requiring additional conditional logic outside of the @for directive, the @empty block is automatically rendered. It provides a clear, user-friendly message (“No tasks available”) directly within the context of the intended list.

Exploring the @switch Block

The @switch block in Angular brings the power of conditional logic to templates, allowing for complex decision-making based on the value of an expression. Similar to switch statements in many programming languages, @switch in Angular templates provides a way to execute one of many code blocks based on an expression’s value.

Consider an application that displays different messages based on the current weather condition. The @switch statement can manage this efficiently:

@Component({
  template: `
    @switch (weather.condition) {
      @case ("sunny") {
        <div>It's a bright sunny day!</div> 
      }
      @case ("rainy") {
        <div>Don't forget your umbrella. It's raining outside!</div> 
      }
      @case ("cloudy") {
        <div>The sky is covered with clouds today.</div>
      }
      @default {
        <div>Weather information not available.</div> 
      }
    }
  `,
})
class WeatherComponent {
  weather = {
    condition: 'sunny', // Can be 'sunny', 'rainy', 'cloudy', etc.
  };
}

In the above snippet, the @switch directive evaluates weather.condition and renders a block of HTML corresponding to the matched case. The @default case provides a fallback option, ensuring that the template can gracefully handle unexpected values.

The @switch directive is particularly useful for scenarios where multiple conditions need to be checked against the same expression, as it avoids the need for nested @if or @else if directives.

Wrap-up

In this article, we’ve taken a deep dive into Angular’s template syntax, focusing on the powerful control flow blocks: @if, @for and @switch. These blocks provide Angular developers with the tools necessary to create dynamic, responsive applications that adapt to the data they present.

  • The @if block allows for conditional rendering of template parts, making it straightforward to show or hide elements based on the application state.
  • The @for block streamlines the process of rendering lists and managing dynamic collections, enabling efficient iteration over arrays and objects.
  • The @switch block offers a clean way to handle multiple conditions within templates, reducing complexity and improving readability.

Each of these blocks enhances the Angular template’s capability to handle dynamic content, manage state-dependent layouts and present data in an organized, efficient manner. By leveraging @if, @for and @switch, we can significantly reduce boilerplate code and increase the maintainability and scalability of our applications.

For more details on Angular’s built-in control flow blocks, be sure to check out the official documentation!


About the Author

Hassan Djirdeh

Hassan is a senior frontend engineer and has helped build large production applications at-scale at organizations like Doordash, Instacart and Shopify. Hassan is also a published author and course instructor where he’s helped thousands of students learn in-depth frontend engineering skills like React, Vue, TypeScript, and GraphQL.

Related Posts

Comments

Comments are disabled in preview mode.