I am trying to use angular v18's provider to provide a new APP_INITIALIZER with dependencies JwtService and Auth Service. here's the code snippet for the logics
export function initAuth(jwtService: JwtService, authService: AuthService) {
return () => (jwtService.getToken() ? authService.getCurrentUser() : EMPTY);
}
export const appConfig: ApplicationConfig = {
providers: [
provideZoneChangeDetection({ eventCoalescing: true }),
provideRouter(routes),
provideHttpClient(withInterceptors([jwtInterceptor])),
{
provide: APP_INITIALIZER,
useFactory: initAuth,
deps: [JwtService, AuthService, HttpClient],
multi: true,
},
],
};
the service for JwtService:
@Injectable({ providedIn: 'root' })
export class JwtService {
getToken(): string {
return window.localStorage['jwtToken'];
}
setToken(token: string): void {
window.localStorage['jwtToken'] = token;
}
destroyToken(): void {
window.localStorage.removeItem('jwtToken');
}
}
the service for AuthService:
@Injectable({ providedIn: 'root' })
export class AuthService {
private apiUrl = environment.apiUrl + '/Auth';
private http = inject(HttpClient);
private router = inject(Router);
private _loggedInUserSubject = new BehaviorSubject<User | null>(null);
currentUser$ = this._loggedInUserSubject.asObservable();
isAuthenticated$ = this.currentUser$.pipe(map((u) => u !== null));
constructor(private jwtService: JwtService) {}
register(credentials: RegisterCredentials): Observable<boolean> {
return this.http
.post<{ username: string }>(this.apiUrl + '/register', credentials)
.pipe(map((user) => user.username === credentials.username));
}
login(credentials: LoginCredentials): Observable<User> {
return this.http
.post<User>(this.apiUrl + '/login', credentials)
.pipe(tap((user) => this.setAuth(user)));
}
logout() {
this.purgeAuth();
this.router.navigate(['']);
}
getCurrentUser() {
return this.http.get<User>(this.apiUrl).pipe(tap((u) => this.setAuth(u)));
}
private setAuth(user: User) {
this._loggedInUserSubject.next(user);
this.jwtService.setToken(user.token);
}
private purgeAuth() {
this._loggedInUserSubject.next(null);
this.jwtService.destroyToken();
}
}
the problem is when I run the application it gave me this error:
as far as I know, this error only occurs when I haven't add a provider for the services. So then I tried to add providers:
export const appConfig: ApplicationConfig = {
providers: [
provideZoneChangeDetection({ eventCoalescing: true }),
provideRouter(routes),
provideHttpClient(withInterceptors([jwtInterceptor])),
JwtService,
AuthService,
{
provide: APP_INITIALIZER,
useFactory: initAuth,
deps: [JwtService, AuthService, HttpClient],
multi: true,
},
],
};
How do I resolve this issue when I try to add dependencies to APP_INITIALIZER in angular 18? Or is there an issue that I am missing at?
EDIT:
After I checked the code, it appears that the AuthService
is the reason for the 'Invalid provider' Error.
After trying out the deps
and providers
by adding some things, and removing it; I figure out that I need to add the dependencies by using inject()
. (not deps
)
const initAuth = () => {
const jwtService = inject(JwtService);
const authService = inject(AuthService);
return () => (jwtService.getToken() ? authService.getCurrentUser() : EMPTY);
};
export const appConfig: ApplicationConfig = {
providers: [
provideZoneChangeDetection({ eventCoalescing: true }),
provideRouter(routes),
provideHttpClient(withInterceptors([jwtInterceptor])),
{
provide: APP_INITIALIZER,
useFactory: initAuth,
multi: true,
},
],
};