Full Trust European Hosting

BLOG about Full Trust Hosting and Its Technology - Dedicated to European Windows Hosting Customer

AngularJS Hosting Europe - HostForLIFE :: Understanding Angular Testing: Component-Level, Unit, Integration, and E2E Techniques

clock November 6, 2025 06:05 by author Peter

One of the most crucial yet sometimes overlooked—aspects of front-end development is testing. Testing guarantees code quality, bug prevention, and trust in each release of large enterprise Angular apps. With examples, best practices, and practical insights, we will examine all forms of testing in Angular, including Unit, Integration, End-to-End (E2E), and Component-level testing.

1. Why Testing Matters in Angular
Modern Angular applications are built with multiple services, components, and modules.
Without automated tests, even a small change can unintentionally break features elsewhere.

Key reasons to write tests:

  • Detect bugs early before production
  • Improve refactoring confidence
  • Ensure consistent functionality
  • Reduce manual QA time

Angular provides an excellent testing ecosystem out of the box with Jasmine, Karma, and Protractor (or Cypress for modern E2E).

2. Types of Testing in Angular

 

 

Test TypePurposeTools Commonly UsedExample Scope

Unit Test

Test smallest code units (functions, services, components)

Jasmine + Karma

Single function or service

Integration Test

Test how modules/components work together

Jasmine + TestBed

Component with service

E2E Test

Test the entire application flow

Cypress / Playwright / Protractor

From login to checkout

Component Test

Focus only on UI component behavior and rendering

TestBed / Jest / Cypress Component Testing

Angular Material Table, Forms, Buttons

3. Unit Testing in Angular

Unit tests check if individual functions or components behave as expected.
Angular uses Jasmine for writing tests and Karma as the test runner.

Example: Testing a Service
math.service.ts

export class MathService {
  add(a: number, b: number): number {
    return a + b;
  }
}


math.service.spec.ts
import { MathService } from './math.service';

describe('MathService', () => {
  let service: MathService;

  beforeEach(() => {
    service = new MathService();
  });

  it('should add two numbers correctly', () => {
    expect(service.add(2, 3)).toBe(5);
  });
});


Best Practices

  • Test each method independently
  • Avoid API or database calls
  • Use mocks or spies for dependencies

4. Component-Level Testing
Component testing focuses on how the UI behaves — inputs, outputs, events, and template rendering.
Angular’s TestBed provides a test environment for creating and interacting with components.
Example: Testing a Simple Component

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

@Component({
  selector: 'app-hello',
  template: `<h3>Hello {{ name }}!</h3>`
})
export class HelloComponent {
  @Input() name = '';
}

hello.component.spec.ts
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HelloComponent } from './hello.component';

describe('HelloComponent', () => {
  let component: HelloComponent;
  let fixture: ComponentFixture<HelloComponent>;

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [HelloComponent]
    });
    fixture = TestBed.createComponent(HelloComponent);
    component = fixture.componentInstance;
  });

  it('should display the input name', () => {
    component.name = 'Rajesh';
    fixture.detectChanges();
    const compiled = fixture.nativeElement;
    expect(compiled.querySelector('h3').textContent).toContain('Rajesh');
  });
});


Best Practices
Use fixture.detectChanges() to apply bindings
Query DOM using fixture.nativeElement

Keep test scenarios small and focused

5. Integration Testing
Integration tests ensure multiple parts of your app work together correctly — for example, a component using a service or API.
Example: Component + Service Integration

user.service.ts
@Injectable({ providedIn: 'root' })
export class UserService {
  getUser() {
    return of({ name: 'Rajesh', role: 'Admin' });
  }
}

profile.component.ts
@Component({
  selector: 'app-profile',
  template: `<p>{{ user?.name }} - {{ user?.role }}</p>`
})
export class ProfileComponent implements OnInit {
  user: any;
  constructor(private userService: UserService) {}
  ngOnInit() {
    this.userService.getUser().subscribe(u => this.user = u);
  }
}

profile.component.spec.ts
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ProfileComponent } from './profile.component';
import { UserService } from './user.service';
import { of } from 'rxjs';

describe('ProfileComponent (Integration)', () => {
  let fixture: ComponentFixture<ProfileComponent>;
  let mockService = { getUser: () => of({ name: 'Rajesh', role: 'Admin' }) };

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [ProfileComponent],
      providers: [{ provide: UserService, useValue: mockService }]
    });
    fixture = TestBed.createComponent(ProfileComponent);
  });

  it('should display user details from service', () => {
    fixture.detectChanges();
    const element = fixture.nativeElement;
    expect(element.textContent).toContain('Rajesh');
  });
});


Best Practices

  • Mock dependencies (like services or APIs)
  • Focus on communication between layers
  • Keep external systems out of the test

6. End-to-End (E2E) Testing
E2E tests simulate real user actions on your application — from login to logout — ensuring that the whole flow works.

Modern Angular apps now prefer Cypress or Playwright over Protractor.

Example: Cypress Test
cypress/e2e/login.cy.ts

describe('Login Page', () => {
  it('should login successfully with valid credentials', () => {
    cy.visit('/login');
    cy.get('input[name="email"]').type('[email protected]');
    cy.get('input[name="password"]').type('12345');
    cy.get('button[type="submit"]').click();
    cy.url().should('include', '/dashboard');
  });
});


Best Practices
Use realistic test data
Separate test environment from production
Avoid flakiness by waiting for API calls using cy.intercept()

7. Choosing the Right Testing Strategy

Project TypeRecommended Focus
Small App / POC Unit & Component Tests
Enterprise App Unit + Integration + E2E
UI Heavy App Component + E2E
API Driven App Integration + E2E

In most projects:

  • 70% of tests are Unit

  • 20% Integration

  • 10% E2E

This gives a good balance between speed and confidence.

8. Testing Tools Summary

ToolPurposeDescription
Jasmine Unit/Integration Test framework for assertions
Karma Test Runner Executes tests in browser
TestBed Angular Testing Utility For setting up components
Cypress / Playwright E2E Testing Real browser automation
Jest Fast Unit Testing Alternative to Jasmine for faster runs

9. Continuous Testing in CI/CD

Integrate your Angular tests into your CI/CD pipeline (Jenkins, GitHub Actions, or Azure DevOps).

Example command in package.json:
"scripts": {"test": "ng test --watch=false --browsers=ChromeHeadless","e2e": "cypress run"}

This ensures that every commit runs all tests automatically.

10. Conclusion
Testing in Angular is not just a best practice it’s a developer’s safety net. Whether you’re building small reusable components or large enterprise apps, combining Unit, Integration, Component, and E2E tests ensures:

  • Better reliability
  • Fewer regressions
  • Confident deployments

Start small, automate everything, and make testing a habit, not an afterthought.



AngularJS Hosting Europe - HostForLIFE :: Various Methods for Retrieving and Redirecting ID Parameters in Angular

clock October 28, 2025 10:20 by author Peter

Angular is a robust front-end framework that offers multiple methods for passing data, including ID parameters, and navigating between components. Effective routing management requires knowing how to collect parameters and reroute users, whether you're developing a sophisticated enterprise application or a single-page application (SPA).

1. Using the RouterLink Directive for Easy Navigation
The simplest method for navigating between Angular components is to use the RouterLink directive. It aids in creating URLs with dynamic parameters and is directly utilized in templates.

<a [routerLink]="['/employee', employee.id]">View Details</a>

the employee.id is appended to the /employee route, creating a dynamic URL like /employee/123. This is a convenient way to navigate when the route parameters are known within the template.

2. Programmatic Navigation with the Router

For more complex scenarios, such as navigation that depends on some business logic or conditional operations, Angular’s Router service can be used for programmatic navigation.
import { Router } from '@angular/router';
constructor(private router: Router) {}
viewEmployeeDetails(employeeId: number) {
  this.router.navigate(['/employee', employeeId]);
}


navigate() method takes an array where the first element is the route path, and the subsequent elements are the route parameters.

3. Retrieving Parameters Using ActivatedRoute

Once you’ve navigated to a route that includes parameters, you'll often need to retrieve those parameters in the component. Angular provides the ActivatedRoute service for this purpose.

import { ActivatedRoute } from '@angular/router';
constructor(private route: ActivatedRoute) {}
ngOnInit(): void {
  const employeeId = this.route.snapshot.paramMap.get('id');
  console.log('Employee ID:', employeeId);
}


snapshot.paramMap.get('id') retrieves the id parameter from the route. This is a synchronous method, meaning it grabs the parameter value only at the moment of the component's creation.

4. Using Observables for Dynamic Parameter Retrieval

While snapshot is useful for simple use cases, Angular applications often require handling route changes dynamically without destroying and recreating components. This is where paramMap as an Observable comes into play.
import { ActivatedRoute } from '@angular/router';
constructor(private route: ActivatedRoute) {}
ngOnInit(): void {
  this.route.paramMap.subscribe(params => {
    const employeeId = params.get('id');
    console.log('Employee ID:', employeeId);
  });
}


paramMap.subscribe() ensures that every time the id parameter changes, the new value is logged or processed accordingly. This is ideal for components that need to respond to route changes dynamically.

5. Combining Query Parameters with Navigation
Sometimes, you may want to navigate to a route and include additional information via query parameters. Angular’s Router service allows combining both route parameters and query parameters.

this.router.navigate(['/employee', employeeId], { queryParams: { ref: 'dashboard' } });

navigation directs to /employee/123?ref=dashboard, where 123 is the route parameter, and ref=dashboard is a query parameter.
If you want to retrieve the query parameters in the component

this.route.queryParams.subscribe(params => {
  const ref = params['ref'];
  console.log('Referred from:', ref);
});

6. Redirection after Form Submission
Another common use case is redirecting the user after a form submission or some action completion.
onSubmit() {
  // Assuming form submission is successful
  this.router.navigate(['/employee', newEmployeeId]);
}

7. Handling Complex Redirections with Guards
Angular also supports complex redirection scenarios using route guards. Guards can intercept navigation and redirect users based on certain conditions.
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {
  constructor(private router: Router) {}
  canActivate(): boolean {
    if (isLoggedIn()) {
      return true;
    } else {
      this.router.navigate(['/login']);
      return false;
    }
  }
}


if the is logged in () function returns false, the user is redirected to the /login route, preventing unauthorized access.

Conclusion

Navigating between routes and handling parameters in Angular is a fundamental aspect of building dynamic and user-friendly applications. Whether you use the simple RouterLink, programmatic navigation, or complex redirection logic, Angular provides the tools to handle a wide range of routing scenarios efficiently. Happy Coding!



AngularJS Hosting Europe - HostForLIFE :: Using Pipes to Create Clear and Effective Angular Applications

clock October 23, 2025 10:12 by author Peter

The use of "pipes" is one of Angular's most potent tools for formatting and changing data inside templates. Developers can apply transformations like formatting dates, changing text cases, or even filtering data in an efficient and reusable way by using pipes, which offer a declarative mechanism to handle data before it is shown to the user. Writing clean, manageable, and modular code for Angular applications requires an understanding of pipes. The main distinctions between pipes and functions will be discussed in this post, along with how to use built-in pipes and make your own custom pipes to increase Angular's functionality. You will have a firm grasp on how to integrate pipes into your Angular projects to improve user experience and expedite data presentation by the end of this tutorial.

What is an Angular Pipe?
In Angular, a pipe is a way to transform data before it is displayed in the user interface. Pipes can be used in templates to modify or format data without having to alter the original data. Pipes are an Angular concept, not a TypeScript (TS) feature. They are a core part of Angular’s template syntax and are used to transform data in the view (template) layer of Angular applications.

Key Points about Pipes in Angular

Angular-Specific: Pipes are a built-in feature of the Angular framework designed to be used in Angular templates. They are not a native feature of JavaScript or TypeScript.
Purpose: Their primary function is to transform data in the template before it is displayed to the user. This transformation can include formatting dates, numbers, currencies, filtering arrays, or performing more complex data transformations.

Declarative Transformation: Pipes enable declarative transformation of data within the template, meaning that the logic for transforming data is cleanly abstracted away from the component’s TypeScript code.

You may be wondering why we should use Pipes when we can use functions.

Criteria Pipe Function
Purpose Data transformation in the template Business logic and calculations
Use case Formatting, filtering, sorting, etc. Complex or multi-step calculations
Performance Pure pipes are efficient for transforming data only when needed Functions can be less performant when used in templates (requires manual calls)
Reusability Highly reusable across templates Functions are reusable within the component or service
Asynchronous Handling Handles observables and promises with AsyncPipe Requires manual subscription logic or use of 'async' in templates
Complexity Best for simple, declarative transformations Best for complex or dynamic logic
When to use When transforming data for display in the template When performing business logic or side effects that don't belong in the template

Types of Pipes

There are two types of Pipes.
Pure Pipe (Default): A pure pipe will only re-run when its input value changes.
    @Pipe({
      name: 'pureExample',
      pure: true // This is the default value, so you can omit this
    })
    export class PureExamplePipe implements PipeTransform {
      transform(value: any): any {
        console.log('Pure pipe executed');
        return value;
      }
    }


Impure Pipe: An impure pipe will re-run whenever Angular detects a change in the component’s state, even if the input value hasn’t changed.
@Pipe({
  name: 'impureExample',
  pure: false // Set to false to make it impure
})
export class ImpureExamplePipe implements PipeTransform {
  transform(value: any): any {
    console.log('Impure pipe executed');
    return value;
  }
}

In Angular, you can use in-built pipes or create your own.

In-built pipes
Angular provides some basic pipes that can be used.

It comes from the '@angular/common' package.

Some popular ones that can be helpful are:
CurrencyPipe, DatePipe, DecimalPipe, LowerCasePipe, UpperCasePipe and TitleCasePipe

How to use an in-built pipe?
In your ts file, define your variable. In our example, we will use the variable title.
title = 'app works!';

In your html, you can use the pipe as follows:
<h1> {{title | uppercase}} </h1>

The result is how the string title is displayed:

Chaining in-built pipes
Create your variable in the ts file.
amount = 123456.123456

In your html file, you can do the following.
<p>{{ amount | currency:'USD' | slice:0:10 }}</p>

The result is as per below:

Note. The currency ‘USD’ is added in front because of the currency pipe, and only 10 characters are displayed because of the slide pipe.

Custom pipes

    Run the command below to create a pipe file:
    ng generate pipe <<pipe-name>>.

For example: ng generate pipe my-custom-pipe. Once executed, the two files below will be created.

Open the file ‘my-custom-pipe.pipe.ts. You will see the following boilerplate code provided:
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'myCustomPipe'
})
export class MyCustomPipePipe implements PipeTransform {
  transform(value: any, args?: any): any {
    return null;
  }
}


After the default class, you can create the function for your new pipe. In our case, we will create a pipe that will replace spaces in a hyphen. It is important to add the decorator ‘@Pipe’ before the class so that Angular knows what follows will be a pipe. Also, pass the name of the pipe as a parameter in the ‘@Pipe’ decorator. Also, when creating the class, implement ‘PipeTransform’. The resulting class will be as follows: 

@Pipe({name: 'removeWhiteSpace'})
export class RemoveWhiteSpacePipe implements PipeTransform {
  transform(value: string): string {
    return value.replace(/\s+/g, '-');
  }
}

The resulting class will be as follows (the full code):
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'myCustomPipe'
})
export class MyCustomPipePipe implements PipeTransform {


  transform(value: any, args?: any): any {
    return null;
  }
}


@Pipe({name: 'removeWhiteSpace'})
export class RemoveWhiteSpacePipe implements PipeTransform {
  transform(value: string): string {
    return value.replace(/\s+/g, '-');
  }
}

In the ts file of your component, create the variable that will hold the value that will be transformed
textWithSpaces = 'This is a text with a lot of spaces that will be transformed';

In the html file of your component, do the following:
<p>{{ textWithSpaces | removeWhiteSpace }}</p>

    The result is the following:

Conclusion
Angular pipes are a powerful and efficient way to transform and format data in your application’s templates. By using built-in pipes, you can easily manipulate data types such as strings, dates, and numbers without having to write repetitive logic in your components. Custom pipes offer even more flexibility, allowing you to create reusable, maintainable, and modular transformation logic tailored to your specific needs.

Understanding the distinction between pipes and functions is key to leveraging their full potential. While functions provide a direct way to execute code, pipes offer a declarative approach to handle transformations directly within templates, improving readability and performance.


Building dynamic and user-friendly applications greatly benefits from the ease with which data can be manipulated in the view layer, whether you're using Angular's built-in pipes or making your own. Gaining proficiency with Angular Pipes will help you write code that is clear, succinct, and compliant with best practices, which will eventually result in applications that are easier to maintain and scale.

Now that you know how to utilize and design pipes, you can add strong data transformations to your Angular applications, which will improve the efficiency and enjoyment of your development process.



AngularJS Hosting Europe - HostForLIFE :: How to Use Reactive Forms to Manage Form Validation in Angular?

clock October 8, 2025 08:52 by author Peter

Create a Basic Reactive Form
Start by importing ReactiveFormsModule in your Angular module:

// app.module.ts
import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
  imports: [ReactiveFormsModule, /* other imports */],
})
export class AppModule {}


Then, build a form in your component using FormBuilder:
// user-form.component.ts
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

@Component({ selector: 'app-user-form', templateUrl: './user-form.component.html' })
export class UserFormComponent {
  userForm: FormGroup;

  constructor(private fb: FormBuilder) {
    this.userForm = this.fb.group({
      name: ['', [Validators.required, Validators.minLength(2)]],
      email: ['', [Validators.required, Validators.email]],
      password: ['', [Validators.required, Validators.minLength(6)]],
    });
  }
}


In the template, bind the form and controls:
<!-- user-form.component.html -->
<form [formGroup]="userForm" (ngSubmit)="onSubmit()">
  <label>
    Name
    <input formControlName="name" />
  </label>
  <div *ngIf="userForm.get('name')?.touched && userForm.get('name')?.invalid">
    <small *ngIf="userForm.get('name')?.errors?.required">Name is required.</small>
    <small *ngIf="userForm.get('name')?.errors?.minlength">Name must be at least 2 characters.</small>
  </div>

  <label>
    Email
    <input formControlName="email" />
  </label>
  <div *ngIf="userForm.get('email')?.touched && userForm.get('email')?.invalid">
    <small *ngIf="userForm.get('email')?.errors?.required">Email is required.</small>
    <small *ngIf="userForm.get('email')?.errors?.email">Enter a valid email.</small>
  </div>

  <button type="submit" [disabled]="userForm.invalid">Submit</button>
</form>


Built-in Validators
Angular provides several built-in validators:

  • Validators.required — field must have a value.
  • Validators.email — value must be a valid email.
  • Validators.min / Validators.max — numeric limits.
  • Validators.minLength / Validators.maxLength — string length limits.
  • Validators.pattern — regex-based validation.

You can combine validators in an array for a control, as shown in the example above.

Custom Synchronous Validators

For rules that don’t exist out of the box (e.g., username format), write a custom validator function that returns either null (valid) or an error object:
import { AbstractControl, ValidationErrors } from '@angular/forms';

export function usernameValidator(control: AbstractControl): ValidationErrors | null {
  const value = control.value as string;
  if (!value) return null;
  const valid = /^[a-z0-9_]+$/.test(value);
  return valid ? null : { invalidUsername: true };
}

// usage in form builder
this.userForm = this.fb.group({
  username: ['', [Validators.required, usernameValidator]],
});

Show helpful messages in the template when invalidUsername exists.

Cross-Field Validation (Password Match)

Some validations depend on multiple controls. Use a validator on the FormGroup:
function passwordMatchValidator(group: AbstractControl): ValidationErrors | null {
  const password = group.get('password')?.value;
  const confirm = group.get('confirmPassword')?.value;
  return password === confirm ? null : { passwordsMismatch: true };
}

this.userForm = this.fb.group({
  password: ['', Validators.required],
  confirmPassword: ['', Validators.required],
}, { validators: passwordMatchValidator });

In the template, show the group-level error:
<div *ngIf="userForm.errors?.passwordsMismatch && userForm.touched">
  <small>Passwords do not match.</small>
</div>


Async Validators (e.g., Check Email Uniqueness)

Async validators are useful for server checks like "is this email taken?". They return an Observable or Promise.
import { AbstractControl } from '@angular/forms';
import { map } from 'rxjs/operators';
import { of } from 'rxjs';

function uniqueEmailValidator(apiService: ApiService) {
  return (control: AbstractControl) => {
    if (!control.value) return of(null);
    return apiService.checkEmail(control.value).pipe(
      map(isTaken => (isTaken ? { emailTaken: true } : null))
    );
  };
}

// in component
this.userForm = this.fb.group({
  email: ['', {
    validators: [Validators.required, Validators.email],
    asyncValidators: [uniqueEmailValidator(this.apiService)],
    updateOn: 'blur' // run async validator on blur to reduce calls
  }]
});

Use updateOn: 'blur' to prevent calling the server on every keystroke.

Displaying Validation State and UX Tips

  • Show errors only after user interaction — use touched or dirty to avoid overwhelming users with errors on load.
  • Disable submit while invalid — [disabled]="userForm.invalid" prevents sending bad data.
  • Focus the first invalid control — on submit, set focus to the first invalid field for better UX.
  • Use updateOn: 'blur' or debounce — reduces validation frequency and server calls.

Example to focus first invalid:
onSubmit() {
  if (this.userForm.invalid) {
    const invalidControl = this.el.nativeElement.querySelector('.ng-invalid');
    invalidControl?.focus();
    return;
  }
  // process valid form
}

Reacting to Value Changes and Live Validation
You can subscribe to valueChanges for any control or the whole form to implement live validation messages, dynamic rules, or enable/disable fields.
this.userForm.get('country')?.valueChanges.subscribe(country => {
  if (country === 'US') {
    this.userForm.get('state')?.setValidators([Validators.required]);
  } else {
    this.userForm.get('state')?.clearValidators();
  }
  this.userForm.get('state')?.updateValueAndValidity();
});

Remember to unsubscribe in ngOnDestroy or use the takeUntil pattern.

Integrating with Backend Validation
Server-side validation is the final source of truth. When the backend returns validation errors, map them to form controls so users can correct them:
// after API error response
handleServerErrors(errors: Record<string, string[]>) {
  Object.keys(errors).forEach(field => {
    const control = this.userForm.get(field);
    if (control) {
      control.setErrors({ server: errors[field][0] });
    }
  });
}


Show control.errors.server messages in the template.

Testing Form Validation
Unit test reactive forms by creating the component, setting values, and asserting validity:
it('should invalidate empty email', () => {
  component.userForm.get('email')?.setValue('');
  expect(component.userForm.get('email')?.valid).toBeFalse();
});


For async validators, use fakeAsync and tick() to simulate time.

  • Accessibility (A11y) Considerations
  • Always link error messages to inputs with aria-describedby.
  • Use clear error language and avoid technical terms.
  • Ensure focus management sends keyboard users to errors on submit.

Example
<input id="email" formControlName="email" aria-describedby="emailError" />
<div id="emailError" *ngIf="userForm.get('email')?.invalid">
  <small>Enter a valid email address.</small>
</div>

Performance Tips and Best Practices

  • Use OnPush change detection where appropriate to reduce re-renders.
  • Avoid heavy computation inside valueChanges subscribers.
  • Use debounceTime for expensive validations or server calls:

this.userForm.get('search')?.valueChanges.pipe(debounceTime(300)).subscribe(...);

Clean up subscriptions with takeUntil or async pipe.

Summary
An effective, testable method for managing form validation is provided by Angular's Reactive Forms. For common rules, use the built-in validators; for special cases, create your own sync and async validators; and for cross-field checks, such as password confirmation, use group validators. Enhance the user experience by integrating server-side errors using setErrors, emphasizing the initial incorrect control, and displaying errors upon interaction. Use performance techniques like debouncing and OnPush change detection, test your validations, and consider accessibility.



AngularJS Hosting Europe - HostForLIFE :: Angular Subscription Management: Using RxJS to Fix Memory Leaks

clock July 21, 2025 08:26 by author Peter

Angular uses RxJS Observables quite extensively for asynchronous data anything from HTTP requests, form value changes, events, route parameters, and many more. Most of the time, you would subscribe to them, but not unsubscribing properly may cause memory leaks and unexpected behavior, especially in large or long-running apps. In this article, we share how we faced a real-life issue related to missed unsubscriptions, how we identified the leak, and how we applied best practices, such as the takeUntil operator and a reusable base class.

Real Scenario
In various dashboard applications, several components had the possibility of listening to data streams coming from the API, user interactions, and changes in route parameters. Such components use subscription on observables through the RxJS subscribe() method inside the Angular lifecycle hooks of ngOnInit().

Example
ngOnInit(): void {
  this.route.params.subscribe(params => {
    this.loadData(params['id']);
  });

  this.userService.getUser().subscribe(user => {
    this.user = user;
  });
}


After navigating between routes multiple times, we noticed the following issues.

  • Console logs appeared multiple times for the same action.
  • Network requests were duplicated.
  • The browser’s memory usage slowly increased over time.

Root Cause

  • Upon inspection using Chrome DevTools memory tab and Angular DevTools, we found that components were not being garbage collected. This was due to active subscriptions holding references to destroyed components.
  • Solution: Using the takeUntil Pattern with Subject.

To fix this, we implemented the takeUntil pattern with a private Subject.

Step 1. Declare an Unsubscribe Subject.
private destroy$ = new Subject<void>();

Step 2. Use takeUntil(this.destroy$) in Every Subscription.
ngOnInit(): void {
  this.route.params
    .pipe(takeUntil(this.destroy$))
    .subscribe(params => this.loadData(params['id']));

  this.userService.getUser()
    .pipe(takeUntil(this.destroy$))
    .subscribe(user => this.user = user);
}


Step 3. Emit and complete the Subject in ngOnDestroy().
ngOnDestroy(): void {
  this.destroy$.next();
  this.destroy$.complete();
}

This pattern ensures that all subscriptions automatically unsubscribe when the component is destroyed.

Improvement: Create a Base Component Class

To avoid repeating the same code in every component, we created a base class.
export abstract class BaseComponent implements OnDestroy {
  protected destroy$ = new Subject<void>();

  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }
}


Now, in any component.
export class MyComponent extends BaseComponent implements OnInit {

  ngOnInit(): void {
    this.dataService.getData()
      .pipe(takeUntil(this.destroy$))
      .subscribe(data => this.data = data);
  }

}


Alternative Approach: AsyncPipe for Simpler Cases
In cases where we can bind observables directly in the template, we prefer using Angular’s AsyncPipe, which handles subscription and unsubscription automatically.

Instead of,
this.dataService.getData().subscribe(data => {
  this.data = data;
});


Use in the template.
data$ = this.dataService.getData();

<div *ngIf="data$ | async as data">
  {{ data.name }}
</div>


Conclusion
Failing to unsubscribe from observables in Angular can lead to performance issues, duplicate API calls, and memory leaks. Using takeUntil with a Subject is a reliable and scalable solution, especially when combined with a base component class. For simpler use cases, Angular's AsyncPipe provides a clean and safe way to handle subscriptions in templates. Adhering to these practices keeps your Angular applications running smoothly, easy to maintain, and protected from those memory leaks that can improve performance. You will maintain both efficiency and code clarity as a result.



AngularJS Hosting Europe - HostForLIFE :: Using Angular Route Guards to Secure Routes

clock July 16, 2025 10:07 by author Peter

Depending on whether a user is logged in or has particular permissions, we frequently need to limit access to particular routes in Angular apps. Angular offers Route Guards, like CanActivate, to protect certain routes. In one of our projects, we had to prevent users from accessing the dashboard unless they were authenticated. We created an AuthGuard with CanActivate and added logic to check if the user token was locally stored. Everything was running fine until we released the app.


 Some users claimed that they were repeatedly taken to the login screen even if they were already logged in.

Reasons for the Problem
We found that timing was the cause of the problem. The guard attempted to verify the token before the validation was finished, even though the app had already called the API to validate the token at startup. It is therefore believed that the user was not authenticated.

How did we fix it?

Our AuthGuard logic has been modified to wait for validation to complete before granting or denying access. We used a shared AuthService with an isAuthenticated$ observable rather than just checking local storage.

Here’s how we adjusted the AuthGuard.
canActivate(): Observable<boolean> {
  return this.authService.isAuthenticated$.pipe(
    take(1),
    map(isAuth => {
      if (!isAuth) {
        this.router.navigate(['/login']);
        return false;
      }
      return true;
    })
  );
}


And in the AuthService, we updated the token status using a BehaviorSubject once the API response came back.
private authStatus = new BehaviorSubject<boolean>(false);

isAuthenticated$ = this.authStatus.asObservable();

validateToken() {
  // Call backend to validate token
  this.http.get('/api/validate-token').subscribe(
    () => this.authStatus.next(true),
    () => this.authStatus.next(false)
  );
}

We called validateToken() once in AppComponent during app initialization.

Conclusion
Route guards are essential for secure routing in Angular apps. But they must be carefully integrated with authentication logic, especially when token validation involves an async call. Using an observable approach helps in handling real-time state and avoiding premature navigation decisions.



AngularJS Hosting Europe - HostForLIFE :: Using Angular Route Guards to Secure Routes

clock July 14, 2025 08:33 by author Peter

Depending on whether a user is logged in or has particular permissions, we frequently need to limit access to particular routes in Angular apps. Angular offers Route Guards, like CanActivate, to protect certain routes. In one of our projects, we had to prevent users from accessing the dashboard unless they were authenticated. We created an AuthGuard with CanActivate and added logic to check if the user token was locally stored. Everything was running fine until we released the app.


Some users claimed that they were repeatedly taken to the login screen even if they were already logged in.

Reasons for the Problem
We found that timing was the cause of the problem. The guard attempted to verify the token before the validation was finished, even though the app had already called the API to validate the token at startup. It is therefore believed that the user was not authenticated.

How did we fix it?
Our AuthGuard logic has been modified to wait for validation to complete before granting or denying access. We used a shared AuthService with an isAuthenticated$ observable rather than just checking local storage.

Here’s how we adjusted the AuthGuard.

canActivate(): Observable<boolean> {
  return this.authService.isAuthenticated$.pipe(
    take(1),
    map(isAuth => {
      if (!isAuth) {
        this.router.navigate(['/login']);
        return false;
      }
      return true;
    })
  );
}


And in the AuthService, we updated the token status using a BehaviorSubject once the API response came back.
private authStatus = new BehaviorSubject<boolean>(false);

isAuthenticated$ = this.authStatus.asObservable();

validateToken() {
  // Call backend to validate token
  this.http.get('/api/validate-token').subscribe(
    () => this.authStatus.next(true),
    () => this.authStatus.next(false)
  );
}


We called validateToken() once in AppComponent during app initialization.

Conclusion
Route guards are essential for secure routing in Angular apps. But they must be carefully integrated with authentication logic, especially when token validation involves an async call. Using an observable approach helps in handling real-time state and avoiding premature navigation decisions.



AngularJS Hosting Europe - HostForLIFE :: Use the ASP.NET Web API in Angular to Retrieve Data From a Database

clock June 25, 2025 09:45 by author Peter

In this article, I will explain how to call ASP.NET web API in your Angular project step by step. You need to enable CORS in your web API and fetch data from web API. It is easy to call API in Angular.


Step 1
Open SQL server of your choice and create a table and insert some records.

    CREATE TABLE [dbo].[Employee](  
        [Employee_Id] [int] IDENTITY(1,1) NOT NULL,  
        [First_Name] [nvarchar](50) NULL,  
        [Last_Name] [nvarchar](50) NULL,  
        [Salary] [money] NULL,  
        [Joing_Date] [nvarchar](50) NULL,  
        [Department] [nvarchar](50) NULL,  
     CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED   
    (  
        [Employee_Id] ASC  
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]  
    ) ON [PRIMARY]  
      
    GO  

Step 2

Open Visual Studio, click on New Project and create an empty web API application project.

After clicking on New Project, one window will appear. Select Web from the left panel, choose ASP.NET Web Application, give a meaningful name to your project, and then click on OK as shown in the below screenshot.

After clicking on OK one more window will appear; choose empty, check on empty Web API checkbox then click on OK as shown in the below screenshot

After clicking OK, the project will be created with the name of WebAPICRUD_Demo.

Step 3
Add Entity Framework now. For that, right click on Models folder, select Add, then select New Item, then click on it.

After clicking on a New item, you will get a window; from there, select Data from the left panel and choose ADO.NET Entity Data Model, give it the name MyModel (this name is not mandatory you can give any name) and click on Add.

After you click on "Add a window", the wizard will open, choose EF Designer from the database and click Next.

After clicking on Next a window will appear. Choose New Connection. Another window will appear, add your server name if it is local then enter a dot (.). Choose your database and click on OK.

The connection will be added. If you wish to save connect as you want. You can change the name of your connection below. It will save connection in web config then click on Next.

After clicking on NEXT another window will appear to choose database table name as shown in the below screenshot then click on Finish. Entity framework will be added and the respective class gets generated under the Models folder.

Following class will be added,
    namespace WebAPICURD_Demo.Models  
    {  
        using System;  
        using System.Collections.Generic;  
          
        public partial class Employee  
        {  
            public int Employee_Id { get; set; }  
            public string First_Name { get; set; }  
            public string Last_Name { get; set; }  
            public Nullable<decimal> Salary { get; set; }  
            public string Joing_Date { get; set; }  
            public string Department { get; set; }  
        }  
    }  

Step 4
Right click on Controllers folder, select Add, then choose Controller as shown in the below screenshot.


After clicking on the controller a window will appear to choose Web API 2 Controller-Empty, click on Add.


Fetch Data From Database Using ASP.NET Web API In Angular
After clicking on Add, another window will appear with DefaultController. Change the name to EmployeeController then click on Add. EmployeeController will be added under Controllers folder. Remember don’t change the Controller suffix for all controllers, change only highlight, and instead of Default just change Home as shown in the below screenshot.


Complete code for controller
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Net;  
    using System.Net.Http;  
    using System.Web.Http;  
    using WebAPICURD_Demo.Models;  
      
    namespace WebAPICURD_Demo.Controllers  
    {  
        public class EmployeeController : ApiController  
        {  
             
            private EmployeeEntities _db;  
            public EmployeeController()  
            {  
                _db =new EmployeeEntities();  
            }  
            public IEnumerable<Employee> GetEmployees()  
            {  
                return _db.Employees.ToList();  
            }  
        }  
    }  


Step 5
Now, enable CORS in the WebService app. First, add the CORS NuGet package. In Visual Studio, from the Tools menu, select NuGet Package Manager, then select Package Manager Console. In the Package Manager Console window, type the following command.
Install-Package Microsoft.AspNet.WebApi.Cors  

This command installs the latest package and updates all dependencies, including the core Web API libraries.

Step 6
Open the file App_Start/WebApiConfig.cs. Add the following code to the WebApiConfig.Register method.

Add namespace
using System.Web.Http.Cors;  

Add the following line of code,
    EnableCorsAttribute cors = new EnableCorsAttribute("*","*","*");  
    config.EnableCors(cors);  


Complete WebApiConfig.cs file code
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Web.Http;  
    using System.Web.Http.Cors;  
      
    namespace WebAPICURD_Demo  
    {  
        public static class WebApiConfig  
        {  
            public static void Register(HttpConfiguration config)  
            {  
                // Web API configuration and services  
                  
                // Web API routes  
                config.MapHttpAttributeRoutes();  
      
                config.Routes.MapHttpRoute(  
                    name: "DefaultApi",  
                    routeTemplate: "api/{controller}/{id}",  
                    defaults: new { id = RouteParameter.Optional }  
                );  
      
                EnableCorsAttribute cors = new EnableCorsAttribute("*","*","*");  
                config.EnableCors(cors);  
            }  
        }  
    }  


Step 6
Open Visual Studio Code and create a new Angular project.
    ng new MyDemo  

Compile your project
    cd MyDemo  

Open your project in the browser,
    ng serve --open  

Step 7
Install bootstrap in your project and import in style.css file,
    npm install bootstrap –save  

    @import 'node_modules/bootstrap/dist/css/bootstrap.min.css';  


Step 8
Open terminal create component,
    ng g c employee-list  

Step 9
Open app.module.ts file and import httpModule
    import { BrowserModule } from '@angular/platform-browser';  
    import { NgModule } from '@angular/core';  
    import {HttpClientModule, HttpClient} from '@angular/common/http';  
      
    import { AppComponent } from './app.component';  
    import { from } from 'rxjs';  
    import { EmployeeListComponent } from './employee-list/employee-list.component';  
      
    @NgModule({  
      declarations: [  
        AppComponent,  
        EmployeeListComponent  
      ],  
      imports: [  
        BrowserModule,  
        HttpClientModule  
      ],  
      providers: [],  
      bootstrap: [AppComponent]  
    })  
    export class AppModule { }  


Step 10
Open employee-list component.ts file and add the following code,
    import { HttpClientModule, HttpClient } from '@angular/common/http';  
    import { Component, OnInit } from '@angular/core';  
      
    @Component({  
      selector: 'app-employee-list',  
      templateUrl: './employee-list.component.html',  
      styleUrls: ['./employee-list.component.css']  
    })  
    export class EmployeeListComponent implements OnInit {  
      
      constructor(private httpService: HttpClient) { }  
      employees: string[];  
      ngOnInit() {  
        this.httpService.get('http://localhost:52202/api/employee').subscribe(  
          data => {  
           this.employees = data as string [];  
          }  
        );  
      }  
      
    }  


Step 11
open employee-list.component.html and add the following code,
    <div class="container py-5">  
        <h3 class="text-center text-uppercase">List of Employees</h3>  
        <table class="table table-bordered table-striped">  
            <thead>  
                <tr class="text-center text-uppercase">  
                    <th>Employee ID</th>  
                    <th>First Name</th>  
                    <th>Last Name</th>  
                    <th>Salary</th>  
                    <th>Joining Date</th>  
                    <th>Department</th>  
                  </tr>  
            </thead>  
            <tbody>  
              <tr *ngFor="let emp of employees">  
                <td>{{emp.Employee_Id}}</td>  
                <td>{{emp.First_Name}}</td>  
                <td>{{emp.Last_Name}}</td>  
                <td>{{emp.Salary}}</td>  
                <td>{{emp.Joing_Date}}</td>  
                <td>{{emp.Department}}</td>  
              </tr>  
            </tbody>  
          </table>  
        </div>  


Step 12
Add your employee-list.component.html selector in app.component.html
    <app-employee-list></app-employee-list>  

Step 13
Run your project in browser.



AngularJS Hosting Europe - HostForLIFE :: New Development Site Angular

clock June 17, 2025 09:19 by author Peter

Note: The publication date of this article is January 10, 2025. This article series is unquestionably an AI result or byproduct.  This piece might represent a change in my writing style since it makes use of AI results that I understand, like those related to StackBlitz | Instant Dev Environments, to make it easier to write and easier to read. Angular first launched in 2016, Angular's home page used to be at angular.io for years. Recently, I found that a new Angular Development Site has been created. This article records some info about this event. 

Official Home: May, 2024

Previous Sites:
Angular - Introduction to the Angular docs --- Angular.io --- v17

Angular - Introduction to the Angular docs --- Angular.io --- v18


Tutorial:

Tutorials • Angular



AngularJS Hosting Europe - HostForLIFE :: Angular State Management with NGXS

clock June 12, 2025 10:33 by author Peter

Managing shared state between components gets more difficult as your Angular application expands.  NGXS (pronounced "nexus") offers a simple, intuitive, and powerful state management pattern for Angular apps, based on the principles of Redux but with a more Angular-friendly approach. This post will discuss how to effectively manage application state by configuring and utilizing NGXS.

Why NGXS?
NGXS provides:

  • A simple API using decorators and observables.
  • Type-safe state and actions.
  • Built-in support for plugins (logger, devtools, storage).
  • Easy-to-understand state mutation via actions.

Step 1. Install NGXS
Use the Angular CLI to install the NGXS packages:
npm install @ngxs/store --save


Optional DevTools and plugins:
npm install @ngxs/devtools-plugin @ngxs/logger-plugin --save

Step 2. Create a State Model
Create an interface to define your state:
// models/todo.model.ts
export interface Todo {
  id: number;
  title: string;
  completed: boolean;
}

Step 3. Define Actions
Actions are plain classes that represent events in your app.

// actions/todo.actions.ts
export class AddTodo {
  static readonly type = '[TODO] Add';
  constructor(public payload: string) {}
}

export class ToggleTodo {
  static readonly type = '[TODO] Toggle';
  constructor(public id: number) {}
}

Step 4. Create the State
Define the NGXS state using the @State() decorator.
// state/todo.state.ts
import { State, Action, StateContext, Selector } from '@ngxs/store';
import { AddTodo, ToggleTodo } from '../actions/todo.actions';
import { Todo } from '../models/todo.model';

@State<Todo[]>({
  name: 'todos',
  defaults: []
})
export class TodoState {

  @Selector()
  static getTodos(state: Todo[]) {
    return state;
  }

  @Action(AddTodo)
  add({ getState, patchState }: StateContext<Todo[]>, { payload }: AddTodo) {
    const state = getState();
    const newTodo: Todo = { id: Date.now(), title: payload, completed: false };
    patchState([...state, newTodo]);
  }

  @Action(ToggleTodo)
  toggle({ getState, patchState }: StateContext<Todo[]>, { id }: ToggleTodo) {
    const state = getState();
    const updated = state.map(todo =>
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    );
    patchState(updated);
  }
}


Step 5. Register the State in the App Module

// app.module.ts
import { NgxsModule } from '@ngxs/store';
import { TodoState } from './state/todo.state';

@NgModule({
  declarations: [...],
  imports: [
    NgxsModule.forRoot([TodoState]),
  ],
  bootstrap: [...]
})
export class AppModule {}

Step 6. Use the State in Components
// app.component.ts
import { Store, Select } from '@ngxs/store';
import { Observable } from 'rxjs';
import { TodoState } from './state/todo.state';
import { AddTodo, ToggleTodo } from './actions/todo.actions';

@Component({...})
export class AppComponent {
  @Select(TodoState.getTodos) todos$: Observable<Todo[]>;

  constructor(private store: Store) {}

  addTodo(title: string) {
    this.store.dispatch(new AddTodo(title));
  }

  toggleTodo(id: number) {
    this.store.dispatch(new ToggleTodo(id));
  }
}

Conclusion
NGXS brings a clean and declarative way to manage state in Angular apps. With actions, selectors, and plugins, it streamlines complex state flows into something more maintainable and scalable. Happy coding !



About HostForLIFE

HostForLIFE is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes.

We have offered the latest Windows 2019 Hosting, ASP.NET 5 Hosting, ASP.NET MVC 6 Hosting and SQL 2019 Hosting.


Tag cloud

Sign in