Service do Angular com erro - resolvido

O erro é após compilar:

ERROR in src/app/core/services/service-principal.service.ts:25:12 - error NG2003: No suitable injection token for parameter ‘base’ of class ‘ServicePrincipalService’.
Found string
public base: string

Classe
import { CrudOperations } from ‘./crudoperations.interface’;

import { HttpClient } from '@angular/common/http';

import {

  ActivatedRoute,

  Router

} from '@angular/router';

import { Injectable } from '@angular/core';

import { CLINICA_MEDICA_API } from './clinicamedica.api';

import pickBy from 'lodash/pickBy';

import isArray from 'lodash/isArray';

import isEmpty from 'lodash/isEmpty';

import isUndefined from 'lodash/isUndefined';

import isNull from 'lodash/isNull';

import trim from 'lodash/trim';

@Injectable({

  providedIn: 'root'

})

export class ServicePrincipalService<T, ID> implements CrudOperations<T, ID> {

  constructor(

    public httpClient: HttpClient,

    public activatedRoute: ActivatedRoute,

    public router: Router,

    public base: string

  ) {}

  public incluir(t: T) {

    return this.httpClient.post(`${CLINICA_MEDICA_API}` + this.base + '/incluir', t);

  }

  public alterar(t: T) {

    return this.httpClient.put(`${CLINICA_MEDICA_API}` + this.base + '/alterar', t);

  }

  public excluir(id: ID) {

    return this.httpClient.delete(`${CLINICA_MEDICA_API}` + this.base + '/excluir/' + id);

  }

  public pesquisar(p: T) {

    const params: any = this.removerUndefinedEmptyNull(p);

    this.updateURLComParametrosDePesquisa(p);

    return this.httpClient.get(`${CLINICA_MEDICA_API}` + this.base + '/pesquisar', { params });

  }

  public buscar(id: ID) {

    return this.httpClient.get(`${CLINICA_MEDICA_API}` + this.base + '/buscar/' + id);

  }

  private removerUndefinedEmptyNull(parameters: any) {

    const res = pickBy(parameters,

      // tslint:disable-next-line:only-arrow-functions

      function(value: any) {

          let definido: boolean;

          if (isArray(value)) {

            definido = !isEmpty(value);

          } else {

            definido = !isUndefined(value) && !isNull(value) && !isEmpty(trim(value));

          }

          return definido;

      }

    );

    return res;

  }

  private updateURLComParametrosDePesquisa(parametros: any) {

    this.router.navigate([], { relativeTo: this.activatedRoute, queryParams: parametros });

  }

}

Boa noite Guilherme,

Eu acho que você terá que criar um InjectionToken. Porque base é uma string, que é um tipo primitivo e o DI não consegue distingui-lo, então esse Token fará o papel de distinguir esse cara q vc precisa dos outros.

Dependency providers - Non-class dependencies

Power of Angular Dependency Injection - Obs.: Esse conteúdo aqui eu confesso que não li com atenção, somente dei uma olhada bem por cima… Mas, eu vi que em algum ponto ele cria diversos token’s e achei que, talvez, seja mais ou menos oq você precisa.

A base é o endereço que o cliente irá acessar o endpoint do servidor.

Exemplos:

  1. se estou na tela de cliente e n servidor o endpoint é cliente, O angular passa isto como parâmetro, para o servico ser acessado.

  2. se estou na tela de venda e n servidor o endpoint é venda, O angular passa isto como parâmetro, para o servico ser acessado.

Não entendi porque está dando erro

Ele dá erro justamente por seu componente ser injetável e o responsável por resolver as injeções de dependências não conseguir resolver uma string.

A documentação do Angular, fala exatamente sobre o que você está tentando fazer:

Not all dependencies are classes. Sometimes you want to inject a string, function, or object.

Apps often define configuration objects with lots of small facts, like the title of the application or the address of a web API endpoint. These configuration objects aren’t always instances of a class. They can be object literals, as shown in the following example.

Eu achei um tópico no Stackoverflow, que aparenta ser algo bem semelhante a sua implementação: Angular: How to send a string to an injection service?

Não sei se ficou claro o motivo pelo qual isso apresenta um erro. Mas, basicamente, é justamente pela sua classe ter a dependência de uma string.

Troquei de string para String e funcionou. Qual é a diferença ?

import { CrudOperations } from './crudoperations.interface';
import { HttpClient } from '@angular/common/http';
import {
  ActivatedRoute,
  Router
} from '@angular/router';
import { Injectable } from '@angular/core';
import { CLINICA_MEDICA_API } from './clinicamedica.api';
import pickBy from 'lodash/pickBy';
import isArray from 'lodash/isArray';
import isEmpty from 'lodash/isEmpty';
import isUndefined from 'lodash/isUndefined';
import isNull from 'lodash/isNull';
import trim from 'lodash/trim';
@Injectable({
  providedIn: 'root'
})
export class ServicePrincipalService<T, ID> implements CrudOperations<T, ID> {
  constructor(
    public httpClient: HttpClient,
    public activatedRoute: ActivatedRoute,
    public router: Router,
    public base: String
  ) {}
  public incluir(t: T) {
    return this.httpClient.post(`${CLINICA_MEDICA_API}` + this.base + '/incluir', t);
  }
  public alterar(t: T) {
    return this.httpClient.put(`${CLINICA_MEDICA_API}` + this.base + '/alterar', t);
  }
  public excluir(id: ID) {
    return this.httpClient.delete(`${CLINICA_MEDICA_API}` + this.base + '/excluir/' + id);
  }
  public pesquisar(p: T) {
    const params: any = this.removerUndefinedEmptyNull(p);
    this.updateURLComParametrosDePesquisa(p);
    return this.httpClient.get(`${CLINICA_MEDICA_API}` + this.base + '/pesquisar', { params });
  }
  public buscar(id: ID) {
    return this.httpClient.get(`${CLINICA_MEDICA_API}` + this.base + '/buscar/' + id);
  }
  private removerUndefinedEmptyNull(parameters: any) {
    const res = pickBy(parameters,
      // tslint:disable-next-line:only-arrow-functions
      function(value: any) {
          let definido: boolean;
          if (isArray(value)) {
            definido = !isEmpty(value);
          } else {
            definido = !isUndefined(value) && !isNull(value) && !isEmpty(trim(value));
          }
          return definido;
      }
    );
    return res;
  }
  private updateURLComParametrosDePesquisa(parametros: any) {
    this.router.navigate([], { relativeTo: this.activatedRoute, queryParams: parametros });
  }
}
1 curtida

string: é um tipo primitivo.
String: é um objeto/tipo por referencia.

Confesso que não sabia da existência dos dois no Angular. Mas, se formos pensar no JAVA, o funcionamento é idêntico.

Essa troca funcionou pois, String é um objeto/uma classe(também conhecido com tipo complexo) e não um tipo primitivo e então o DI consegue identifica-lo e dar a devida tratativa, oque ele não conseguiria fazer usando um tipo primitivo e então, você precisaria de um InjectionToken.

1 curtida