28th May 2024

Understanding Angular: Lifecycle, Decorators, and Inbuilt Directives

Angular-Lifecycle-Directive-Decorator-Blog-VS-Online-img

Introduction

Angular is a powerful and widely-used framework for building dynamic web applications. Understanding the core concepts of Angular, such as the component lifecycle, decorators, and inbuilt directives, is essential for any developer aiming to create robust and efficient applications. In this comprehensive guide, we will explore the Angular lifecycle, delve into the role of decorators, and discuss the various inbuilt directives that simplify the development process. Whether you're a beginner or an experienced developer, this guide will enhance your understanding and application of these fundamental Angular features.

What are angular lifecycle hooks?

Angular lifecycle hooks are a series of callback methods that provide developers with opportunities to tap into key moments in the lifecycle of a component or directive. These hooks enable developers to execute custom logic at different stages of a component’s existence, from its creation to its destruction. Understanding and effectively using these hooks is crucial for managing component behavior and ensuring that resources are properly allocated and cleaned up.

Here’s a brief overview of the main Angular lifecycle hooks:

ngOnChanges:
  • Purpose: Called before ngOnInit and whenever one or more data-bound input properties change.
  • Use Case: Respond to changes to input properties.
ngOnInit:
  • Purpose: Called once upon component initialization after the first ngOnChanges.
  • Use Case: Perform any necessary setup or initializations.
ngDoCheck:
  • Purpose: Invoked with every change detection run, allowing custom change detection logic.
  • Use Case: Detect and act upon changes that Angular can't or won't detect.
ngAfterContentInit:
  • Purpose: Called after Angular projects external content into the component’s view.
  • Use Case: Work with projected content (content children).
ngAfterContentChecked:
  • Purpose: Invoked after every change detection cycle for projected content.
  • Use Case: Respond to changes in the projected content.
ngAfterViewInit:
  • Purpose: Called after Angular initializes the component's views and child views.
  • Use Case: Perform any additional initialization that requires access to component’s view.
ngAfterViewChecked:
  • Purpose: Invoked after every change detection cycle for the component's views and child views.
  • Use Case: Respond to changes in the component’s view and its child views.
ngOnDestroy:
  • Purpose: Called just before Angular destroys the component.
  • Use Case: Clean up resources, unsubscribe from observables, and detach event handlers to avoid memory leaks.

Each lifecycle hook offers a unique opportunity to perform actions at specific points during the component’s lifecycle. By leveraging these hooks, developers can optimize application performance, manage resources efficiently, and ensure a smooth user experience.

What are Decorators in Angular?

Decorators in Angular are a special kind of declaration that can be attached to classes, methods, properties, and parameters to add metadata and modify their behavior. They are a core part of Angular’s architecture, enabling the framework to understand how different pieces of code should interact and behave.

Decorators are functions that take the form @Decorator and can be used to enhance and configure Angular components, services, directives, and other entities. Here are some of the key decorators in Angular:

@Component:
  • Purpose: Declares a class as an Angular component and provides metadata about the component.
  • Metadata: Includes selector, template, styles, and more.
  • Example:
                                
                                    
  @Component({
    selector: 'app-example',
    templateUrl: './example.component.html',
    styleUrls: ['./example.component.css']
  })
  export class ExampleComponent {
    // Component logic
  }
 
                                
                            
@Directive:
  • Purpose: Declares a class as an Angular directive and provides metadata about the directive.
  • Metadata: Includes selector and other directive-specific properties.
  • Example:
                                
                                    
  @Directive({
    selector: '[appHighlight]'
  })
  export class HighlightDirective {
    // Directive logic
  }
 
                                
                            
@Injectable:
  • Purpose: Marks a class as available to be injected as a dependency.
  • Metadata: Configures the service and its dependencies.
  • Example:
                                
                                    
  @Injectable({
    providedIn: 'root'
  })
  export class DataService {
    // Service logic
  }
 
                                
                            
@Input:
  • Purpose: Marks a property as an input property, allowing data to be passed to the component from its parent.
  • Metadata: Specifies the binding for the property.
  • Example:
                                
                                    
  export class ChildComponent {
    @Input() data: string;
    // Component logic
  }

                                
                            
@Output:
  • Purpose: Marks a property as an output property, allowing the component to emit events to its parent.
  • Metadata: Specifies the event binding for the property.
  • Example:
                                
                                    
  export class ChildComponent {
    @Output() dataChange = new EventEmitter<string>();
    // Component logic
  }

                                
                            
@HostListener:
  • Purpose: Declares a method as an event handler for a host element’s event.
  • Metadata: Specifies the event and optionally the event arguments.
  • Example:
                                
                                    
  export class ExampleDirective {
    @HostListener('click', ['$event'])
    onClick(event: Event) {
      // Handle click event
    }
  }

                                
                            
@HostBinding:
  • Purpose: Binds a property of the directive/component to a host element property.
  • Metadata: Specifies the host property to bind to.
  • Example:
                                
                                    
  export class ExampleDirective {
    @HostBinding('class.active') isActive = true;
  }

                                
                            

Decorators provide a way to add metadata to classes and their members, making it possible for Angular to understand how to process and instantiate them. They are a fundamental part of Angular's dependency injection and component-based architecture, enabling modular and reusable code.

What are Directives in Angular?

Directives in Angular are classes that add behavior to elements in your Angular applications. They are a core feature of Angular and allow developers to manipulate the DOM, control the behavior of elements, and create reusable code. There are three main types of directives:

Component Directives:
  • Purpose: These are the most common directives. They define a template, styles, and logic for a piece of the user interface. Component directives are the building blocks of Angular applications.
  • Example:
                                
                                    
  @Component({
    selector: 'app-example',
    templateUrl: './example.component.html',
    styleUrls: ['./example.component.css']
  })
  export class ExampleComponent {
    // Component logic
  }

                                
                            
Attribute Directives:
  • Purpose: These directives change the appearance or behavior of an existing element, component, or another directive. They can add or remove classes, styles, and other attributes.
  • Example:
                                
                                    
  @Directive({
    selector: '[appHighlight]'
  })
  export class HighlightDirective {
    @HostListener('mouseenter') onMouseEnter() {
      this.highlight('yellow');
    }

    @HostListener('mouseleave') onMouseLeave() {
      this.highlight(null);
    }

    private highlight(color: string) {
      this.el.nativeElement.style.backgroundColor = color;
    }

    constructor(private el: ElementRef) {}
  }

                                
                            
Structural Directives:
  • Purpose: These directives change the DOM layout by adding or removing elements. They are usually denoted with an asterisk (*) before their name.
  • Example:
                                
                                    
  @Directive({
    selector: '[appUnless]'
  })
  export class UnlessDirective {
    @Input() set appUnless(condition: boolean) {
      if (!condition) {
        this.viewContainer.createEmbeddedView(this.templateRef);
      } else {
        this.viewContainer.clear();
      }
    }

    constructor(private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef) {}
  }

                                
                            

Inbuilt Directives in Angular

Angular comes with a set of inbuilt directives that help with common tasks. These inbuilt directives can be categorized as either structural or attribute directives:

Structural Directives:

1.ngIf:
  • Purpose: Conditionally includes or excludes an element in the DOM.
  • Example:
                                
                                    
  <div *ngIf="condition">
    Content to display if condition is true
  </div>

                                
                            
2.ngFor:
  • Purpose: Iterates over a collection and creates a new instance of the element for each item.
  • Example:
                                
                                    
  <div *ngFor="let item of items">
    {{ item }}
  </div>

                                
                            
3.ngSwitch:
  • Purpose: Conditionally includes or excludes elements based on matching expressions.
  • Example:
                                
                                    
<div [ngSwitch]="condition">
  <div *ngSwitchCase="'case1'">Case 1 content</div>
  <div *ngSwitchCase="'case2'">Case 2 content</div>
  <div *ngSwitchDefault>Default content</div>
</div>

                                
                            

Attribute Directives:

1.ngClass:
  • Purpose: Adds or removes CSS classes dynamically.
  • Example:
                                
                                    
  <div [ngClass]="{'active': isActive, 'disabled': isDisabled}">
    Content
  </div>

                                
                            
2.ngStyle:
  • Purpose: Adds or removes CSS styles dynamically.
  • Example:
                                
                                    
  <div [ngStyle]="{'color': textColor, 'font-size': fontSize}">
    Styled Content
  </div>

                                
                            
3.ngModel
  • Purpose: Binds the value of an input, select, or textarea element to a variable.
  • Example:
                                
                                    
  <input [(ngModel)]="username" placeholder="Enter your username">

                                
                            

These inbuilt directives provide powerful tools for developers to control the structure and behavior of their applications without writing a lot of custom code. By leveraging Angular's directives, you can create dynamic and responsive applications efficiently.

Conclusion

Understanding Angular's lifecycle hooks, decorators, and inbuilt directives is essential for any developer looking to master this powerful framework. By harnessing lifecycle hooks, you can control and optimize the behavior of your components at various stages of their existence. Decorators provide a declarative way to add metadata and enhance the functionality of your classes, making your code more modular and maintainable. Inbuilt directives offer convenient tools for manipulating the DOM, enabling you to create dynamic and responsive user interfaces with minimal effort.

By thoroughly grasping these core concepts, you can build robust, efficient, and scalable Angular applications. Whether you're managing component initialization and cleanup, enhancing classes with decorators, or leveraging inbuilt directives to control the DOM, these features are fundamental to effective Angular development. Keep exploring and experimenting with these tools to continuously improve your skills and deliver high-quality web applications.

With a solid foundation in Angular's lifecycle, decorators, and directives, you're well-equipped to tackle complex projects and advance your development expertise. Happy coding!

Let's develop your ideas into reality