How to write a service that requires constructor parameters?

I have a component that declares a MetricsService . This service requires an HttpModule plus two HttpModule that specify the host and authorization key to use.

The metrics service works as follows:

 @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"; } 

The component that uses it is written as follows:

 export class DatavizComponent implements OnInit, OnChanges { constructor( private zms: MetricsService, ) { } 

My question is: how do I write a component constructor so that everything works, including passing the host and key (but not sending http)?

Note. Code currently written does not compile.

To be more precise, I expect the component to provide application-specific data like this:

  export class DatavizComponent implements OnInit, OnChanges { constructor( private zms = MetricsService("http://myhost.com", "mykey"), ) { } 

But if it works, how do you pass http?

UPDATE AFTER THE SUGGESTED DECISION:

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

In component:

 @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 ) { } 

In the constructor, the log looks like this (values ​​are not passed):

 MetricsService constructor= wsAuthKey=blahblah=, wsHost=https://preprod-admin.host.ws 

where "abc" and "efg" should be displayed.

But I am wondering if there is a problem with the component using the dataviz data component. The following information was transmitted in this component:

 @Input() private wsAuthKey:string; @Input() private wsHost:string; 

As I would like the tag to further configure the host and key:

  <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> 
+22
constructor angular service components
source share
3 answers

You can make parameters optional by adding @Optional() (DI) and ? (TypeScript) and @Inject(somekey) for primitive values ​​that are not supported as provider keys

 @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'}, ] 

If provided, they are passed; otherwise, they are ignored, but the DI can still enter the MetricsService .

+32
source share

This is a general recipe described in this question in particular. This should be a service that contains the configuration:

 @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; } } 

In the case when it needs to be changed, it can be redefined or extended for the entire module or for a specific component:

 @Component( ... { provide: MetricsConfig, useClass: class ExtendedMetricsConfig { ... } } ) export class DatavizComponent ... 

In this case, there is no need to make the MetricsConfig class. This may be an OpaqueToken provider. But the class can be conveniently extended, it is easier to enter and already provides an interface for input.

+13
source share

From white papers: https://angular.io/guide/dependency-injection-in-action#injectiontoken

Use the @Optional decorator in the constructor:

 export class MyService { constructor( @Optional() public var: type = value ) { } } 
0
source share

All Articles