post on basics of angular

Angular Series Part 3 - Basics of Angular

December 31, 2022

VinoPravin

Angular Series Part 3 - Basics of Angular

Post last updated: December 31, 2022

Basics of Angular

Components

image alt text

A component is a piece of code that represents a part of an Angular application. It consists of a class, a template, and metadata that describes how the component should be used. Components can communicate with each other and with the rest of the application through inputs, outputs, and services.

In general, a component is a class that controls a piece of the UI. It is made up of a template, which defines the UI, and a class, which defines the behavior of the component.

Here is a simple example of an Angular component:

import { Component } from '@angular/core'

@Component({
  selector: 'app-greeting',
  template: `<h1>Hello, world!</h1>`,
  styles: [
    `
      h1 {
        color: blue;
      }
    `
  ]
})
export class GreetingComponent {
  // component logic goes here
}

In this example, the component is defined using the @Component decorator, which is a function that takes a metadata object. The metadata object has several properties, including:

  • selector: The HTML tag that will be used to render the component in the template.

  • template: The HTML template for the component, which defines the UI.

  • styles: An array of CSS styles that will be applied to the component.

    The component also has an associated class, GreetingComponent, which defines the behavior of the component. You can add properties and methods to the class to define the component's behavior.

Templates

image alt text

A template is an HTML file that defines the UI of an Angular component. It can contain directives, which are special tags that add logic and behavior to the UI. Templates can also use interpolation, property binding, and event binding to bind data and events to the UI.

<div>
  <h1>{{ title }}</h1>
  <p>{{ description }}</p>
  <button (click)="doSomething()">Do Something</button>
</div>

In this example, the template includes an h1 element that displays a title, a p element that displays a description, and a button that calls a method when clicked.

The template can also include directives, which are special attributes that add logic and behavior to the template. For example, the *ngIf directive can be used to show or hide an element based on a condition:

<div *ngIf="showError">
  <p>There was an error!</p>
</div>

The template can also include interpolation expressions, which are used to display data from the component. In the example above, the {{ title }} and {{ description }} expressions are used to display the title and description properties of the component.

Directives

image alt text

In Angular, a directive is a special attribute that adds logic and behavior to a template. There are two types of directives: structural directives, which modify the DOM layout by adding, removing, or manipulating elements, and attribute directives, which modify the appearance or behavior of an element.

Here are some examples of common Angular directives:

  • *ngIf: A structural directive that adds or removes an element from the DOM based on a condition.

  • *ngFor: A structural directive that repeats an element for each item in an array.

  • [ngStyle]: An attribute directive that sets inline styles on an element based on an object or expression.

  • [ngClass]: An attribute directive that adds or removes CSS classes from an element based on an object or expression.

  • (click): An event binding directive that registers a DOM event listener and calls a component method when the event is triggered.

Here is an example of how you might use these directives in a template:

<div *ngIf="showError">
  <p>There was an error!</p>
</div>

<ul>
  <li *ngFor="let item of items">{{ item }}</li>
</ul>

<button [ngStyle]="{ 'font-size': fontSize + 'px' }">Click me</button>

<div [ngClass]="{ 'highlighted': isHighlighted }">
  This element will be highlighted if isHighlighted is true.
</div>

<button (click)="doSomething()">Click me</button>

Note: In general the Component we are using is also a directive.

Services

image alt text An Angular Service is a class that provides a specific functionality to the rest of the application. It is typically used to encapsulate logic that is not directly related to the UI and can be shared across multiple components. Here is an example of an Angular service:

import { Injectable } from '@angular/core'

@Injectable({
  providedIn: 'root'
})
export class GreetingService {
  greet(name: string) {
    return `Hello, ${name}!`
  }
}

In this example, the GreetingService class provides a greet() method that takes a name as an argument and returns a greeting. The @Injectable decorator is used to mark the class as an injectable service. To use the service in a component, you can inject it using the component's constructor:

import { Component } from '@angular/core';
import { GreetingService } from './greeting.service';

@Component({
  selector: 'app-greeting',
  template: `<h1>{{ greeting }}</h1>`,
})
export class GreetingComponent {
  greeting: string;

  constructor(private greetingService: GreetingService) {
    this.greeting = this.greetingService.greet('John');
  }
}

In this example, the GreetingService is injected into the GreetingComponent using the component's constructor. The component can then use the greet() method to get a greeting and display it in the template.

Applications of Angular Service

  • Data management: Services can be used to manage data that is shared across multiple components, such as retrieving data from a server or storing data in a database.

  • Business logic: Services can be used to encapsulate complex business logic, such as calculating discounts or determining eligibility for certain features.

  • External API integration: Services can be used to make HTTP requests to external APIs and handle the data that is returned.

  • Event management: Services can be used to publish and subscribe to events, allowing components to communicate with each other without being directly coupled.

  • Utility functions: Services can be used to provide utility functions, such as formatting dates or generating random numbers, that are needed by multiple components.

Component lifecycle

image alt text

The Angular component lifecycle is the series of events that takes place from the moment a component is created until the moment it is destroyed. It includes initialization, rendering, and destruction phases, and each phase has its own set of lifecycle hooks that you can use to perform specific tasks.

Here is a brief overview of the Angular component lifecycle:

  • Creation phase: This phase starts when a component is created and ends when the component is fully initialized. During this phase, the component's constructor is called and any dependencies are injected.

  • Rendering phase: This phase starts when the component is fully initialized and ends when the component is destroyed. During this phase, the component's template is rendered in the browser and the component's logic is executed.

  • Destruction phase: This phase starts when the component is destroyed and ends when the component is fully cleaned up. During this phase, the component's resources are released and any subscriptions are unsubscribed.

Here are some of the lifecycle hooks that you can use to perform tasks during each phase:

  • ngOnChanges: This hook is called when one or more data-bound input properties of a component or directive changes. It is a method that is invoked whenever the value of an input property changes or the component is initialized.

    Here is an example of how you can use ngOnChanges:

Imagine you have a component that displays a list of users. Each user has a name and an email address. The component has two input properties: users and filterTerm. The users property is an array of users and the filterTerm property is a string that is used to filter the list of users. Here is an example of using ngOnChanges in a component:

import { Component, Input, OnChanges } from '@angular/core'

@Component({
  selector: 'app-user-list',
  template: `
    <ul>
      <li *ngFor="let user of filteredUsers">
        {{ user.name }} ({{ user.email }})
      </li>
    </ul>
  `
})
export class UserListComponent implements OnChanges {
  @Input() users: User[]
  @Input() filterTerm: string

  filteredUsers: User[]

  ngOnChanges(changes: SimpleChanges) {
    // If the filterTerm or users input properties have changed,
    // update the filteredUsers array
    if (changes.filterTerm || changes.users) {
      this.filteredUsers = this.users.filter(
        (user) =>
          user.name.includes(this.filterTerm) ||
          user.email.includes(this.filterTerm)
      )
    }
  }
}

In this example, the UserListComponent component has two @Input properties: users and filterTerm. When the value of either of these properties changes, the ngOnChanges method is called.

The ngOnChanges method filters the users array based on the value of the filterTerm property and updates the filteredUsers array with the filtered list of users. The component's template then uses the filteredUsers array to display the list of users.

You can use the ngOnChanges method to perform any actions or calculations based on the changed input values. In this case, the ngOnChanges method is used to update the list of users displayed in the component based on the value of the filterTerm property.

  • ngOnInit: This hook is called after the component's or directive's data-bound properties have been initialized. You can use it to initialize the component's data or perform any other one-time setup tasks.It is a good place to put any initialization logic for your component or directive.

    Here is an example of using ngOnInit in a component:

import { Component, OnInit } from '@angular/core'

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.css']
})
export class ExampleComponent implements OnInit {
  // A property that will hold a value that we want to display in the template
  message: string

  constructor() {}

  ngOnInit() {
    // This is where you can put initialization logic for the component.
    this.message = 'Hello World!'
  }
}

In this example, the ExampleComponent implements the OnInit interface and the ngOnInit method is called when the component is initialized. Inside the ngOnInit method, we set the value of the message property to 'Hello World!'.

In the component's template, we can then display the value of the message property like this:

<p>{{ message }}</p>

When the component is rendered, the template will display the message 'Hello World!'.

It is important to note that ngOnInit is called after the component's or directive's data-bound properties have been initialized, but before the template has been rendered. This means that you cannot access the DOM in the ngOnInit method. If you need to access the DOM, you should use the ngAfterViewInit lifecycle hook instead.

  • ngDoCheck: This hook is called during every change detection run, immediately after ngOnChanges and ngOnInit. You can use it to detect and act upon changes that Angular can't or won't detect on its own. It is a good place to put logic that needs to be executed whenever the component's or directive's data-bound properties change, or whenever Angular detects a change in the component or directive.

Here is an example of using ngDoCheck in a component:

import { Component, OnInit, DoCheck } from '@angular/core';

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.css']
})
export class ExampleComponent implements OnInit, DoCheck {

  private _counter = 0;

  constructor() { }

  ngOnInit() {
  }

  ngDoCheck() {
    console.log(`Change detection cycle detected! Counter value: ${this._counter}`);
    this._counter++;
  }

}

In this example, the ngDoCheck hook logs a message to the console every time a change detection cycle is detected, and increments a counter variable by one. This can be useful for keeping track of how often change detection is occurring in the component.

It is important to note that ngDoCheck is called during every change detection run, which can be frequent and may have performance implications for your application. If you only need to perform a certain action when a specific property changes, you should use the ngOnChanges lifecycle hook instead.

  • ngAfterContentInit: This hook is called after the component's content (i.e., its projected content) has been initialized. You can use it to perform any additional setup tasks that depend on the component's content. It is a good place to put initialization logic that relies on the component's or directive's content.

    Content in this context refers to the projected content that has been added to the component or directive using a content projection (e.g. ng-content).

Here is an example of using ngAfterContentInit in a component:

import { Component, AfterContentInit } from '@angular/core'

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.css']
})
export class ExampleComponent implements AfterContentInit {
  // A property that will hold a reference to the projected content
  content: string

  constructor() {}

  ngAfterContentInit() {
    // This is where you can put initialization logic that relies on the component's content.
    this.content =
      'The projected content is: ' + this.projectedContent.innerHTML
  }
}

In this example, the ExampleComponent implements the AfterContentInit interface and the ngAfterContentInit method is called after the component's content has been initialized. Inside the ngAfterContentInit method, we can access the component's projected content using the projectedContent property. In this case, we are setting the value of the content property to a string that includes the projected content's inner HTML.

In the component's template, we can then display the value of the content property like this:

<p>{{ content }}</p>

It is important to note that ngAfterContentInit is called after the component's or directive's content has been initialized, but before the template has been rendered. This means that you cannot access the DOM in the ngAfterContentInit method. If you need to access the DOM, you should use the ngAfterViewInit lifecycle hook instead.

  • ngAfterContentChecked: This hook is called after the component's content (i.e., its projected content) has been checked for changes. You can use it to perform any additional tasks that depend on the component's content. It is a good place to put logic that needs to be executed whenever the component's or directive's content changes, or whenever Angular detects a change in the component or directive's content.

Content in this context refers to the projected content that has been added to the component or directive using a content projection (e.g. ng-content).

Here is an example of using ngAfterContentChecked in a component:

import { Component, AfterContentChecked } from '@angular/core'

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.css']
})
export class ExampleComponent implements AfterContentChecked {
  // A property that will hold a value that we want to display in the template
  message: string

  constructor() {}

  ngAfterContentChecked() {
    // This is where you can put logic that needs to be executed whenever the component's content changes.
    this.message =
      'The projected content is: ' + this.projectedContent.innerHTML
  }
}

In this example, the ExampleComponent implements the AfterContentChecked interface and the ngAfterContentChecked method is called after every check of the component's content. Inside the ngAfterContentChecked method, we can access the component's projected content using the projectedContent property. In this case, we are setting the value of the message property to a string that includes the projected content's inner HTML.

In the component's template, we can then display the value of the message property like this:

<p>{{ message }}</p>

It is important to note that ngAfterContentChecked is called after every check of the component's or directive's content, which can be frequent and may have performance implications for your application. If you only need to perform a certain action when a specific property changes, you should use the ngOnChanges lifecycle hook instead.

  • ngAfterViewInit: This hook is called after the component's view (i.e., its template) has been initialized. You can use it to perform any additional setup tasks that depend on the component's view. It is a good place to put initialization logic that relies on the component's or directive's views.

Views in this context refer to the component's template and any nested templates that have been added to the component or directive using a view projection (e.g. *ngIf or *ngFor).

Here is an example of using ngAfterViewInit in a component:

import { Component, AfterViewInit } from '@angular/core'

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.css']
})
export class ExampleComponent implements AfterViewInit {
  // A property that will hold a reference to an element in the template
  element: HTMLElement

  constructor() {}

  ngAfterViewInit() {
    // This is where you can put initialization logic that relies on the component's views.
    this.element = document.getElementById('some-element')
  }
}

In this example, the ExampleComponent implements the AfterViewInit interface and the ngAfterViewInit method is called after the component's views have been initialized. Inside the ngAfterViewInit method, we can access elements in the component's template using the document.getElementById method. In this case, we are setting the value of the element property to a reference to an element with the ID 'some-element'.

It is important to note that ngAfterViewInit is called after the component's or directive's views have been initialized, which means that the template has been rendered and the component's or directive's view-related child components have been initialized. This means that you can access the DOM in the ngAfterViewInit method.

  • ngAfterViewChecked: This hook is called after every check of a component's or directive's views and child views.It is a good place to put logic that needs to be executed whenever the component's or directive's views change, or whenever Angular detects a change in the component or directive's views.

Views in this context refer to the component's template and any nested templates that have been added to the component or directive using a view projection (e.g. *ngIf or *ngFor). Here is an example of using ngAfterViewChecked in a component:

import { Component, AfterViewChecked } from '@angular/core'

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.css']
})
export class ExampleComponent implements AfterViewChecked {
  // A property that will hold a value that we want to display in the template
  message: string

  constructor() {}

  ngAfterViewChecked() {
    // This is where you can put logic that needs to be executed whenever the component's views change.
    this.message =
      'The inner HTML of some-element is: ' + this.element.innerHTML
  }
}

In this example, the ExampleComponent implements the AfterViewChecked interface and the ngAfterViewChecked method is called after every check of the component's views. Inside the ngAfterViewChecked method, we can access elements in the component's template using the element property. In this case, we are setting the value of the message property to a string that includes the inner HTML of an element with the ID 'some-element'.

In the component's template, we can then display the value of the message property like this:

<p>{{ message }}</p>

It is important to note that ngAfterViewChecked is called after every check of the component's or directive's views, which can be frequent and may have performance implications for your application. If you only need to perform a certain action when a specific property changes, you should use the ngOnChanges lifecycle hook instead.

  • ngOnDestroy: This hook is called just before a component or directive is destroyed. It is a good place to put cleanup logic for your component or directive.

Here is an example of using ngOnDestroy in a component:

import { Component, OnDestroy } from '@angular/core'

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.css']
})
export class ExampleComponent implements OnDestroy {
  // A property that will hold a reference to a subscription
  subscription: any

  constructor() {}

  ngOnDestroy() {
    // This is where you can put cleanup logic for the component.
    this.subscription.unsubscribe()
  }
}

In this example, the ExampleComponent implements the OnDestroy interface and the ngOnDestroy method is called just before the component is destroyed. Inside the ngOnDestroy method, we can put any cleanup logic that we need. In this case, we are unsubscribing from a subscription to prevent memory leaks.

It is important to note that ngOnDestroy is called just before the component or directive is destroyed, which means that the component's or directive's views have already been removed from the DOM. This means that you cannot access the DOM in the ngOnDestroy method. If you need to access the DOM before the component or directive is destroyed, you should use the ngOnInit or ngAfterViewInit lifecycle hooks instead.

Author

VinoPravin

A Professional Full Stack Web Developer based in India. I help some of the fastest growing startups launch and grow their products.