http - que - servicios angular 6
¿Cómo escribir un constructor de servicio que requiere parámetros en angular 2? (2)
Tengo un componente que declara el servicio MetricsService. Este servicio requiere tanto el módulo http como dos cadenas que definen el host y la clave de autenticación a usar.
El servicio de métricas es el siguiente:
@Injectable()
export class MetricsService {
constructor(
private http: Http,
public wsAuthKey: string,
public wsHost: string
) {
this.wsAuthKey = wsAuthKey || "blahblahblahblahblahblahblahblah=";
this.wsHost = wsHost || "https://preprod-admin.myservice.ws";
}
El componente que lo usa está escrito de la siguiente manera:
export class DatavizComponent implements OnInit, OnChanges {
constructor(
private zms: MetricsService,
) {
}
Mi pregunta es ¿cómo debo escribir el constructor del componente para que todo funcione, incluyendo pasar el host y la clave (pero no pasar el http)?
Nota: El código como está escrito actualmente no compila.
Para ser más precisos, esperaría que el componente proporcionara datos que dependieran de la aplicación algo como esto:
export class DatavizComponent implements OnInit, OnChanges {
constructor(
private zms = MetricsService("http://myhost.com", "mykey"),
) {
}
Pero si esto funciona, ¿cómo pasar http?
ACTUALIZAR DESPUÉS DE LA SOLUCIÓN PROPUESTA:
export class MetricsService {
constructor(
private http: Http,
@Inject(''wsAuthKey'') @Optional() public wsAuthKey?: string,
@Inject(''wsHost'') @Optional() public wsHost?: string
) {
this.wsAuthKey = wsAuthKey || "blahblah=";
this.wsHost = wsHost || "https://preprod-admin.host.ws";
console.log("MetricsService constructor="
+ " wsAuthKey="+this.wsAuthKey
+ ", wsHost="+this.wsHost
);
}
En el componente:
@Component({
selector: ''dataviz-offers-volumes'',
templateUrl: ''app/dataviz.component.html'',
styleUrls: [''app/dataviz.component.css''],
encapsulation: ViewEncapsulation.None,
providers: [
{provide: ''wsAuthKey'', useValue: ''abc''},
{provide: ''wsHost'', useValue: ''efg''},
],
})
export class DatavizComponent implements OnInit, OnChanges {
@ViewChild(''chart'') private chartContainer: ElementRef;
@Input() private graphId:string;
@Input() private wsAuthKey:string;
@Input() private wsHost:string;
@Input() private maxSamples=12;
constructor(
private zms: MetricsService
) {
}
En el constructor, el registro es el siguiente (el valor no se pasa):
MetricsService constructor= wsAuthKey=blahblah=, wsHost=https://preprod-admin.host.ws
donde debería mostrar ''abc'' y ''efg''.
Pero me pregunto si no hay un problema con el componente que usa dataviz componenet. En este componente, se ha pasado la siguiente información:
@Input() private wsAuthKey:string;
@Input() private wsHost:string;
Como me gustaría que la etiqueta opcionalmente preestablezca el host y la clave:
<h1>dataviz volume</h1>
<div class="chartContainer left" title="Simultaneous offers via dataviz directive">
<dataviz-offers-volumes
id="dataviz-volumes1"
[graphId]="graphId"
[wsAuthKey]="''myauthkey''"
[wsHost]="''http://myhost.com''"
[maxSamples]="123"
>
</dataviz-offers-volumes>
</div>
Esta es una receta común que se describe en esta pregunta en particular. Debe ser un servicio que tenga la configuración:
@Injectable()
export class MetricsConfig {
wsAuthKey = "blahblahblahblahblahblahblahblah=";
wsHost = "https://preprod-admin.myservice.ws";
}
@Injectable()
export class MetricsService {
constructor(
private http: Http,
metricsConfig: MetricsConfig
) {
this.wsAuthKey = metricsConfig.wsAuthKey;
this.wsHost = metricsConfig.wsHost;
}
}
En el caso de que necesite cambiarse, puede anularse o ampliarse para todo el módulo o para un componente particular:
@Component(
...
{ provide: MetricsConfig, useClass: class ExtendedMetricsConfig { ... } }
)
export class DatavizComponent ...
No es necesario que MetricsConfig
una clase en este caso. Puede ser un proveedor de valor OpaqueToken también. Pero una clase se puede extender cómodamente, es más fácil de inyectar y ya proporciona una interfaz para escribir.
Puede hacer que los parámetros sean opcionales agregando @Optional()
(DI) y ?
(TypeScript) y @Inject(somekey)
para valores primitivos que no son compatibles como claves de proveedor
@Injectable()
export class MetricsService {
constructor(
private http: Http,
@Inject(''wsAuthKey'') @Optional() public wsAuthKey?: string,
@Inject(''wsHost'') @Optional() public wsHost?: string
) {
this.wsAuthKey = wsAuthKey || "blahblahblahblahblahblahblahblah=";
this.wsHost = wsHost || "https://preprod-admin.myservice.ws";
}
providers: [
{provide: ''wsAuthKey'', useValue: ''abc''},
{provide: ''wsHost'', useValue: ''efg''},
]
Si se proporcionan, se pasan, de lo contrario se ignoran, pero DI aún puede inyectar MetricsService
.