> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/angular/angular/llms.txt
> Use this file to discover all available pages before exploring further.

# Common Directives

> Built-in directives from @angular/common for DOM manipulation

# Common Directives

Angular's `@angular/common` package provides essential directives for manipulating the DOM structure and styling elements in your templates.

<Warning>
  **Deprecation Notice**: Structural directives (`ngIf`, `ngFor`, `ngSwitch`) are deprecated as of Angular v20 and will be removed in v22. Use the new [control flow syntax](https://angular.dev/guide/templates/control-flow) instead.
</Warning>

## Structural Directives

Structural directives change the DOM structure by adding or removing elements.

### NgIf

Conditionally includes a template based on the value of an expression.

<Tabs>
  <Tab title="Syntax">
    ```typescript theme={null}
    @Directive({
      selector: '[ngIf]'
    })
    export class NgIf<T = unknown> {
      @Input() ngIf: T;
      @Input() ngIfThen: TemplateRef<NgIfContext<T>> | null;
      @Input() ngIfElse: TemplateRef<NgIfContext<T>> | null;
    }
    ```
  </Tab>

  <Tab title="Examples">
    ```html theme={null}
    <!-- Simple usage -->
    <div *ngIf="condition">Content to render when condition is true.</div>

    <!-- With else block -->
    <div *ngIf="condition; else elseBlock">Content when true</div>
    <ng-template #elseBlock>Content when false</ng-template>

    <!-- With then and else -->
    <div *ngIf="condition; then thenBlock else elseBlock"></div>
    <ng-template #thenBlock>Content when true</ng-template>
    <ng-template #elseBlock>Content when false</ng-template>

    <!-- Store value locally -->
    <div *ngIf="user$ | async as user">
      Welcome, {{ user.name }}!
    </div>
    ```
  </Tab>

  <Tab title="Migration">
    ```html theme={null}
    <!-- Old (Deprecated) -->
    <div *ngIf="condition; else elseBlock">True content</div>
    <ng-template #elseBlock>False content</ng-template>

    <!-- New (Recommended) -->
    @if (condition) {
      <div>True content</div>
    } @else {
      <div>False content</div>
    }
    ```
  </Tab>
</Tabs>

**Import:**

```typescript theme={null}
import { NgIf } from '@angular/common';
```

**Source:** `packages/common/src/directives/ng_if.ts:166`

***

### NgFor

Renders a template for each item in a collection.

<Tabs>
  <Tab title="Syntax">
    ```typescript theme={null}
    @Directive({
      selector: '[ngFor][ngForOf]'
    })
    export class NgForOf<T, U extends NgIterable<T> = NgIterable<T>> {
      @Input() ngForOf: (U & NgIterable<T>) | undefined | null;
      @Input() ngForTrackBy: TrackByFunction<T>;
      @Input() ngForTemplate: TemplateRef<NgForOfContext<T, U>>;
    }
    ```
  </Tab>

  <Tab title="Examples">
    ```html theme={null}
    <!-- Basic iteration -->
    <li *ngFor="let item of items">{{ item }}</li>

    <!-- With index -->
    <li *ngFor="let item of items; index as i">
      {{ i + 1 }}. {{ item }}
    </li>

    <!-- With tracking function -->
    <li *ngFor="let item of items; trackBy: trackByFn">
      {{ item.name }}
    </li>

    <!-- With local variables -->
    <li *ngFor="let item of items; first as isFirst; last as isLast; even as isEven">
      <span *ngIf="isFirst">First: </span>
      {{ item }}
      <span *ngIf="isLast"> (Last)</span>
      <span *ngIf="isEven"> [Even]</span>
    </li>
    ```
  </Tab>

  <Tab title="Context Variables">
    The following variables are available in the template context:

    * `$implicit: T` - The current item
    * `ngForOf: NgIterable<T>` - The collection being iterated
    * `index: number` - Current index (0-based)
    * `count: number` - Total number of items
    * `first: boolean` - True if first item
    * `last: boolean` - True if last item
    * `even: boolean` - True if even index
    * `odd: boolean` - True if odd index
  </Tab>

  <Tab title="Migration">
    ```html theme={null}
    <!-- Old (Deprecated) -->
    <li *ngFor="let item of items; trackBy: trackByFn">
      {{ item }}
    </li>

    <!-- New (Recommended) -->
    @for (item of items; track item.id) {
      <li>{{ item }}</li>
    }
    ```
  </Tab>
</Tabs>

**Import:**

```typescript theme={null}
import { NgFor } from '@angular/common';
```

**Source:** `packages/common/src/directives/ng_for_of.ts:177`

<Tip>
  Always provide a `trackBy` function for better performance when iterating over large lists or lists that change frequently.
</Tip>

***

### NgSwitch

Switches between views based on a matching expression.

<Tabs>
  <Tab title="Syntax">
    ```typescript theme={null}
    @Directive({
      selector: '[ngSwitch]'
    })
    export class NgSwitch {
      @Input() ngSwitch: any;
    }

    @Directive({
      selector: '[ngSwitchCase]'
    })
    export class NgSwitchCase {
      @Input() ngSwitchCase: any;
    }

    @Directive({
      selector: '[ngSwitchDefault]'
    })
    export class NgSwitchDefault {}
    ```
  </Tab>

  <Tab title="Examples">
    ```html theme={null}
    <!-- Basic switch -->
    <div [ngSwitch]="status">
      <p *ngSwitchCase="'active'">Active Status</p>
      <p *ngSwitchCase="'inactive'">Inactive Status</p>
      <p *ngSwitchCase="'pending'">Pending Status</p>
      <p *ngSwitchDefault>Unknown Status</p>
    </div>

    <!-- Multiple cases for same view -->
    <div [ngSwitch]="value">
      <p *ngSwitchCase="1">One</p>
      <p *ngSwitchCase="2">Two</p>
      <p *ngSwitchCase="3">Three</p>
      <p *ngSwitchDefault>Other number</p>
    </div>

    <!-- Nested switch -->
    <div [ngSwitch]="outer">
      <div *ngSwitchCase="'a'">
        <div [ngSwitch]="inner">
          <p *ngSwitchCase="1">A-1</p>
          <p *ngSwitchCase="2">A-2</p>
        </div>
      </div>
      <div *ngSwitchDefault>Default</div>
    </div>
    ```
  </Tab>

  <Tab title="Migration">
    ```html theme={null}
    <!-- Old (Deprecated) -->
    <div [ngSwitch]="status">
      <p *ngSwitchCase="'active'">Active</p>
      <p *ngSwitchCase="'pending'">Pending</p>
      <p *ngSwitchDefault>Unknown</p>
    </div>

    <!-- New (Recommended) -->
    @switch (status) {
      @case ('active') {
        <p>Active</p>
      }
      @case ('pending') {
        <p>Pending</p>
      }
      @default {
        <p>Unknown</p>
      }
    }
    ```
  </Tab>
</Tabs>

**Import:**

```typescript theme={null}
import { NgSwitch, NgSwitchCase, NgSwitchDefault } from '@angular/common';
```

**Source:** `packages/common/src/directives/ng_switch.ts:120`

<Note>
  As of Angular v17, `NgSwitch` uses strict equality (`===`) instead of loose equality (`==`) for matching cases.
</Note>

***

## Attribute Directives

Attribute directives modify the appearance or behavior of DOM elements without changing the structure.

### NgClass

Adds and removes CSS classes on an HTML element.

<Tabs>
  <Tab title="Syntax">
    ```typescript theme={null}
    @Directive({
      selector: '[ngClass]'
    })
    export class NgClass implements DoCheck {
      @Input('class') klass: string;
      @Input('ngClass') ngClass: string | string[] | Set<string> | {
        [klass: string]: any
      } | null | undefined;
    }
    ```
  </Tab>

  <Tab title="Examples">
    ```html theme={null}
    <!-- String -->
    <div [ngClass]="'class1 class2 class3'">Content</div>

    <!-- Array -->
    <div [ngClass]="['class1', 'class2', 'class3']">Content</div>

    <!-- Object -->
    <div [ngClass]="{
      'active': isActive,
      'disabled': isDisabled,
      'highlighted': isHighlighted
    }">Content</div>

    <!-- Set -->
    <div [ngClass]="classSet">Content</div>

    <!-- Combined with class attribute -->
    <div class="base-class" [ngClass]="dynamicClasses">Content</div>
    ```
  </Tab>

  <Tab title="Component">
    ```typescript theme={null}
    @Component({
      selector: 'app-example',
      template: `
        <div [ngClass]="currentClasses">Multiple classes</div>
        <button (click)="toggleActive()">Toggle</button>
      `
    })
    export class ExampleComponent {
      isActive = false;
      hasError = false;

      currentClasses = {
        'active': this.isActive,
        'error': this.hasError,
        'large': true
      };

      toggleActive() {
        this.isActive = !this.isActive;
        this.updateClasses();
      }

      updateClasses() {
        this.currentClasses = {
          'active': this.isActive,
          'error': this.hasError,
          'large': true
        };
      }
    }
    ```
  </Tab>
</Tabs>

**Import:**

```typescript theme={null}
import { NgClass } from '@angular/common';
```

**Source:** `packages/common/src/directives/ng_class.ts:79`

<Tip>
  For simple use cases, prefer [class bindings](https://angular.dev/guide/templates/binding#css-class-and-style-property-bindings) like `[class.active]="isActive"` instead of `ngClass`.
</Tip>

***

### NgStyle

Updates styles for the containing HTML element.

<Tabs>
  <Tab title="Syntax">
    ```typescript theme={null}
    @Directive({
      selector: '[ngStyle]'
    })
    export class NgStyle implements DoCheck {
      @Input('ngStyle') ngStyle: { [klass: string]: any } | null | undefined;
    }
    ```
  </Tab>

  <Tab title="Examples">
    ```html theme={null}
    <!-- Object of styles -->
    <div [ngStyle]="{
      'color': textColor,
      'font-size': fontSize + 'px',
      'background-color': bgColor
    }">Content</div>

    <!-- With units -->
    <div [ngStyle]="{
      'width.px': width,
      'height.%': height,
      'margin.em': margin
    }">Content</div>

    <!-- Dynamic styles -->
    <div [ngStyle]="currentStyles">Content</div>
    ```
  </Tab>

  <Tab title="Component">
    ```typescript theme={null}
    @Component({
      selector: 'app-example',
      template: `
        <div [ngStyle]="currentStyles">Styled content</div>
      `
    })
    export class ExampleComponent {
      canSave = true;
      isUnchanged = true;
      isSpecial = true;

      currentStyles: Record<string, string> = {};

      ngOnInit() {
        this.setCurrentStyles();
      }

      setCurrentStyles() {
        this.currentStyles = {
          'font-style': this.canSave ? 'italic' : 'normal',
          'font-weight': !this.isUnchanged ? 'bold' : 'normal',
          'font-size': this.isSpecial ? '24px' : '12px'
        };
      }
    }
    ```
  </Tab>
</Tabs>

**Import:**

```typescript theme={null}
import { NgStyle } from '@angular/common';
```

**Source:** `packages/common/src/directives/ng_style.ts:64`

<Tip>
  For simple use cases, prefer [style bindings](https://angular.dev/guide/templates/binding#css-class-and-style-property-bindings) like `[style.color]="color"` instead of `ngStyle`.
</Tip>

***

## Usage Notes

### Importing Directives

<CodeGroup>
  ```typescript CommonModule theme={null}
  import { CommonModule } from '@angular/common';

  @Component({
    imports: [CommonModule],
    // ...
  })
  ```

  ```typescript Individual Imports theme={null}
  import { NgIf, NgFor, NgClass, NgStyle } from '@angular/common';

  @Component({
    imports: [NgIf, NgFor, NgClass, NgStyle],
    // ...
  })
  ```
</CodeGroup>

### Performance Considerations

<AccordionGroup>
  <Accordion title="NgFor Performance">
    Always use `trackBy` with `*ngFor` when rendering lists that may change:

    ```typescript theme={null}
    trackByFn(index: number, item: Item): number {
      return item.id; // Use unique identifier
    }
    ```
  </Accordion>

  <Accordion title="Change Detection">
    * `NgClass` and `NgStyle` implement custom change detection for deep object comparison
    * Use immutable data patterns for better performance
    * Consider using direct bindings for simple cases
  </Accordion>
</AccordionGroup>

## See Also

<CardGroup cols={2}>
  <Card title="Control Flow" icon="code-branch" href="https://angular.dev/guide/templates/control-flow">
    Modern control flow syntax
  </Card>

  <Card title="Template Syntax" icon="code" href="https://angular.dev/guide/templates">
    Angular template guide
  </Card>

  <Card title="Structural Directives" icon="layer-group" href="https://angular.dev/concepts/dependency-injectionrectives/structural-directives">
    Creating custom directives
  </Card>

  <Card title="Pipes" icon="filter" href="/api/common/pipes">
    Common pipes reference
  </Card>
</CardGroup>
