Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular: How to send a string to an injection service?

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();
    }
}

UPDATE

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));
    }
}
like image 462
Filipe Mansano Avatar asked Jan 02 '18 16:01

Filipe Mansano


2 Answers

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'
}
like image 107
Sannon Aragão Avatar answered Nov 19 '22 22:11

Sannon Aragão


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.

like image 37
LLai Avatar answered Nov 20 '22 00:11

LLai