i created generic service to crud task, the service use the HttpClient by DI (Dependency Injection), but i need to inform another value in the constructor of the service, how to make this?
because when I define that in the constructor of my class that will consume the CRUD service using DI, there is no way to pass the parameter to the constructor
below is the service
import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { CrudInterface } from "@app/core/crud.interface";
import { environment } from "@env/environment";
import { Observable } from "rxjs/Observable";
@Injectable()
export class CRUD<T> implements CrudInterface<T>{
endpoint: string;
constructor(private http: HttpClient, routeDir: string){
this.endpoint = `${environment.endpoint}/${routeDir}`;
}
getAll(): Observable<T[]> {
return this.http.get<T[]>(`${this.endpoint}`);
}
get(id: number): Observable<T> {
return this.http.get<T>(`${this.endpoint}/${id}`);
}
create(object: T): Observable<T> {
return this.http.post<T>(`${this.endpoint}`, object);
}
update(object: T): Observable<T> {
return this.http.put<T>(`${this.endpoint}`, object);
}
delete(id: number): Observable<any> {
return this.http.delete<T>(`${this.endpoint}/${id}`);
}
}
import { Usuario } from "@app/usuarios/model/usuario";
import { CRUD } from "@app/core/crud.service";
class TestCrudServide {
constructor(
/**
* How to inform the parameter here?
* in this case the endpoint (2nd parameter of the CRUD service)
*/
private crudService: CRUD<Usuario>
){ }
getAll(){
this.crudService.getAll();
}
}
utilizing a solution proposed by Sannon Aragão (thanks) of the concept of factories, i created the service provider for create the instance dynamically
https://angular.io/guide/dependency-injection#factory-providers
export class crudServiceProvider {
static getProvider(routeDir: string) {
return {
provide: CRUD,
deps: [HttpClient],
useFactory: (dep) => {
return new CRUD(dep, routeDir);
}
}
}
}
and in my component
@Component({
selector: 'app-revenda',
templateUrl: './revenda.component.html',
styleUrls: ['./revenda.component.css'],
providers:[ crudServiceProvider.getProvider('/api/revenda') ]
})
export class RevendaComponent implements OnInit {
constructor(
private crudService: CRUD<Revenda>
) { }
ngOnInit() {
// now it's work with the correct path and type!
this.crudService.get(1).subscribe(item => console.log(item));
}
}
Filipe, from the module with you want to provide your service:
{
provide: 'userService1',
deps: [ HttpClient ],
useFactory: (dep1 ) => {
return new UserService( dep1, 'test');
}
}
In the component where you will use the service:
constructor( @Inject('userService1') private userService: UserService ) { }
In the CRUD API you get the parameter as string:
constructor( private http: HttpClient, private s: string) {
console.log(s); // will print 'test'
}
I don't believe you can do this with how dependency injection works. What you can do is create a base CRUD class
export class CRUD<T> implements CrudInterface<T>{
endpoint: string;
constructor(private http: HttpClient, routeDir: string){
this.endpoint = `${environment.endpoint}/${routeDir}`;
}
getAll(): Observable<T[]> {
return this.http.get<T[]>(`${this.endpoint}`);
}
get(id: number): Observable<T> {
return this.http.get<T>(`${this.endpoint}/${id}`);
}
create(object: T): Observable<T> {
return this.http.post<T>(`${this.endpoint}`, object);
}
update(object: T): Observable<T> {
return this.http.put<T>(`${this.endpoint}`, object);
}
delete(id: number): Observable<any> {
return this.http.delete<T>(`${this.endpoint}/${id}`);
}
}
Then make an Injectable service that extends the CRUD class
@Injectable()
export class UserService extends CRUD<Usario> {
constructor(http: HttpClient){
super(http, 'users');
}
}
UserService
is the class that you provide in AppModule and inject into your component. You can see that super is being used to pass in the routeDir
parameter. Here is a stack blitz demoing this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With