I'm learning angular through course and currently I'm learning about Interceptors. The angular version in the course isn't 17 but the one which I'm using in my local is. So, after 1st trying to implement interceptor via class didn't work as intercept didn't happen.
When I looked into net and saw that we can make an intercept constant and that we can provide it in app.config.ts, even after doing that it didn't work. So I'm literally stuck. Any help would be appreciated. Here are my files:
app.component.ts
import { Component, OnInit, OnDestroy } from '@angular/core';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { CommonModule } from '@angular/common';
import { RouterOutlet } from '@angular/router';
import { FormsModule } from '@angular/forms';
import { Post } from './Post';
import { PostService } from './post-service';
import { Subscription } from 'rxjs';
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule, RouterOutlet, HttpClientModule, FormsModule],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent implements OnInit, OnDestroy {
title = 'http-request';
postJsonUrl: string = 'https://ng-complete-guide-d77e5-default-rtdb.firebaseio.com/posts.json';
loadedPosts: Post[] = [];
isFetching = false;
error = null;
errorSubscription: Subscription;
constructor(private http: HttpClient, private postService: PostService) { }
ngOnInit() {
this.isFetching = true;
this.errorSubscription = this.postService.error.subscribe(errorMessage => {
this.error = errorMessage;
});
//things metioned in ngOnInit will load once the application is loaded
//subscribing here, heavy-lifiting in service class
this.postService.fetchPosts().subscribe(posts => {
this.isFetching = false;
this.loadedPosts = posts;
console.log(posts);
}, error => {
this.isFetching = false;
this.error = error.message;
console.log(error);
});
}
onCreatePost(postData: Post) {
this.postService.createAndStorePost(postData.title, postData.content);
}
onFetchPosts() {
this.isFetching = true;
// Send Http request
//subscribing here, heavy-lifiting in service class
this.postService.fetchPosts().subscribe(posts => {
this.isFetching = false;
this.loadedPosts = posts;
}, error => {
this.isFetching = false;
this.error = error.message;
});
}
onClearPosts() {
this.postService.deletePosts().subscribe(() => {
this.isFetching = false;
this.loadedPosts = [];
})
}
onErrorHandling() {
this.error = false;
this.isFetching = false;
}
ngOnDestroy(): void {
this.errorSubscription.unsubscribe();
}
}
auth-interceptor-service.interceptor.ts
import { HttpInterceptorFn } from '@angular/common/http';
export const authInterceptorServiceInterceptor: HttpInterceptorFn = (req, next) => {
console.log("Request is on its way");
return next(req);
};
app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import { provideHttpClient, withInterceptors, withInterceptorsFromDi } from '@angular/common/http';
import { authInterceptorServiceInterceptor } from './auth-interceptor-service.interceptor';
export const appConfig: ApplicationConfig = {
providers: [provideRouter(routes), provideHttpClient(withInterceptors([
authInterceptorServiceInterceptor
]))]
};
post-service.ts
import { HttpClient, HttpEventType, HttpHeaders, HttpParams } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { Post } from "./Post";
import { Subject, map, tap } from "rxjs";
//either provide it this way or in app.module.ts if exists
@Injectable({ providedIn: 'root' })
export class PostService {
postJsonUrl: string = 'https://ng-complete-guide-d77e5-default-rtdb.firebaseio.com/posts.json';
error = new Subject<string>();
constructor(private http: HttpClient) { }
createAndStorePost(title: string, content: string) {
const postData: Post = { title: title, content: content };
// Send Http request
console.log(postData);
this.http
.post(
this.postJsonUrl, //.json for firebase
postData,
{
observe: 'response',
//response will show the whole body
responseType : 'json'
}
)
.subscribe(responseData => {
console.log(responseData);
}, error => {
this.error.next(error.message);
});
//angular uses observables for http requests. If not subscribed, it discards that particular
//http as not important, hence no result. So do subscribe to http requests.
}
fetchPosts() {
let searchParams = new HttpParams();
searchParams = searchParams.append('print', 'pretty');
searchParams = searchParams.append('custom', 'key');
return this.http.get<{ [key: string]: Post }>(this.postJsonUrl,
{
//we can send header
headers: new HttpHeaders({'Custom-Header' : 'Hello'}),
//and params too....... two paramters
params : searchParams
})
//.pipe() does intermediate operation and returns a new obserable which can be subscribed
.pipe(map(responseData => {
const postsArray: Post[] = [];
for (const key in responseData) {
if (responseData.hasOwnProperty(key)) {
postsArray.push({ ...responseData[key], id: key });
console.log(postsArray);
}
}
return postsArray;
}));
//here we funneled our object from the pbject and added them in array
//we gonna sibscribe in component page
}
deletePosts(){
return this.http.delete(this.postJsonUrl, {
observe : 'events',
responseType : 'json'
}).pipe(tap(event => {
if(event.type == HttpEventType.Sent){
//...
}
if(event.type === HttpEventType.Response){
console.log(event);
}
}));
}
}
Post.ts
export interface Post {
title: string;
content: string;
id?: string;
}
I tried all solutions like: Adding @SkipSelf, checking if HttpClientModule is imported only once. But nothing worked.
Before Angular 15, there were class interceptors in Angular that needed to be registered in the app.module under providers. However, starting from version 15, functional interceptors are used, which, in Angular 17, should be registered in the app.config.ts
export const appConfig: ApplicationConfig = { providers: [ provideRouter(routes), provideHttpClient(withInterceptors([YourInterceptor])), ]};
A really nice articole about: https://medium.com/@santosant/angular-functional-interceptors-3a2a2e71cdef