Angular Directives Structural and Attribute Directives

Angular is a powerful front-end framework that allows developers to build dynamic and interactive web applications. One of the core features of Angular is directives, which are instructions in the DOM that modify the behavior or appearance of elements. Directives are broadly categorized into two types: structural directives and attribute directives.


Table of Contents

  1. Introduction to Angular Directives
  2. Structural Directives
    1. *ngIf
    2. *ngFor
  3. Attribute Directives
    1. [ngStyle]
    2. [ngClass]
  4. Combining Directives
  5. Practical Examples and Use Cases
  6. Performance Considerations
  7. Best Practices
  8. Common Mistakes
  9. Conclusion

1. Introduction to Angular Directives

In Angular, a directive is a class that adds behavior to elements in your Angular applications. Directives can:

  • Change the structure of the DOM
  • Modify element appearance and style
  • Respond to user events

Angular categorizes directives into three main types:

  1. Component Directives: These are the most common and include Angular components.
  2. Structural Directives: Change the DOM structure by adding, removing, or manipulating elements.
  3. Attribute Directives: Change the appearance or behavior of elements without changing the DOM structure.

This post focuses specifically on structural directives (*ngIf and *ngFor) and attribute directives ([ngStyle] and [ngClass]).


2. Structural Directives

Structural directives are responsible for modifying the structure of the DOM. They can add, remove, or replace elements based on conditions or loops.

2.1 *ngIf Directive

The *ngIf directive is used to conditionally include or remove elements in the DOM based on a Boolean expression.

Syntax:

<div *ngIf="condition">
  Content to display if condition is true
</div>
  • condition: A boolean expression. If true, the element is rendered; if false, the element is removed from the DOM.

Example:

// app.component.ts
export class AppComponent {
  isLoggedIn: boolean = true;
}
<!-- app.component.html -->
<div *ngIf="isLoggedIn">
  Welcome, user!
</div>
<div *ngIf="!isLoggedIn">
  Please log in.
</div>

In this example, the message “Welcome, user!” will appear only if isLoggedIn is true.

Using *ngIf with else

Angular allows using an else clause for *ngIf.

<div *ngIf="isLoggedIn; else loginTemplate">
  Welcome, user!
</div>
<ng-template #loginTemplate>
  Please log in.
</ng-template>

Here, if isLoggedIn is false, the template #loginTemplate will be rendered.


2.2 *ngFor Directive

The *ngFor directive is used to iterate over a collection and render a template for each item in the collection.

Syntax:

<li *ngFor="let item of items">
  {{item}}
</li>
  • let item of items: Iterates over the items array and assigns each element to item.

Example:

// app.component.ts
export class AppComponent {
  items: string[] = ['Apple', 'Banana', 'Cherry'];
}
<!-- app.component.html -->
<ul>
  <li *ngFor="let item of items">{{item}}</li>
</ul>

This code will render:

  • Apple
  • Banana
  • Cherry

Using index and other variables

*ngFor also allows access to index, first, last, and even/odd properties.

<li *ngFor="let item of items; let i = index; let isFirst = first">
  {{i + 1}}. {{item}} <span *ngIf="isFirst">(First Item)</span>
</li>

3. Attribute Directives

Attribute directives are used to change the appearance or behavior of elements. Unlike structural directives, they do not add or remove elements; they only modify existing elements.


3.1 [ngStyle] Directive

The [ngStyle] directive allows you to dynamically set CSS styles for an element based on component data.

Syntax:

<div [ngStyle]="{'property': value, 'property2': value2}">
  Styled content
</div>

Example:

// app.component.ts
export class AppComponent {
  isHighlighted: boolean = true;
  color: string = 'red';
}
<!-- app.component.html -->
<div [ngStyle]="{'color': color, 'font-weight': isHighlighted ? 'bold' : 'normal'}">
  This is dynamically styled text
</div>

Here, the text color and font weight are applied dynamically depending on component variables.

Dynamic styles using component object

You can also define an object in the component for styles:

styles = {
  color: 'blue',
  'font-size': '20px'
};
<div [ngStyle]="styles">
  This text is blue and 20px in size
</div>

3.2 [ngClass] Directive

The [ngClass] directive allows you to dynamically add or remove CSS classes based on component data.

Syntax:

<div [ngClass]="{'class-name': condition, 'another-class': anotherCondition}">
  Styled content
</div>

Example:

// app.component.ts
export class AppComponent {
  isActive: boolean = true;
  hasError: boolean = false;
}
<!-- app.component.html -->
<div [ngClass]="{'active': isActive, 'error': hasError}">
  This element may have active or error classes
</div>

In this example, the active class will be applied, and error will not, depending on the conditions.

Using [ngClass] with arrays

You can also bind [ngClass] to an array of class names:

classes = ['text-large', 'text-bold'];
<div [ngClass]="classes">
  This element has multiple classes applied
</div>

4. Combining Directives

Structural and attribute directives can be combined for dynamic and flexible templates.

Example:

export class AppComponent {
  items: string[] = ['Apple', 'Banana', 'Cherry'];
  isHighlighted: boolean = true;
}
<ul>
  <li *ngFor="let item of items" [ngClass]="{'highlight': isHighlighted}">
{{item}}
</li> </ul>

Here, each item is iterated using *ngFor, and the highlight class is applied dynamically.


5. Practical Examples and Use Cases

Conditional Rendering with *ngIf

<div *ngIf="user">
  Hello, {{user.name}}
</div>
<div *ngIf="!user">
  Guest, please log in
</div>

Looping Through Lists with *ngFor

<table>
  <tr *ngFor="let product of products">
&lt;td&gt;{{product.name}}&lt;/td&gt;
&lt;td&gt;{{product.price | currency}}&lt;/td&gt;
</tr> </table>

Dynamic Styling with [ngStyle]

<p [ngStyle]="{'background-color': isActive ? 'green' : 'grey'}">
  Status
</p>

Dynamic Classes with [ngClass]

<button [ngClass]="{'btn-primary': isPrimary, 'btn-secondary': !isPrimary}">
  Click Me
</button>

6. Performance Considerations

  • Avoid excessive use of *ngIf on large lists; prefer [hidden] for visibility toggling without DOM removal.
  • Use trackBy with *ngFor for lists with frequent updates to reduce DOM re-rendering.
<li *ngFor="let item of items; trackBy: trackByFn">{{item}}</li>
trackByFn(index: number, item: any) {
  return item.id;
}

7. Best Practices

  1. Use *ngIf only when you want elements to be removed from the DOM entirely.
  2. Use [ngClass] and [ngStyle] for dynamic styling rather than inline style attributes.
  3. Combine *ngFor with trackBy for large arrays.
  4. Keep template expressions simple; complex logic should go in the component.

8. Common Mistakes

  1. Forgetting the * in structural directives (ngIf vs *ngIf).
  2. Modifying DOM directly instead of using directives.
  3. Overusing [ngStyle] for static styles instead of CSS classes.
  4. Using *ngFor without trackBy on large datasets causing performance issues.

9. Conclusion

Angular directives provide developers with powerful tools to create dynamic, maintainable, and flexible web applications. Structural directives like *ngIf and *ngFor allow conditional rendering and looping, while attribute directives like [ngStyle] and [ngClass] make dynamic styling simple. Mastering these directives is essential for efficient Angular development and building responsive and user-friendly web apps.

Example Summary:

<div *ngIf="items.length">Items exist</div>
<ul>
  <li *ngFor="let item of items" [ngClass]="{'highlight': isHighlighted}">
{{item}}
</li> </ul> <div [ngStyle]="{'color': 'red', 'font-weight': 'bold'}"> Dynamic styling example </div>

By combining these directives, Angular developers can control both DOM structure and appearance, resulting in rich, interactive web applications.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *