Thanks to visit codestin.com
Credit goes to www.w3schools.com

Menu
×
   ❮     
HTML CSS JAVASCRIPT SQL PYTHON JAVA PHP HOW TO W3.CSS C C++ C# BOOTSTRAP REACT MYSQL JQUERY EXCEL XML DJANGO NUMPY PANDAS NODEJS DSA TYPESCRIPT ANGULAR ANGULARJS GIT POSTGRESQL MONGODB ASP AI R GO KOTLIN SASS VUE GEN AI SCIPY CYBERSECURITY DATA SCIENCE INTRO TO PROGRAMMING BASH RUST

Angular HttpClient


HttpClient lets your app fetch and send data over HTTP.


HTTP Essentials

  • Client: Use HttpClient to fetch and send JSON.
  • Observables: HTTP methods return Observables. Use subscribe() or the async pipe.
  • UX: Show loading and clear error messages.
  • Provide once: Register provideHttpClient() at bootstrap.
import { provideHttpClient, HttpClient } from '@angular/common/http';

// Bootstrap
// bootstrapApplication(App, { providers: [provideHttpClient()] });

// Use in a component
// http.get<User[]>('/api/users').subscribe({ next: d => users = d });

Notes:

  • Related: See Services to encapsulate HTTP logic, Router for navigations after requests, and Templates for rendering lists and states.
  • Provide the client with provideHttpClient() at bootstrap.
  • Use non-blocking UIs with loading and error states; be mindful of CORS (browser security that controls which origins can call an API) when calling public APIs.
  • Base URL & env: Centralize the API base URL/config in a token or constant and reuse it in services.
  • Security: Validate untrusted URL parts; avoid interpolating raw user input directly into request URLs.

GET Requests

  • Read data with http.get<T>().
  • Track loading and error state for UX.
  • Update component state in the subscription.
loading = true; error = '';
http.get<User[]>('/api/users').subscribe({
  next: d => { users = d; loading = false; },
  error: () => { error = 'Failed to load'; loading = false; }
});

Example

import { bootstrapApplication } from '@angular/platform-browser';
import { Component, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { provideHttpClient, HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule],
  template: `
    <h3>HttpClient</h3>
    <button (click)="load()">Load Users</button>
    <p *ngIf="loading">Loading...</p>
    <p *ngIf="error" style="color:crimson">{{ error }}</p>
    <ul>
      <li *ngFor="let u of users">{{ u.name }} ({{ u.email }})</li>
    </ul>
  `
})
export class App {
  http = inject(HttpClient);
  users: any[] = [];
  loading = false;
  error = '';

  load() {
    this.loading = true;
    this.error = '';
    this.http.get<any[]>('https://jsonplaceholder.typicode.com/users')
      .subscribe({
        next: (data) => { this.users = data; this.loading = false; },
        error: () => { this.error = 'Failed to load users'; this.loading = false; }
      });
  }
}

bootstrapApplication(App, { providers: [provideHttpClient()] });
<app-root></app-root>

Run Example »

Example explained

  • provideHttpClient(): Registers HttpClient so requests work.
  • inject(HttpClient): Retrieves the client in a standalone component.
  • GET: http.get<any[]>(url) returns an Observable; subscribe() sets users on success and error on failure.
  • UX flags: loading and error drive the template (spinner/message).

Notes:

  • Standalone-friendly: Use provideHttpClient() over importing HttpClientModule.
  • Cross-cutting: Use interceptors (hooks on each request/response) for auth/logging; register once at the appropriate scope.
  • UX: Avoid multiple clicks by disabling the button while loading.
  • CORS: If calls fail in the browser but work in curl, it may be CORS—use APIs that allow your origin or a proxy.
  • Typing & options: Use get<MyType>() and build options with HttpParams/HttpHeaders.


POST Requests

  • Create data with http.post<T>().
  • Disable the button while sending to prevent duplicates.
  • Render the returned result or an error message.
loading = true; error = ''; result = null;
http.post<Post>('/api/posts', { title, body }).subscribe({
  next: r => { result = r; loading = false; },
  error: () => { error = 'Failed to create'; loading = false; }
});

Example

import { bootstrapApplication } from '@angular/platform-browser';
import { Component, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { provideHttpClient, HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule],
  template: `
    <h3>HttpClient POST</h3>
    <button (click)="createPost()" [disabled]="loading">Create Post</button>
    <p *ngIf="loading">Sending...</p>
    <p *ngIf="error" style="color:crimson">{{ error }}</p>
    <div *ngIf="result">
      <p>Created Post ID: {{ result.id }}</p>
      <p>Title: {{ result.title }}</p>
    </div>
  `
})
export class App {
  http = inject(HttpClient);
  loading = false;
  error = '';
  result: any = null;

  createPost() {
    this.loading = true;
    this.error = '';
    this.result = null;
    this.http.post<any>('https://jsonplaceholder.typicode.com/posts', {
      title: 'foo',
      body: 'bar',
      userId: 1
    }).subscribe({
      next: (res) => { this.result = res; this.loading = false; },
      error: () => { this.error = 'Failed to create post'; this.loading = false; }
    });
  }
}

bootstrapApplication(App, { providers: [provideHttpClient()] });
<app-root></app-root>

Run Example »

Example explained

  • POST: http.post<T>(url, body) sends JSON and returns the created object.
  • Disable while sending: The button binds to loading to prevent duplicate submissions.
  • Result: On success, show the returned result; on error, show a clear message.

Notes:

  • Validate inputs: Send the minimal, validated payload the server expects; show field errors clearly.
  • Idempotency: Avoid duplicate submissions; keep the button disabled while sending and after success if appropriate.
  • Handle errors: Show a clear error message and let the user retry; keep the UI responsive with a loading flag.

Error Handling

  • Always show a helpful message and allow retry.
  • Check status codes to decide retry vs fail fast.
  • Keep the UI responsive with a loading flag.
error = ''; loading = true;
http.get('/api/data').subscribe({
  next: r => { data = r; loading = false; },
  error: err => { error = `Request failed (status ${'{'}err?.status ?? 'unknown'{}})`; loading = false; }
});

Example

import { bootstrapApplication } from '@angular/platform-browser';
import { Component, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { provideHttpClient, HttpClient, withInterceptors, HttpResponse, HttpErrorResponse, HttpRequest, HttpHandlerFn } from '@angular/common/http';
import { of, throwError } from 'rxjs';

// Fake HTTP interceptor so the demo works without external network calls
function mockHttp(req: HttpRequest<any>, next: HttpHandlerFn) {
  if (req.method === 'GET' && req.url.includes('jsonplaceholder.typicode.com/usersx')) {
    return throwError(() => new HttpErrorResponse({ status: 404, statusText: 'Not Found', url: req.url }));
  }
  if (req.method === 'GET' && req.url.includes('jsonplaceholder.typicode.com/users')) {
    const body = [
      { id: 1, name: 'Leanne Graham', email: '[email protected]' },
      { id: 2, name: 'Ervin Howell', email: '[email protected]' }
    ];
    return of(new HttpResponse({ status: 200, body }));
  }
  return next(req);
}

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule],
  styles: [`
    button { margin-right: 8px; }
    .error { color: crimson; }
    .ok { color: seagreen; }
  `],
  template: `
    <h3>HTTP Error Handling</h3>

    <div>
      <button (click)="loadOk()" [disabled]="loading">Load OK</button>
      <button (click)="loadFail()" [disabled]="loading">Load Fail</button>
      <button (click)="retry()" [disabled]="!lastAction || loading">Retry</button>
    </div>

    <p *ngIf="loading">Loading...</p>
    <p *ngIf="error" class="error">{{ error }}</p>
    <p *ngIf="!error && data" class="ok">Loaded {{ isArray(data) ? data.length + ' items' : '1 item' }}</p>

    <ul *ngIf="isArray(data)">
      <li *ngFor="let u of data">{{ u.name }} ({{ u.email }})</li>
    </ul>
  `
})
export class App {
  http = inject(HttpClient);
  loading = false;
  error = '';
  data: any[] | null = null;
  lastAction = '';
  isArray(value: unknown): value is any[] { return Array.isArray(value as any); }

  fetch(url: string): void {
    this.loading = true;
    this.error = '';
    this.data = null;
    this.http.get<any[]>(url).subscribe({
      next: (res) => { this.data = res; this.loading = false; },
      error: (err) => {
        const status = err?.status ?? 'unknown';
        this.error = `Request failed (status ${status}). Please try again.`;
        this.loading = false;
      }
    });
  }

  loadOk() {
    this.lastAction = 'ok';
    this.fetch('https://jsonplaceholder.typicode.com/users');
  }

  loadFail() {
    this.lastAction = 'fail';
    this.fetch('https://jsonplaceholder.typicode.com/usersx');
  }

  retry() {
    if (this.lastAction === 'ok') this.loadOk();
    else if (this.lastAction === 'fail') this.loadFail();
  }
}

bootstrapApplication(App, { providers: [provideHttpClient(withInterceptors([mockHttp]))] });
<app-root></app-root>

Run Example »

Example explained

  • Error message: Build a helpful message from err.status; keep the UI responsive with loading.
  • Retry: Store the lastAction and wire a retry() button to re-run the last request.
  • OK vs Fail: Separate methods help demonstrate success and failure flows.

Notes:

  • Don't swallow errors: Surface a helpful message to users and log details for debugging.
  • Retry strategy: Only retry on transient errors (e.g., 5xx); avoid retrying 4xx client errors.
  • Feedback: Show a clear error message and let the user retry; keep the UI responsive with a loading flag.
  • Cancel stale requests: On rapid input, switch to the latest stream (e.g., switchMap) to avoid races.
  • Interceptors: Centralize auth headers, logging, and retry to keep components slim.

HTTP Interceptors

  • Run cross-cutting logic on every request/response (e.g., auth headers, logging).
  • Register once at bootstrap with provideHttpClient(...).
import { HttpInterceptorFn, provideHttpClient, withInterceptors } from '@angular/common/http';

export const authInterceptor: HttpInterceptorFn = (req, next) => {
  const cloned = req.clone({ setHeaders: { Authorization: 'Bearer TOKEN' } });
  return next(cloned);
};

bootstrapApplication(App, {
  providers: [provideHttpClient(withInterceptors([authInterceptor]))]
});

Example

import { bootstrapApplication } from '@angular/platform-browser';
import { Component } from '@angular/core';
import { provideHttpClient, withInterceptors } from '@angular/common/http';

@Component({ selector: 'app-root', standalone: true, template: `<p>Interceptors demo</p>` })
export class App {}

bootstrapApplication(App, {
  providers: [provideHttpClient(withInterceptors([]))]
});
<app-root></app-root>

Run Example »

Example explained

  • withInterceptors([...]): Registers interceptor functions for all requests.
  • Interceptor: A function (req, next) that can req.clone(...) to modify the request, then calls next(req).
  • provideHttpClient(): Enables HttpClient and composes interceptors at bootstrap.


×

Contact Sales

If you want to use W3Schools services as an educational institution, team or enterprise, send us an e-mail:
[email protected]

Report Error

If you want to report an error, or if you want to make a suggestion, send us an e-mail:
[email protected]

W3Schools is optimized for learning and training. Examples might be simplified to improve reading and learning. Tutorials, references, and examples are constantly reviewed to avoid errors, but we cannot warrant full correctness of all content. While using W3Schools, you agree to have read and accepted our terms of use, cookie and privacy policy.

Copyright 1999-2025 by Refsnes Data. All Rights Reserved. W3Schools is Powered by W3.CSS.