Activity 11: Research Angular Directives


What are Angular Directives?

Angular directives are a core feature of Angular that allow you to extend HTML functionality by attaching behavior to elements in your Angular applications. They are used to create reusable and modular components, manipulate the DOM, and control the presentation and behavior of elements.

Directives in Angular fall into three main categories: Component Directives, Structural Directives, and Attribute Directives.

1. Component Directives

Definition: Component directives are directives with their own views (HTML templates) and are the most commonly used type in Angular applications. They create custom, reusable UI elements and encapsulate both the template and logic into a single unit.

Key Features:

  • They have their own HTML template and styles.

  • They define their own behavior through TypeScript classes.

  • They are used to create custom UI components.

Example:

// header.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-header',
  template: `<header><h1>My Application</h1></header>`,
  styles: [`header { background-color: #f3f3f3; padding: 10px; }`]
})
export class HeaderComponent { }
<!-- app.component.html -->
<app-header></app-header>

2. Structural Directives

Definition: Structural directives change the structure of the DOM by adding or removing elements. They are prefixed with an asterisk (*) in Angular templates.

Key Features:

  • They manipulate the DOM layout.

  • They are used for conditional rendering and looping.

Common Examples:

  • *ngIf: Conditionally includes a template based on the value of an expression.

  • *ngFor: Iterates over a collection and renders a template for each item.

Examples:

<!-- *ngIf Example -->
<div *ngIf="isLoggedIn">Welcome back!</div>
// app.component.ts
export class AppComponent {
  isLoggedIn = true;
}
<!-- *ngFor Example -->
<ul>
  <li *ngFor="let item of items">{{ item }}</li>
</ul>
// app.component.ts
export class AppComponent {
  items = ['Item 1', 'Item 2', 'Item 3'];
}

3. Attribute Directives

Definition: Attribute directives change the appearance or behavior of an element but do not affect the structure of the DOM. They are used to apply styles, classes, or other visual changes.

Key Features:

  • They modify the behavior or appearance of elements.

  • They are typically used for dynamic styling or class management.

Common Examples:

  • ngClass: Dynamically adds or removes CSS classes based on the value of an expression.

  • ngStyle: Dynamically sets the inline styles of an element.

Examples:

<!-- ngClass Example -->
<div [ngClass]="{'active': isActive, 'inactive': !isActive}">Dynamic Class Binding</div>
// app.component.ts
export class AppComponent {
  isActive = true;
}
<!-- ngStyle Example -->
<div [ngStyle]="{'color': color, 'font-size.px': fontSize}">Styled Text</div>
// app.component.ts
export class AppComponent {
  color = 'red';
  fontSize = 16;
}

Summary

  • Component Directives: Create reusable components with their own view and logic.

  • Structural Directives: Modify the DOM structure, including or excluding elements based on conditions (*ngIf) or looping over collections (*ngFor).

  • Attribute Directives: Change the appearance or behavior of elements without altering the DOM structure, such as dynamically applying classes (ngClass) or styles (ngStyle).

Understanding and using these directives effectively can greatly enhance your ability to build dynamic and responsive Angular applications.


Use Cases of Angular Directives

Angular directives play a crucial role in enhancing the behavior and structure of DOM elements in Angular applications. Each type of directive serves different purposes and is suited to specific scenarios. Here’s a look at practical use cases for each type of directive:

1. Component Directives

Use Cases:

  • Creating Reusable UI Components: Component directives are ideal for creating modular and reusable UI elements. For example, a <user-profile> component can encapsulate user information and presentation logic, making it reusable throughout the application.

  • Encapsulating Complex UI Logic: Components help in isolating complex UI logic and styles. For example, a <date-picker> component can handle all aspects of date selection, including display and interaction.

  • Building Layouts: Use component directives to create complex layouts. For example, a <dashboard> component might include various widgets and layout elements that can be reused across different parts of the application.

Example:

// user-profile.component.ts
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-user-profile',
  template: `
    <div>
      <h2>{{ name }}</h2>
      <p>Email: {{ email }}</p>
    </div>
  `,
  styles: [`div { border: 1px solid #ddd; padding: 10px; }`]
})
export class UserProfileComponent {
  @Input() name: string = '';
  @Input() email: string = '';
}
<!-- *ngIf Example: Displaying a loading message -->
<div *ngIf="isLoading">Loading...</div>

2. Structural Directives

Use Cases:

  • Conditional Rendering: Use *ngIf to conditionally include or exclude elements based on application state. For example, showing a loading spinner only when data is being fetched.

  • Looping Through Collections: Use *ngFor to iterate over a list and display elements. For instance, rendering a list of tasks in a to-do list application.

  • Creating Dynamic Content: Combine *ngFor with *ngIf to conditionally display elements within a loop. For example, showing a message if a list is empty.

Examples:

<!-- *ngIf Example: Displaying a loading message -->
<div *ngIf="isLoading">Loading...</div>
// app.component.ts
export class AppComponent {
  isLoading = true;
}
<!-- *ngFor Example: Rendering a list of tasks -->
<ul>
  <li *ngFor="let task of tasks">{{ task.name }}</li>
</ul>
// app.component.ts
export class AppComponent {
  tasks = [{ name: 'Task 1' }, { name: 'Task 2' }, { name: 'Task 3' }];
}
<!-- Combined *ngIf and *ngFor Example: Showing a message if the list is empty -->
<ul *ngIf="tasks.length > 0; else noTasks">
  <li *ngFor="let task of tasks">{{ task.name }}</li>
</ul>
<ng-template #noTasks>No tasks available.</ng-template>

3. Attribute Directives

Use Cases:

  • Dynamic Styling: Use ngClass and ngStyle to apply or modify styles dynamically based on component state. For instance, changing the background color of a button when it is clicked.

  • Adding or Removing CSS Classes: Use ngClass to toggle classes based on user interactions or application state. For example, adding a class to highlight a selected item.

  • Conditional Styling: Use ngStyle to change inline styles dynamically. For example, changing the font size of text based on user input.

Examples:

<!-- ngClass Example: Toggling classes based on a condition -->
<button [ngClass]="{'active': isActive, 'inactive': !isActive}">Click Me</button>
// app.component.ts
export class AppComponent {
  isActive = true;
}
<!-- ngStyle Example: Changing text color and font size -->
<p [ngStyle]="{'color': textColor, 'font-size.px': fontSize}">Dynamic Styling</p>
// app.component.ts
export class AppComponent {
  textColor = 'blue';
  fontSize = 18;
}

Summary

  • Component Directives: Ideal for creating reusable, self-contained UI elements and encapsulating complex UI logic.

  • Structural Directives: Useful for altering the DOM structure, including or excluding elements based on conditions, and iterating over collections.

  • Attribute Directives: Perfect for dynamically modifying the appearance and behavior of elements without changing the DOM structure.

These directives enhance Angular applications by providing powerful tools to manage and manipulate the DOM, leading to more dynamic, modular, and maintainable code.


Here are some well-explained Angular code snippets demonstrating various uses of Angular directives. These examples include conditional rendering, looping, and dynamic class binding.

1. Conditional Rendering with *ngIf

Use Case: Displaying content based on a condition.

Code Snippet:

<!-- app.component.html -->
<div *ngIf="isLoggedIn; else loginPrompt">
  <h1>Welcome back, user!</h1>
  <button (click)="logout()">Logout</button>
</div>
<ng-template #loginPrompt>
  <h1>Please log in</h1>
  <button (click)="login()">Login</button>
</ng-template>
// app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  isLoggedIn = false;

  login() {
    this.isLoggedIn = true;
  }

  logout() {
    this.isLoggedIn = false;
  }
}

Explanation:

  • *ngIf conditionally includes the <div> element if isLoggedIn is true.

  • ng-template is used for the content that should be displayed when isLoggedIn is false.


2. Looping Through a List with *ngFor

Use Case: Displaying a list of items.

Code Snippet:

<!-- app.component.html -->
<ul>
  <li *ngFor="let item of items">{{ item.name }} - {{ item.price | currency }}</li>
</ul>
// app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  items = [
    { name: 'Item 1', price: 29.99 },
    { name: 'Item 2', price: 19.99 },
    { name: 'Item 3', price: 9.99 }
  ];
}

Explanation:

  • *ngFor iterates over the items array and renders each item in the list.

  • The currency pipe formats the price value as currency.


3. Dynamic Class Binding with ngClass

Use Case: Applying CSS classes based on component state.

Code Snippet:

<!-- app.component.html -->
<button [ngClass]="{'btn-primary': isPrimary, 'btn-secondary': !isPrimary}" (click)="toggleClass()">
  Click Me
</button>
// app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  isPrimary = true;

  toggleClass() {
    this.isPrimary = !this.isPrimary;
  }
}

Explanation:

  • ngClass dynamically adds the btn-primary or btn-secondary class based on the isPrimary property.

  • toggleClass() method switches between the two states when the button is clicked.


4. Dynamic Style Binding with ngStyle

Use Case: Applying inline styles dynamically.

Code Snippet:

<!-- app.component.html -->
<p [ngStyle]="{'color': textColor, 'font-size.px': fontSize}">
  This text has dynamic styles.
</p>
<input type="color" [(ngModel)]="textColor" placeholder="Choose color">
<input type="number" [(ngModel)]="fontSize" placeholder="Font size">
// app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  textColor = 'black';
  fontSize = 16;
}

Explanation:

  • ngStyle applies the color and font-size styles dynamically based on component properties.

  • Two inputs allow users to change the text color and font size.


5. Using ngIf with ngFor

Use Case: Displaying a message if the list is empty.

Code Snippet:

<!-- app.component.html -->
<ul *ngIf="items.length > 0; else noItems">
  <li *ngFor="let item of items">{{ item }}</li>
</ul>
<ng-template #noItems>
  <p>No items to display.</p>
</ng-template>
// app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  items: string[] = []; // This array can be populated with items or left empty to test the noItems template
}

Explanation:

  • *ngIf checks if items array has elements and uses ng-template to show a message when the list is empty.

  • *ngFor iterates over items to display each element.

Summary

These code snippets illustrate how Angular directives can be effectively used to enhance the behavior and structure of your application. They demonstrate:

  • Conditional rendering with *ngIf

  • Looping through data with *ngFor

  • Dynamic class and style binding with ngClass and ngStyle


Reference Link: Directives in Angular

1
Subscribe to my newsletter

Read articles from Danilo Buenafe Jr directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Danilo Buenafe Jr
Danilo Buenafe Jr