I tried to create a generic service to call my API and build is giving me that error :
Can't resolve all parameters for DataService in /ng-app/src/app/services/data.service.ts: (?, [object Object]).
I know i'm not the first who got it but everything I found didn't help.
Here is what i tried :
- Checking if @Injectable was correct
- Not using the barrel
- Using types in constructor params
- Tsconfig.json emitDecoratorMetadata set to true
- All services are registered in the Providers part of the ngModule
I don't know what else I could try to fix it ...
Here is some code :
DataService :
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { catchError } from 'rxjs/operators';
import { Observable } from 'rxjs';
import { AppError } from '../common/validators/app-error';
import { NotFoundError } from '../common/not-found-error';
import { BadRequest } from './../common/bad-request-error';
@Injectable({
providedIn: 'root'
})
export class DataService {
constructor(private url: string, public httpClient: HttpClient) { }
getAll(){
return this.httpClient.get(this.url).pipe(catchError(this.handleError));
}
getOne(ressource){
return this.httpClient.get(this.url + '/' + ressource).pipe(catchError(this.handleError));
}
create(ressource){
return this.httpClient.post(this.url, JSON.stringify(ressource)).pipe(catchError(this.handleError));
}
update(ressource,oldRessource){
return this.httpClient.put(this.url + '/' + oldRessource, JSON.stringify(ressource)).pipe(catchError(this.handleError));
}
delete(ressource){
return this.httpClient.delete(this.url + '/' + ressource).pipe(catchError(this.handleError));
}
public handleError(err: Response){
if (err.status == 400 ){
return Observable.throw(new BadRequest(err));
}
if (err.status == 404) {
return Observable.throw(new NotFoundError());
}
// Return error by default if no specific error
return Observable.throw(new AppError(err));
}
}
A service extending from DataService
import { HttpClient } from '@angular/common/http';
import { DataService } from './data.service';
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class CategorieService extends DataService {
constructor(httpClient: HttpClient) {
super('http://localhost:8081/categories' ,httpClient);
}
}
UPDATE:
I got I have to use a ToketInjection pattern to solve my issue. I also used environments classes to avoid having to setup the base URL at different places.
But I still don't get how i can now change that URL in my DataService for each Services extending from DataService.
Here is some code :
App.module.ts :
...
import { CategorieService } from './services/categorie.service';
import { DataService } from './services/data.service';
import { environment } from 'src/environments/environment';
export function getBaseUrl(): string {
return environment.API_BASE_URL;
}
@NgModule({
declarations: [
...
],
imports: [
...
])
],
providers: [
...
DataService,
CategorieService,
{ provide: 'API_BASE_URL', useFactory: getBaseUrl },
],
bootstrap: [AppComponent]
})
export class AppModule { }
Environement.ts
export const environment = {
production: false,
API_BASE_URL: "http://localhost:8081/",
};
Data.service.ts
import { Injectable, Inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { catchError } from 'rxjs/operators';
import { Observable } from 'rxjs';
import { AppError } from '../common/validators/app-error';
import { NotFoundError } from '../common/not-found-error';
import { BadRequest } from './../common/bad-request-error';
@Injectable({
providedIn: 'root'
})
export class DataService {
//constructor(private url: string, public httpClient: HttpClient) { }
constructor(@Inject('API_BASE_URL') private url, public httpClient: HttpClient) { }
getAll(){
return this.httpClient.get(this.url).pipe(catchError(this.handleError));
}
getOne(ressource){
return this.httpClient.get(this.url + '/' + ressource).pipe(catchError(this.handleError));
}
create(ressource){
return this.httpClient.post(this.url, JSON.stringify(ressource)).pipe(catchError(this.handleError));
}
update(ressource,oldRessource){
return this.httpClient.put(this.url + '/' + oldRessource, JSON.stringify(ressource)).pipe(catchError(this.handleError));
}
delete(ressource){
return this.httpClient.delete(this.url + '/' + ressource).pipe(catchError(this.handleError));
}
public handleError(err: Response){
if (err.status == 400 ){
return Observable.throw(new BadRequest(err));
}
if (err.status == 404) {
return Observable.throw(new NotFoundError());
}
// Return error by default if no specific error
return Observable.throw(new AppError(err));
}
}
I would like to add some parameters to my base API URL the same way i tried to do it before to be able to reach specific parts of my API but i don't get how to do that with TokenInjection.