Reputation: 578
I use Angular: 7.2.10 and when I try to build project for production with command:
ng b --prod
I got error
ERROR in : Can't resolve all parameters for ApiService in ...
I have service with a constructor with 3 params:
constructor(api: string, private _http: HttpClient, private httpUtils: HttpUtilsService) {
this.api = `${api}/api`;
}
Which instantiates by factory defined at app.module.ts:
{
provide: ApiService,
useFactory: apiHost,
deps: [Store, HttpClient, HttpUtilsService]
}
apiHost
export function apiHost(store: Store<RemoteConfig>, http: HttpClient, httpUtils: HttpUtilsService) {
let item: string = localStorage.getItem(environment.apiHost);
//store.pipe(select(backendApiHost), take(1)).subscribe(api => item = api); // Todo not always read val!
//console.log('ss: ' + item);
return new ApiService(item, http, httpUtils);
}
When I use ng build
it works successfully.
Upvotes: 3
Views: 1780
Reputation: 31803
Dependencies are implicitly resolved by examining the metadata emitted by the compiler. This metadata is derived from the types of the parameters.
At runtime, the angular injector inspects that information to determine which dependencies to inject. Specifically, it looks for a registered provider for each corresponding parameter.
Since you haven't registered a provider that maps to the metadata emitted for a parameter of type string
the lookup fails and you receive an error. You could register a provider for that type but it would not be wise to do so given just how broadly strings are used.
However, Angular's dependency injection facilities are not limited to this implicit resolution. Using a combination of the Inject
decorator and InjectionToken
s you can achieve what you wish.
api-token.ts
import {InjectionToken} from '@angular/core';
export const apiToken = new InjectionToken('api', {
providedIn: 'root',
value: 'myapi'
});
Now you can use this token to request that this dependency is resolved for a specific parameter.
data.service.ts
import {Inject, Injectable} from '@angular/core';
import {apiToken} from './api-token';
@Injectable({providedIn: 'root'})
export class DataService {
constructor(@Inject(apiToken) api: string) {}
}
Upvotes: 3
Reputation: 11
i suggest you to remove the api variable from the constructor, pass it on the class methods, use the constructor only to pass injection.
constructor(public _http: HttpClient) { }
getApi(api: string) {
this._http.get(api).toPromise()
}
then extends your api service and pass the uri in the parameter, i suggest you let _http public too, the api host cannot see the private http and these typing can fail a build prod
Upvotes: 0
Reputation: 1741
Angular can't find a provider for api: string
. In fact, you do not inject ApiService, you create it in the code here: return new ApiService(item, http, httpUtils)
, so you don't need to define it in providers.
Upvotes: 0