close
close
angular http interceptor loading spinner

angular http interceptor loading spinner

3 min read 01-10-2024
angular http interceptor loading spinner

Angular is a powerful framework for building dynamic web applications, and one common feature users expect is feedback during data loading processes. A loading spinner is an excellent way to improve user experience by indicating that a request is in progress. In this article, we’ll explore how to create an Angular HTTP Interceptor to manage a loading spinner and provide an enhanced user experience.

What is an HTTP Interceptor?

An HTTP Interceptor in Angular is a service that can modify requests and responses. It's part of the Angular HttpClientModule and can be used to handle tasks such as logging, error handling, and managing loading states. When an HTTP request is made, the interceptor captures the request, processes it, and can also react to the response.

Why Use a Loading Spinner?

  • User Feedback: Provides immediate feedback to the user that their action is being processed.
  • Improved UX: Prevents users from taking actions that may cause issues or errors while data is loading.
  • Visual Consistency: Keeps the interface dynamic and interactive, making applications feel more responsive.

Step-by-Step Implementation

1. Create a New Angular Project

If you haven't set up an Angular project yet, you can create one by running the following command:

ng new loading-spinner-example

2. Generate a New Interceptor

Generate a new interceptor using Angular CLI:

ng generate interceptor loading

3. Implement the Loading Spinner Logic

In your loading.interceptor.ts, you can implement logic to manage the loading spinner. Here’s a basic example:

import { Injectable } from '@angular/core';
import {
  HttpEvent,
  HttpInterceptor,
  HttpHandler,
  HttpRequest,
  HttpResponse,
  HttpErrorResponse
} from '@angular/common/http';
import { Observable, tap } from 'rxjs';
import { LoadingSpinnerService } from './loading-spinner.service'; // Assuming you created a loading spinner service

@Injectable()
export class LoadingInterceptor implements HttpInterceptor {

  constructor(private loadingSpinnerService: LoadingSpinnerService) {}

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    this.loadingSpinnerService.show(); // Show loading spinner before request

    return next.handle(req).pipe(
      tap(
        (event: HttpEvent<any>) => {
          if (event instanceof HttpResponse) {
            this.loadingSpinnerService.hide(); // Hide spinner on response
          }
        },
        (error: HttpErrorResponse) => {
          this.loadingSpinnerService.hide(); // Hide spinner on error
          // Handle error appropriately
        }
      )
    );
  }
}

4. Create a Loading Spinner Service

You can manage the visibility of the loading spinner using a dedicated service:

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class LoadingSpinnerService {
  private loadingSubject = new BehaviorSubject<boolean>(false);
  loading$ = this.loadingSubject.asObservable();

  show() {
    this.loadingSubject.next(true);
  }

  hide() {
    this.loadingSubject.next(false);
  }
}

5. Create the Loading Spinner Component

Next, create a loading spinner component that listens to the loading$ observable from the service:

import { Component } from '@angular/core';
import { LoadingSpinnerService } from './loading-spinner.service';

@Component({
  selector: 'app-loading-spinner',
  template: `
    <div *ngIf="isLoading | async" class="spinner-overlay">
      <div class="spinner"></div>
    </div>
  `,
  styles: [`
    .spinner-overlay {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background: rgba(255, 255, 255, 0.8);
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .spinner {
      border: 5px solid #f3f3f3;
      border-top: 5px solid #3498db;
      border-radius: 50%;
      width: 50px;
      height: 50px;
      animation: spin 1s linear infinite;
    }
    @keyframes spin {
      0% { transform: rotate(0deg); }
      100% { transform: rotate(360deg); }
    }
  `]
})
export class LoadingSpinnerComponent {
  isLoading = this.loadingSpinnerService.loading$;

  constructor(private loadingSpinnerService: LoadingSpinnerService) {}
}

6. Integrate the Spinner Component

Finally, include the LoadingSpinnerComponent in your main application component (usually app.component.html):

<app-loading-spinner></app-loading-spinner>
<router-outlet></router-outlet>

7. Register the Interceptor

Don’t forget to register the interceptor in your app module:

import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { LoadingInterceptor } from './loading.interceptor';

@NgModule({
  declarations: [
    // your components
  ],
  imports: [
    // your modules
  ],
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: LoadingInterceptor, multi: true },
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

Conclusion

Implementing a loading spinner using an Angular HTTP Interceptor significantly enhances user experience by providing feedback during data loading operations. By managing the visibility of the spinner through a dedicated service, you can maintain clean and efficient code.

Feel free to expand on this implementation by customizing the spinner's design or adding additional features such as error handling. Remember, user experience is key in web applications, and a little feedback can go a long way!

Additional Considerations

  1. SEO Optimization: While loading spinners are primarily a UX element, remember that any loading content will not be indexed by search engines. Therefore, try to reduce loading times by optimizing API responses.

  2. Testing: Ensure to write unit tests for your interceptor and spinner service to validate that the loading spinner behaves as expected under various conditions.

By incorporating a loading spinner with Angular's HTTP Interceptor, you create a more engaging and user-friendly application. Happy coding!

Latest Posts